private void AcceptLoop() { while (!this.thread.ShouldExit) { try { TcpClient client = this.listener.AcceptTcpClient(); TcpServerConnection connection = this.server.AcceptClient(client, this.lspHookedLocalEP, this.lspHooked); this.server.AddEvent(connection.VisitorCreateTransportEvent(EventType.Connected, client)); connection.Start(); } // user stopped the listener. catch (SocketException) { } // user is dispoing the listener. catch (Exception ex) { this.server.AddEvent(new TransportEvent(EventType.Exception, null, ex)); } } }
/// <summary> /// accept the connected TcpClient. /// </summary> /// <param name="client"> /// a TcpClient object that specifies the connected tcp client. /// </param> /// <param name="lspHookedLocalEP"> /// an IPEndPoint object that specifies the local endpoint.<para/> /// if LSP hooked, return the required local endpoint.<para/> /// otherwise, return the actual listened local endpoint. /// </param> /// <param name="isLspHooked"> /// a bool value that indicates whether lsp hooked the transport. /// </param> /// <returns> /// a TcpServerConnection that specifies the constructed client. /// </returns> /// <exception cref="ArgumentNullException"> /// thrown when client is null. /// </exception> /// <exception cref="InvalidOperationException"> /// thrown when invalid connected tcp client. /// </exception> /// <exception cref="InvalidOperationException"> /// thrown when invalid endpoint of connected tcp client /// </exception> /// <exception cref="InvalidOperationException"> /// thrown when the client specified by endpoint exists /// </exception> internal TcpServerConnection AcceptClient(TcpClient client, IPEndPoint lspHookedLocalEP, bool isLspHooked) { if (client == null) { throw new ArgumentNullException("client"); } TcpServerConnection connection = new TcpServerConnection(client, this, lspHookedLocalEP, isLspHooked); IPEndPoint endpoint = connection.RemoteEndPoint; if (endpoint == null) { throw new InvalidOperationException("invalid endpoint of connected tcp client"); } //Whether this is a fowarder channel if (connection.IsAForwarderChannel) { //Get the primary channel TcpServerConnection primaryChannel = this.connections[endpoint]; if (primaryChannel == null) { throw new InvalidOperationException("A forward channel is found but no primary channel is found"); } primaryChannel.AssociatedForwarderChannel = connection; } else { if (this.connections.ContainsKey(endpoint)) { throw new InvalidOperationException("the client specified by endpoint exists"); } this.connections.Add(endpoint, connection); } return connection; }
/// <summary> /// expect packet from transport.<para/> /// the transport must be a TcpServer or NetbiosServer. /// </summary> /// <param name="host"> /// an IVisitorGetAnyPacket interface that specifies the host of visitor. /// </param> /// <param name="eventQueue"> /// a SyncFilterQueue<TransportEvent> that specifies the queue to store event. /// </param> /// <param name="sequence"> /// a DataSequence object that manages the sequence information of multiple clients. /// </param> /// <param name="timeout"> /// a TimeSpan object that indicates the timeout to expect event. /// </param> /// <param name="skipEvent"> /// a bool value that specifies whether skip the event.<para/> /// if true, just wait for packet coming; otherwise, both data and event will return. /// </param> /// <returns> /// a StackPacket object that specifies the received packet.<para/> /// if all buffer is closed in this while, and required to return if all buffer is closed, return null.<para/> /// otherwise never return null, if no packets coming in timespan, throw exception. /// </returns> public static TransportEvent Visit( IVisitorGetAnyData host, SyncFilterQueue <TransportEvent> eventQueue, DataSequence sequence, TimeSpan timeout, bool skipEvent) { // the end time for operation. DateTime endTime = DateTime.Now + timeout; TimeSpan currentTimeout = timeout; while (true) { sequence.Reset(); // try to decode packet from all clients in sequence. while (true) { SequenceItem item = sequence.Next(TimeSpan.MinValue); // all item in the sequences returned if (item == null) { break; } TransportEvent transportEvent = item.Source as TransportEvent; // if event arrived and donot skip the event, return the event directly. if (transportEvent != null) { if (skipEvent) { continue; } sequence.Remove(transportEvent); Utility.Remove(eventQueue, transportEvent); return(transportEvent); } object remoteEndPoint; object localEndPoint; host.VisitorGetEndPoint(item.Source, out remoteEndPoint, out localEndPoint); int consumedLength = 0; StackPacket packet = null; try { // set timeout to zero, must not wait for more data. // if timeout, process next. packet = host.VisitorDecodePackets( item.Source, remoteEndPoint, localEndPoint, out consumedLength); // remove the sequence information in data sequence. sequence.Consume(item.Source, consumedLength); if (packet != null) { TcpServerConnection connection = item.Source as TcpServerConnection; if (connection != null) { return(connection.VisitorCreateTransportEvent(EventType.ReceivedPacket, packet)); } else { return(new TransportEvent(EventType.ReceivedPacket, remoteEndPoint, localEndPoint, packet)); } } } // skip timeout of any host. catch (TimeoutException) { } } // waiting for next data coming. sequence.Next(currentTimeout); currentTimeout = endTime - DateTime.Now; } }