/// <summary>
        /// to receive bytes from connection.<para/>
        /// the transport must be a TcpServer, UdpClient or UdpServer.
        /// </summary>
        /// <param name="timeout">
        /// a TimeSpan object that specifies the timeout for this operation.
        /// </param>
        /// <param name="maxCount">
        /// an int value that specifies the maximum count of expect bytes.
        /// </param>
        /// <param name="remoteEndPoint">
        /// an object that indicates the connection received data from.
        /// </param>
        /// <returns>
        /// a bytes array that contains the received bytes.
        /// </returns>
        /// <exception cref="ObjectDisposedException">
        /// thrown when this object is disposed.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// thrown when udp client is not start, must invoke Start() first.
        /// </exception>
        public byte[] ExpectBytes(TimeSpan timeout, int maxCount, out object remoteEndPoint)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("UdpClientTransport");
            }

            if (this.udpClient == null)
            {
                throw new InvalidOperationException("udp client is not start, must invoke Start() first.");
            }

            UdpReceivedBytes bytes = this.buffer.Dequeue(timeout);

            remoteEndPoint = bytes.RemoteEndPoint;

            // exception event arrived
            if (bytes.Packet == null)
            {
                // do not remove it.
                this.buffer.Enqueue(bytes);

                throw new InvalidOperationException("exception arrived when expect bytes from udp.");
            }

            return(bytes.Packet);
        }
예제 #2
0
        /// <summary>
        /// filter the disconnected event from specified client.
        /// </summary>
        /// <param name="obj">
        /// a UdpReceivedBytes object that contains the event to filt.
        /// </param>
        /// <returns>
        /// if the received data is from the specified local endpoint, return true; otherwise, false.
        /// </returns>
        public bool FilterUdpPacketOrBytes(UdpReceivedBytes obj)
        {
            if (obj == null)
            {
                return(false);
            }

            return(this.CompareUdpPacketOrBytes(obj.LocalEndPoint));
        }
        /// <summary>
        /// get packet from packet cache or decode from buffer.
        /// </summary>
        /// <param name="timeout">
        /// a TimeSpan object that specifies the timeout
        /// </param>
        /// <param name="removeEvent">
        /// a bool value that indicates whether need to remove the event from buffer.
        /// </param>
        /// <param name="remoteEndPoint">
        /// an object that specifies the remote endpoint.
        /// </param>
        /// <returns>
        /// a StackPacket object that contains the decoded packet.
        /// </returns>
        private StackPacket GetPacket(TimeSpan timeout, bool removeEvent, out object remoteEndPoint)
        {
            // get the packet in packet list.
            IPEndPointStackPacket packet = Utility.GetOne <IPEndPointStackPacket>(this.packetCache, null);

            if (packet != null)
            {
                remoteEndPoint = packet.RemoteEndPoint;

                return(packet.Packet);
            }

            UdpReceivedBytes bytes = this.buffer.Dequeue(timeout);

            remoteEndPoint = bytes.RemoteEndPoint;

            // exception event arrived
            if (bytes.Packet == null)
            {
                if (!removeEvent)
                {
                    this.buffer.Enqueue(bytes);
                }

                InvalidOperationException exc =
                    new InvalidOperationException("exception arrived when expect packet from udp.");

                // identify this exception.
                exc.Data.Add(exc.GetType().Name, true);

                throw exc;
            }

            // decode packets using data in buffer.
            int consumedLength = 0;
            int expectedLength = 0;

            StackPacket[] packets = this.decoder(remoteEndPoint, bytes.Packet, out consumedLength, out expectedLength);

            // if no packet, drop the recieved data and continue.
            if (packets == null || packets.Length == 0)
            {
                throw new InvalidOperationException("udp client failed to decode udp packet");
            }

            // if packet arrived, add to packet list, and return the first.
            foreach (StackPacket item in packets)
            {
                this.packetCache.Enqueue(
                    new IPEndPointStackPacket(item, bytes.RemoteEndPoint, bytes.LocalEndPoint));
            }

            // set timeout to zero. when packet is decoded, must not wait.
            return(GetPacket(new TimeSpan(), removeEvent, out remoteEndPoint));
        }
        /// <summary>
        /// expect packet from transport.<para/>
        /// the transport must be a TcpServer, UdpClient or UdpServer.
        /// </summary>
        /// <param name="endpoint">
        /// an IPEndPoint object that specifies the endpoint to get packet.
        /// </param>
        /// <param name="timeout">
        /// a TimeSpan object that indicates the timeout to expect event.
        /// </param>
        /// <param name="removeEvent">
        /// a bool value that indicates whether need to remove the event from buffer.
        /// </param>
        /// <param name="remoteEndPoint">
        /// an object that specifies the remote endpoint expected packet.
        /// </param>
        /// <param name="localEndPoint">
        /// an object that indicates the local endpoint received packet at.
        /// </param>
        /// <returns>
        /// a StackPacket object that specifies the received packet.<para/>
        /// never return null, if no packets, throw exception.
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// thrown when udp server failed to decode udp packet
        /// </exception>
        private StackPacket GetFilteredPacket(
            IPEndPoint endpoint, TimeSpan timeout, bool removeEvent,
            out object remoteEndPoint, out object localEndPoint)
        {
            // generate the filter.
            Filter <IPEndPointStackPacket> packetFilter = null;
            Filter <UdpReceivedBytes>      bytesFilter  = null;

            if (endpoint != null)
            {
                packetFilter = new TransportFilter(endpoint).FilterUdpPacketOrBytes;
                bytesFilter  = new TransportFilter(endpoint).FilterUdpPacketOrBytes;
            }

            // get the packet in packet list.
            IPEndPointStackPacket packet = Utility.GetOne <IPEndPointStackPacket>(this.packetCache, packetFilter);

            if (packet != null)
            {
                remoteEndPoint = packet.RemoteEndPoint;
                localEndPoint  = packet.LocalEndPoint;

                return(packet.Packet);
            }

            UdpReceivedBytes bytes = this.GetUdpBytes(
                bytesFilter, timeout, removeEvent, out remoteEndPoint, out localEndPoint);

            // decode packets using data in buffer.
            int consumedLength = 0;
            int expectedLength = 0;

            StackPacket[] packets = this.decoder(remoteEndPoint, bytes.Packet, out consumedLength, out expectedLength);

            // if no packet, drop the recieved data and continue.
            if (packets == null || packets.Length == 0)
            {
                throw new InvalidOperationException("udp server failed to decode udp packet");
            }

            // if packet arrived, add to packet list, and return the first.
            foreach (StackPacket item in packets)
            {
                this.packetCache.Enqueue(
                    new IPEndPointStackPacket(item, bytes.RemoteEndPoint, bytes.LocalEndPoint));
            }

            // set timeout to zero. when packet is decoded, must not wait.
            return(GetFilteredPacket(endpoint, new TimeSpan(), removeEvent, out remoteEndPoint, out localEndPoint));
        }
        /// <summary>
        /// expect packet from transport.<para/>
        /// the transport must be a TcpServer, UdpClient or UdpServer.
        /// </summary>
        /// <param name="filter">
        /// a Filter delegate that specifies the endpoint to receive data.<para/>
        /// if null, receive data from any endpoint.
        /// </param>
        /// <param name="timeout">
        /// a TimeSpan object that indicates the timeout to expect event.
        /// </param>
        /// <param name="removeEvent">
        /// a bool value that indicates whether need to remove the event from buffer.
        /// </param>
        /// <param name="remoteEndPoint">
        /// an object that specifies the remote endpoint expected packet.
        /// </param>
        /// <param name="localEndPoint">
        /// an object that indicates the local endpoint received packet at.
        /// </param>
        /// <returns>
        /// a UdpReceivedBytes object that specifies the received udp packet.<para/>
        /// never return null, if no packets, throw exception.
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// thrown when the received udp packet is invalid
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// thrown when exception arrived when expect bytes from udp client.
        /// </exception>
        private UdpReceivedBytes GetUdpBytes(
            Filter <UdpReceivedBytes> filter, TimeSpan timeout, bool removeEvent,
            out object remoteEndPoint, out object localEndPoint)
        {
            UdpReceivedBytes bytes = null;

            if (filter == null)
            {
                bytes = this.buffer.Dequeue(timeout);
            }
            else
            {
                bytes = this.buffer.Dequeue(timeout, filter);
            }

            if (bytes == null)
            {
                throw new InvalidOperationException("the received udp packet is invalid");
            }

            remoteEndPoint = bytes.RemoteEndPoint;
            localEndPoint  = bytes.LocalEndPoint;

            // exception event arrived
            if (bytes.Packet == null)
            {
                if (!removeEvent)
                {
                    this.buffer.Enqueue(bytes);
                }

                InvalidOperationException exc =
                    new InvalidOperationException("exception arrived when expect bytes from udp client.");

                // identify this exception.
                exc.Data.Add(exc.GetType().Name, true);

                throw exc;
            }

            return(bytes);
        }