/// <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="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);
        }