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