private void HandleGatewayTunnelRequest( II2NPHeader msg, IEnumerable <AesEGBuildRequestRecord> records, EGBuildRequestRecord myrec, BuildRequestRecord drec) { var tunnel = new GatewayTunnel(drec); var replykey = drec.ReplyKey.Key.Clone(); var replyiv = drec.ReplyIV.Clone(); tunnel.EstablishedTime.SetNow(); var doaccept = AcceptingTunnels(drec); var response = doaccept ? BuildResponseRecord.RequestResponse.Accept : BuildResponseRecord.DefaultErrorReply; Logging.LogDebug(() => string.Format("HandleGatewayTunnelRequest {3}: {0} Gateway tunnel request: {1} for tunnel id {2}.", tunnel.Destination.Id32Short, response, tunnel.ReceiveTunnelId, tunnel.TunnelDebugTrace)); TunnelProvider.UpdateTunnelBuildReply(records, myrec, replykey, replyiv, response); if (response == BuildResponseRecord.RequestResponse.Accept) { AddTunnel(tunnel); TunnelMgr.AddExternalTunnel(tunnel); AcceptedTunnelBuildRequest(drec); } TransportProvider.Send(tunnel.Destination, msg.Message); }
private void HandleEndpointTunnelRequest( II2NPHeader msg, IEnumerable <AesEGBuildRequestRecord> records, EGBuildRequestRecord myrec, BuildRequestRecord drec) { var tunnel = new EndpointTunnel(drec); var replykey = drec.ReplyKey.Key.Clone(); var replyiv = drec.ReplyIV.Clone(); tunnel.EstablishedTime.SetNow(); var doaccept = AcceptingTunnels(drec); var response = doaccept ? BuildResponseRecord.RequestResponse.Accept : BuildResponseRecord.DefaultErrorReply; DebugUtils.LogDebug(() => string.Format("HandleEndpointTunnelRequest {3}: {0} Endpoint tunnel request: {1} for tunnel id {2}.", tunnel.Destination.Id32Short, response, tunnel.ReceiveTunnelId, tunnel.TunnelDebugTrace)); TunnelProvider.UpdateTunnelBuildReply(records, myrec, replykey, replyiv, response); var responsemessage = new VariableTunnelBuildReplyMessage(records.Select(r => new BuildResponseRecord(r))); var buildreplymsg = new TunnelGatewayMessage(responsemessage.GetHeader16(tunnel.ResponseMessageId), tunnel.ResponseTunnelId); if (response == BuildResponseRecord.RequestResponse.Accept) { AddTunnel(tunnel); TunnelMgr.AddExternalTunnel(tunnel); AcceptedTunnelBuildRequest(drec); } TransportProvider.Send(tunnel.Destination, buildreplymsg); }
/* * Exploration * * Exploration is a special form of netdb lookup, where a router attempts to learn about new routers. * It does this by sending a floodfill router a I2NP DatabaseLookupMessage, looking for a random key. * As this lookup will fail, the floodfill would normally respond with a I2NP DatabaseSearchReplyMessage * containing hashes of floodfill routers close to the key. This would not be helpful, as the requesting * router probably already knows those floodfills, and it would be impractical to add ALL floodfill * routers to the "don't include" field of the lookup. For an exploration query, the requesting router * adds a router hash of all zeros to the "don't include" field of the DatabaseLookupMessage. * * The floodfill will then respond only with non-floodfill routers close to the requested key. * * https://geti2p.net/en/docs/how/network-database * * 11 => exploration lookup, return DatabaseSearchReplyMessage * containing non-floodfill routers only (replaces an * excludedPeer of all zeroes) * https://geti2p.net/spec/i2np#databaselookup */ void ExplorationRouterLookup() { I2PIdentHash ident = new I2PIdentHash(true); var ff = NetDb.Inst.GetClosestFloodfill(ident, 10, null, false) .Shuffle() .Take(DatabaseLookupSelectFloodfillCount) .ToArray(); foreach (var oneff in ff) { var msg = new DatabaseLookupMessage( ident, RouterContext.Inst.MyRouterIdentity.IdentHash, DatabaseLookupMessage.LookupTypes.Exploration, new I2PIdentHash[] { new I2PIdentHash(false) }); #if LOG_ALL_IDENT_LOOKUPS Logging.Log("IdentResolver: Random router lookup " + ident.Id32Short + " sent to " + oneff.Id32Short); #endif try { TransportProvider.Send(oneff, msg); } catch (Exception ex) { Logging.Log(ex); } } }
private bool HandleTunnelData(IEnumerable <TunnelDataMessage> msgs) { EncryptTunnelMessages(msgs); #if LOG_ALL_TUNNEL_TRANSFER LogDataSent.Log(() => "PassthroughTunnel " + Destination.Id32Short + " TunnelData sent."); #endif var dropped = 0; foreach (var one in msgs) { if (Limiter.DropMessage()) { ++dropped; continue; } one.TunnelId = SendTunnelId; Bandwidth.DataSent(one.Payload.Length); TransportProvider.Send(Destination, one); } #if LOG_ALL_TUNNEL_TRANSFER if (dropped > 0) { DebugUtils.LogDebug(() => string.Format("{0} bandwidth limit. {1} dropped messages. {2}", this, dropped, Bandwidth)); } #endif return(true); }
private void HandleTunnelData(List <TunnelDataMessage> msgs) { DecryptTunnelMessages(msgs); var newmsgs = Reassembler.Process(msgs); foreach (var one in newmsgs) { if (one.GetType() == typeof(TunnelMessageLocal)) { DebugUtils.Log("InboundTunnel " + TunnelDebugTrace + " TunnelData distributed Local :\r\n" + one.Header.ToString()); MessageReceived(((TunnelMessageLocal)one).Header); } else if (one.GetType() == typeof(TunnelMessageRouter)) { DebugUtils.Log("InboundTunnel " + TunnelDebugTrace + " TunnelData distributed Router :\r\n" + one.Header.ToString()); TransportProvider.Send(((TunnelMessageRouter)one).Destination, one.Header.Message); } else if (one.GetType() == typeof(TunnelMessageTunnel)) { var tone = (TunnelMessageTunnel)one; DebugUtils.Log("InboundTunnel " + TunnelDebugTrace + " TunnelData distributed Tunnel :\r\n" + one.Header.ToString()); var gwmsg = new TunnelGatewayMessage(tone.Header, tone.Tunnel); TransportProvider.Send(tone.Destination, gwmsg); } else { DebugUtils.LogWarning("InboundTunnel " + TunnelDebugTrace + " TunnelData without routing rules:\r\n" + one.Header.ToString()); } } }
public T GetTransportProvider <T>() where T : TransportProvider { T t; List <TransportProvider> .Enumerator enumerator = this.transportProviders.GetEnumerator(); try { while (enumerator.MoveNext()) { TransportProvider current = enumerator.Current; if (!(current is T)) { continue; } t = (T)current; return(t); } return(default(T)); } finally { ((IDisposable)enumerator).Dispose(); } return(t); }
public bool TryGetTransportProvider(ProtocolHeader header, out TransportProvider provider) { bool flag; if (this.TransportProviders.Count == 0) { throw new ArgumentException("TransportProviders"); } provider = null; using (IEnumerator <TransportProvider> enumerator = this.TransportProviders.GetEnumerator()) { while (enumerator.MoveNext()) { TransportProvider current = enumerator.Current; if (current.ProtocolId != header.ProtocolId) { continue; } provider = current; flag = true; return(flag); } provider = this.GetDefaultProvider(); return(false); } return(flag); }
private bool HandleReceiveQueue() { II2NPHeader16[] messages = null; lock ( ReceiveQueue ) { if (ReceiveQueue.Count == 0) { return(true); } var msgs = new List <II2NPHeader16>(); int dropped = 0; foreach (var msg in ReceiveQueue) { if (Limiter.DropMessage()) { ++dropped; continue; } msgs.Add((II2NPHeader16)msg); } messages = msgs.ToArray(); #if LOG_ALL_TUNNEL_TRANSFER if (dropped > 0) { if (FilterMessageTypes.Update(new HashedItemGroup(Destination, 0x63e9))) { Logging.LogDebug(() => string.Format("{0} bandwidth limit. {1} dropped messages. {2}", this, dropped, Bandwidth)); } } #endif } if (messages == null || messages.Length == 0) { return(true); } var tdata = TunnelDataMessage.MakeFragments(messages.Select(msg => (TunnelMessage)(new TunnelMessageLocal(msg))), SendTunnelId); EncryptTunnelMessages(tdata); #if LOG_ALL_TUNNEL_TRANSFER if (FilterMessageTypes.Update(new HashedItemGroup(Destination, 0x17f3))) { Logging.Log("GatewayTunnel " + Destination.Id32Short + ": TunnelData sent."); } #endif foreach (var tdmsg in tdata) { Bandwidth.DataSent(tdmsg.Payload.Length); TransportProvider.Send(Destination, tdmsg); } return(true); }
/// <summary> /// Initializes a new instance of the <see cref="BoardingJourneyCard" /> class. /// </summary> protected BoardingJourneyCard() { id = "000000"; transport = null; seat = ""; departureDate = DateTime.Now; arrivalDate = DateTime.Now; transportProvider = null; owner = null; denied = false; valid = false; }
/// <summary> /// Initializes a new instance of the <see cref="BoardingJourneyCard" /> class. /// </summary> /// <param name="id">The id.</param> /// <param name="seat">The seat.</param> /// <param name="departureDate">The departure date.</param> /// <param name="arrivalDate">The arrival date.</param> /// <param name="client">The client.</param> /// <param name="transportProvider">The transport company.</param> protected BoardingJourneyCard(String id, String seat, DateTime departureDate, DateTime arrivalDate, BoardingJourneyCardOwner client, TransportProvider transportProvider) { this.id = id; this.seat = seat; this.departureDate = departureDate; this.arrivalDate = arrivalDate; this.owner = client; this.transportProvider = transportProvider; denied = false; valid = false; }
public RpcServer() { _cacheContainer = new ServerCacheContainer(); _localCacheService = new LocalCacheService(_section, _cacheContainer); _serializer = SerializerFactory.GetSerializer(_section.Serializer); _transportProvider = new TransportProvider(_cacheContainer, _serializer); _acceptor = _transportProvider.GetAcceptor(); }
// Constructor public TransportClient(TransportProvider provider) { #region Contracts if (provider == null) { throw new ArgumentNullException(); } #endregion // Default _provider = provider; }
public ProtocolHeader GetSupportedHeader(ProtocolHeader requestedHeader) { AmqpVersion amqpVersion; TransportProvider transportProvider = null; if (!this.TryGetTransportProvider(requestedHeader, out transportProvider)) { return(this.GetDefaultHeader()); } if (transportProvider.TryGetVersion(requestedHeader.Version, out amqpVersion)) { return(requestedHeader); } return(new ProtocolHeader(transportProvider.ProtocolId, transportProvider.DefaultVersion)); }
private void SendUpdate(I2PIdentHash ff, uint token) { // If greater than zero, a DeliveryStatusMessage // is requested with the Message ID set to the value of the Reply Token. // A floodfill router is also expected to flood the data to the closest floodfill peers // if the token is greater than zero. // https://geti2p.net/spec/i2np#databasestore var ds = new DatabaseStoreMessage( RouterContext.Inst.MyRouterInfo, token, RouterContext.Inst.MyRouterInfo.Identity.IdentHash, 0); TransportProvider.Send(ff, ds); }
public AbstractConsumer(IMessageHandler handler, ClientCacheContainer cacheContainer, ILoadBalance loadBalance, ISerializer serializer) { _handler = handler; _handler.Recieved += Message_Recieved; _cacheContainer = cacheContainer; _loadBalance = loadBalance; _serializer = serializer; _transportProvider = new TransportProvider(_cacheContainer, serializer); _connector = _transportProvider.GetConnector(_handler); }
public FluentRecordBase AddTransportProvider( ) { // // DEPENDENCIES _servTP = container.GetRequiredService <ITransportProvidersService>(); // // ARRANGE _tp = (TransportProvider)Records.transportProvider.Clone(); // // ACT _servTP.Create(_tp, _user); return(this); }
private void HandleEndpointTunnelRequest( II2NPHeader msg, TunnelBuildRequestDecrypt decrypt) { var config = new TunnelConfig( TunnelConfig.TunnelDirection.Inbound, TunnelConfig.TunnelPool.External, new TunnelInfo(new List <HopInfo> { new HopInfo( RouterContext.Inst.MyRouterIdentity, new I2PTunnelId()) } )); var tunnel = new EndpointTunnel(this, config, decrypt.Decrypted); tunnel.EstablishedTime.SetNow(); var doaccept = AcceptingTunnels(decrypt.Decrypted); var response = doaccept ? BuildResponseRecord.RequestResponse.Accept : BuildResponseRecord.DefaultErrorReply; Logging.LogDebug($"HandleEndpointTunnelRequest {tunnel.TunnelDebugTrace}: " + $"{tunnel.Destination.Id32Short} Endpoint tunnel request: {response} " + $"for tunnel id {tunnel.ReceiveTunnelId}."); var newrecords = decrypt.CreateTunnelBuildReplyRecords(response); var responsemessage = new VariableTunnelBuildReplyMessage( newrecords.Select(r => new BuildResponseRecord(r)), tunnel.ResponseMessageId); var buildreplymsg = new TunnelGatewayMessage( responsemessage, tunnel.ResponseTunnelId); if (response == BuildResponseRecord.RequestResponse.Accept) { RunningEndpointTunnels[tunnel] = 1; TunnelMgr.AddTunnel(tunnel); AcceptedTunnelBuildRequest(decrypt.Decrypted); } TransportProvider.Send(tunnel.Destination, buildreplymsg); }
// Methods public void Attach(TransportHandler handler) { #region Contracts if (handler == null) { throw new ArgumentNullException(); } #endregion // Attach handler.Attach(_provider); // Provider _provider = handler; }
private TransportProvider GetDefaultProvider() { TransportProvider transportProvider = null; if (this.RequireSecureTransport) { transportProvider = this.GetTransportProvider <TlsTransportProvider>(); } else if (this.AllowAnonymousConnection) { transportProvider = this.GetTransportProvider <AmqpTransportProvider>(); } else { transportProvider = this.GetTransportProvider <SaslTransportProvider>(); } return(transportProvider); }
public void TestInitialize() { _savedTransportProvider = new TransportProvider(); _fakeTransportProvider = new TransportProvider() { active = true, defaultAttribute = true, ID = 1, key = "asdf", text_EN = "asdf" }; _fakeTransportProviders = new List <TransportProvider>(); _fakeTransportProviders.Add(new TransportProvider() { active = true, defaultAttribute = true, ID = 2, key = "dth", text_EN = "wert" }); _transportProvidersServ = new Mock <ITransportProvidersService>(); _transportProvidersServ.Setup(s => s.GetMany(It.IsAny <Func <TransportProvider, bool> >())) .Returns(_fakeTransportProviders.AsQueryable); _transportProvidersServ.Setup(s => s.Get(1)) .Returns(_fakeTransportProvider); _transportProvidersServ.Setup(s => s.Get(1000)) .Returns((TransportProvider)null); _transportProvidersServ.Setup(s => s.Create(It.IsAny <TransportProvider>(), It.IsAny <string>())) .Returns(_fakeTransportProvider); _transportProvidersServ.Setup(s => s.Save(It.Is <TransportProvider>(r => r.ID == 1), It.IsAny <string>())) .Callback((TransportProvider tp, string user) => _savedTransportProvider = tp); _transportProvidersServ.Setup(s => s.Delete(1, It.IsAny <string>())) .Verifiable(); var mapperConfig = new MapperConfiguration(config => { config.ConfigureApi(); }); _mapper = mapperConfig.CreateMapper(); _controller = new TransportProvidersController(_transportProvidersServ.Object, _mapper); }
public FluentRecordBase AddTransportProvider( ) { // // DEPENDENCIES if (_servTP == null) { AddServTransportProvider(); } // // ARRANGE _tp = (TransportProvider)Records.transportProvider.Clone(); // // ACT _servTP.Create(_tp, _user); return(this); }
private void SendUpdateTunnelReply(I2PIdentHash ff, uint token) { // If greater than zero, a DeliveryStatusMessage // is requested with the Message ID set to the value of the Reply Token. // A floodfill router is also expected to flood the data to the closest floodfill peers // if the token is greater than zero. // https://geti2p.net/spec/i2np#databasestore var replytunnel = TunnelProvider.Inst.GetInboundTunnel(true); var ds = new DatabaseStoreMessage(RouterContext.Inst.MyRouterInfo, token, replytunnel.Destination, replytunnel.ReceiveTunnelId); lock ( OutstandingRequests ) { OutstandingRequests[token] = new FFUpdateRequestInfo(ff); } TransportProvider.Send(ff, ds); }
internal static void HandleDatabaseStore(DatabaseStoreMessage ds) { if (ds.RouterInfo == null && ds.LeaseSet == null) { throw new ArgumentException("DatabaseStore without Router or Lease info!"); } if (ds.RouterInfo != null) { #if LOG_ALL_TUNNEL_TRANSFER //Logging.Log( "HandleDatabaseStore: DatabaseStore RouterInfo" + ds.ToString() ); #endif NetDb.Inst.AddRouterInfo(ds.RouterInfo); } else { #if LOG_ALL_TUNNEL_TRANSFER //Logging.Log( "HandleDatabaseStore: DatabaseStore LeaseSet" + ds.ToString() ); #endif NetDb.Inst.AddLeaseSet(ds.LeaseSet); } if (ds.ReplyToken != 0) { if (ds.ReplyTunnelId != 0) { var outtunnel = TunnelProvider.Inst.GetEstablishedOutboundTunnel(true); if (outtunnel != null) { outtunnel.Send(new TunnelMessageRouter( (new TunnelGatewayMessage( new DeliveryStatusMessage(ds.ReplyToken), ds.ReplyTunnelId)), ds.ReplyGateway)); } } else { TransportProvider.Send(ds.ReplyGateway, new DeliveryStatusMessage(ds.ReplyToken)); } } }
/// <summary> /// Start the router with the current RouterContext settings. /// </summary> public static void Start() { lock ( StartedLock ) { if (Started) { return; } try { var rci = RouterContext.Inst; NetDb.Start(); Logging.Log("I: " + RouterContext.Inst.MyRouterInfo.ToString()); Logging.Log("Published: " + RouterContext.Inst.Published.ToString()); Logging.Log("Connecting..."); TransportProvider.Start(); TunnelProvider.Start(); ClientMgr = new ClientTunnelProvider(TunnelProvider.Inst); ExplorationMgr = new ExplorationTunnelProvider(TunnelProvider.Inst); TransitTunnelMgr = new TransitTunnelProvider(TunnelProvider.Inst); Worker = new Thread(Run) { Name = "Router", IsBackground = true }; Worker.Start(); NetDb.Inst.IdentHashLookup.LeaseSetReceived += IdentHashLookup_LeaseSetReceived; NetDb.Inst.IdentHashLookup.LookupFailure += IdentHashLookup_LookupFailure; Started = true; } catch (Exception ex) { Logging.Log(ex); } } }
private void SendRIDatabaseLookup(I2PIdentHash ident, IdentUpdateRequestInfo info) { var ff = NetDb.Inst.GetClosestFloodfill( ident, 10 + 3 * info.Retries, info.AlreadyQueried, false); if (!ff.Any()) { Logging.Log($"IdentResolver: failed to find a floodfill router to lookup ({ident}): "); return; } ff.Shuffle(); ff = ff.Take(DatabaseLookupSelectFloodfillCount).ToArray(); foreach (var oneff in ff) { try { var msg = new DatabaseLookupMessage( ident, RouterContext.Inst.MyRouterIdentity.IdentHash, DatabaseLookupMessage.LookupTypes.RouterInfo); TransportProvider.Send(oneff, msg); #if LOG_ALL_IDENT_LOOKUPS Logging.Log($"IdentResolver: RouterInfo query {msg.Key.Id32Short} sent to {oneff.Id32Short}"); #endif } catch (Exception ex) { Logging.Log("SendRIDatabaseLookup", ex); } } foreach (var f in ff) { info.AlreadyQueried.Add(f); } }
public static void Start() { if (Started) { return; } var rci = RouterContext.Inst; NetDb.Start(); Logging.Log("I: " + RouterContext.Inst.MyRouterInfo.ToString()); Logging.Log("Published: " + RouterContext.Inst.Published.ToString()); Logging.Log("Connecting..."); TransportProvider.Start(); TunnelProvider.Start(); Started = true; }
// Methods public void Attach(TransportProvider provider) { #region Contracts if (provider == null) { throw new ArgumentNullException(); } #endregion // Require if (_provider != null) { throw new InvalidOperationException(); } // Provider _provider = provider; }
private bool CreateTunnelMessageFragments(IEnumerable <TunnelMessage> messages) { var data = TunnelDataMessage.MakeFragments(messages, SendTunnelId); var encr = OutboundGatewayDecrypt(data); foreach (var msg in encr) { #if LOG_ALL_TUNNEL_TRANSFER if (FilterMessageTypes.Update(new HashedItemGroup((int)msg.MessageType, 0x4272))) { Logging.LogDebug($"OutboundTunnel: Send {NextHop.Id32Short} : {msg}"); } #endif Bandwidth.DataSent(msg.Payload.Length); TransportProvider.Send(NextHop, msg); } return(true); }
public ProtocolHeader GetSupportedHeader(ProtocolHeader requestedHeader) { // Protocol id negotiation TransportProvider provider = null; if (!this.TryGetTransportProvider(requestedHeader, out provider)) { return(this.GetDefaultHeader()); } // Protocol version negotiation AmqpVersion version; if (!provider.TryGetVersion(requestedHeader.Version, out version)) { return(new ProtocolHeader(provider.ProtocolId, provider.DefaultVersion)); } return(requestedHeader); }
public bool TryGetTransportProvider(ProtocolHeader header, out TransportProvider provider) { if (this.TransportProviders.Count == 0) { throw new ArgumentException("TransportProviders"); } provider = null; foreach (TransportProvider transportProvider in this.TransportProviders) { if (transportProvider.ProtocolId == header.ProtocolId) { provider = transportProvider; return(true); } } // Not found. Return the preferred one based on settings provider = this.GetDefaultProvider(); return(false); }
/// <summary> /// Initiate method for asynchronous receive operation of payload data. /// </summary> private void ReceivePayloadAsync(TransportProvider<TlsSocket> client) { // Initialize bytes received. client.BytesReceived = 0; // Initiate receiving. if (m_payloadAware) { // Payload boundaries are to be preserved. client.SetReceiveBuffer(m_payloadMarker.Length + Payload.LengthSegment); ReceivePayloadAwareAsync(client, true); } else { // Payload boundaries are not to be preserved. client.SetReceiveBuffer(ReceiveBufferSize); ReceivePayloadUnawareAsync(client); } }
/// <summary> /// Initiate method for asynchronous receive operation of payload data. /// </summary> private void ReceivePayloadAsync(TransportProvider<Socket> worker) { // Initialize pointers. worker.ReceiveBufferOffset = 0; worker.ReceiveBufferLength = -1; // Initiate receiving. if (m_payloadAware) { // Payload boundaries are to be preserved. worker.ReceiveBuffer = new byte[m_payloadMarker.Length + Payload.LengthSegment]; ReceivePayloadAwareAsync(worker); } else { // Payload boundaries are not to be preserved. worker.ReceiveBuffer = new byte[ReceiveBufferSize]; ReceivePayloadUnawareAsync(worker); } }
/// <summary> /// Processes the termination of client. /// </summary> private void TerminateConnection(TransportProvider<SslStream> client, bool raiseEvent) { client.Reset(); if (raiseEvent) OnClientDisconnected(client.ID); m_tcpClients.TryRemove(client.ID, out client); }
/// <summary> /// Callback method for asynchronous accept operation. /// </summary> private void ProcessAccept() { TransportProvider<Socket> client = new TransportProvider<Socket>(); SocketAsyncEventArgs receiveArgs = null; TcpClientInfo clientInfo; try { if (CurrentState == ServerState.NotRunning) return; if (m_acceptArgs.SocketError != SocketError.Success) { // Error is unrecoverable. // We need to make sure to restart the // server before we throw the error. SocketError error = m_acceptArgs.SocketError; ThreadPool.QueueUserWorkItem(state => ReStart()); throw new SocketException((int)error); } // Process the newly connected client. client.Provider = m_acceptArgs.AcceptSocket; // Set up SocketAsyncEventArgs for receive operations. receiveArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction(); receiveArgs.Completed += ReceiveHandler; // Return to accepting new connections. m_acceptArgs.AcceptSocket = null; if (!m_tcpServer.AcceptAsync(m_acceptArgs)) { ThreadPool.QueueUserWorkItem(state => ProcessAccept()); } #if !MONO // Authenticate the connected client Windows credentials. if (m_integratedSecurity) { NetworkStream socketStream = null; NegotiateStream authenticationStream = null; try { socketStream = new NetworkStream(client.Provider); authenticationStream = new NegotiateStream(socketStream); authenticationStream.AuthenticateAsServer(); if (authenticationStream.RemoteIdentity is WindowsIdentity) Thread.CurrentPrincipal = new WindowsPrincipal((WindowsIdentity)authenticationStream.RemoteIdentity); } finally { if (socketStream != null) socketStream.Dispose(); if (authenticationStream != null) authenticationStream.Dispose(); } } #endif if (MaxClientConnections != -1 && ClientIDs.Length >= MaxClientConnections) { // Reject client connection since limit has been reached. TerminateConnection(client, receiveArgs, false); } else { // We can proceed further with receiving data from the client. clientInfo = new TcpClientInfo() { Client = client, SendArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction(), SendLock = new SpinLock(), SendQueue = new ConcurrentQueue<TcpServerPayload>() }; // Set up socket args. client.SetSendBuffer(SendBufferSize); clientInfo.SendArgs.Completed += m_sendHandler; clientInfo.SendArgs.SetBuffer(client.SendBuffer, 0, client.SendBufferSize); m_clientInfoLookup.TryAdd(client.ID, clientInfo); OnClientConnected(client.ID); if (!m_payloadAware) { receiveArgs.UserToken = client; } else { EventArgs<TransportProvider<Socket>, bool> userToken = ReusableObjectPool<EventArgs<TransportProvider<Socket>, bool>>.Default.TakeObject(); userToken.Argument1 = client; receiveArgs.UserToken = userToken; } ReceivePayloadAsync(client, receiveArgs); } } catch (Exception ex) { // Notify of the exception. if ((object)client.Provider != null) { string clientAddress = ((IPEndPoint)client.Provider.RemoteEndPoint).Address.ToString(); string errorMessage = string.Format("Unable to accept connection to client [{0}]: {1}", clientAddress, ex.Message); OnClientConnectingException(new Exception(errorMessage, ex)); } if ((object)receiveArgs != null) { TerminateConnection(client, receiveArgs, false); } } }
/// <summary> /// Callback method for asynchronous accept operation. /// </summary> private void AcceptAsyncCallback(IAsyncResult asyncResult) { TransportProvider<Socket> tcpClient = new TransportProvider<Socket>(); try { // Return to accepting new connections. m_tcpServer.BeginAccept(AcceptAsyncCallback, null); // Process the newly connected client. tcpClient.Secretkey = SharedSecret; tcpClient.Provider = m_tcpServer.EndAccept(asyncResult); if (MaxClientConnections != -1 && ClientIDs.Length >= MaxClientConnections) { // Reject client connection since limit has been reached. TerminateConnection(tcpClient, false); } else { // We can proceed further with receiving data from the client. if (Handshake) { // Handshaking must be performed. ReceiveHandshakeAsync(tcpClient); } else { // No handshaking to be performed. lock (m_tcpClients) { m_tcpClients.Add(tcpClient.ID, tcpClient); } OnClientConnected(tcpClient.ID); ReceivePayloadAsync(tcpClient); } } } catch { // Server socket has been terminated. m_tcpServer.Close(); OnServerStopped(); } }
/// <summary> /// Processes the termination of client. /// </summary> private void TerminateConnection(TransportProvider<TlsSocket> client, bool raiseEvent) { TlsClientInfo clientInfo; client.Reset(); if (raiseEvent) OnClientDisconnected(client.ID); m_clientInfoLookup.TryRemove(client.ID, out clientInfo); }
/// <summary> /// Callback method for asynchronous accept operation. /// </summary> private void ProcessAccept(SocketAsyncEventArgs acceptArgs) { TransportProvider<TlsSocket> client = new TransportProvider<TlsSocket>(); IPEndPoint remoteEndPoint = null; NetworkStream netStream; try { if (CurrentState == ServerState.NotRunning) return; // If acceptArgs was disposed, m_acceptArgs will either // be null or another instance of SocketAsyncEventArgs. // This check will tell us whether it's been disposed. if ((object)acceptArgs != m_acceptArgs) return; if (acceptArgs.SocketError != SocketError.Success) { // Error is unrecoverable. // We need to make sure to restart the // server before we throw the error. SocketError error = acceptArgs.SocketError; ThreadPool.QueueUserWorkItem(state => ReStart()); throw new SocketException((int)error); } // Get the remote end point in case we need to display useful error messages remoteEndPoint = acceptArgs.AcceptSocket.RemoteEndPoint as IPEndPoint; if (MaxClientConnections != -1 && ClientIDs.Length >= MaxClientConnections) { // Reject client connection since limit has been reached. TerminateConnection(client, false); } else { // Process the newly connected client. LoadTrustedCertificates(); netStream = new NetworkStream(acceptArgs.AcceptSocket); client.Provider = new TlsSocket { Socket = acceptArgs.AcceptSocket, SslStream = new SslStream(netStream, false, m_remoteCertificateValidationCallback ?? CertificateChecker.ValidateRemoteCertificate, m_localCertificateSelectionCallback) }; client.Provider.Socket.ReceiveBufferSize = ReceiveBufferSize; client.Provider.SslStream.BeginAuthenticateAsServer(m_certificate, m_requireClientCertificate, m_enabledSslProtocols, m_checkCertificateRevocation, ProcessTlsAuthentication, client); } // Return to accepting new connections. acceptArgs.AcceptSocket = null; if (!m_tlsServer.AcceptAsync(acceptArgs)) { ThreadPool.QueueUserWorkItem(state => ProcessAccept(acceptArgs)); } } catch (ObjectDisposedException) { // m_acceptArgs may be disposed while in the middle of accepting a connection } catch (Exception ex) { // Notify of the exception. if ((object)remoteEndPoint != null) { string clientAddress = remoteEndPoint.Address.ToString(); string errorMessage = $"Unable to accept connection to client [{clientAddress}]: {ex.Message}"; OnClientConnectingException(new Exception(errorMessage, ex)); } TerminateConnection(client, false); } }
/// <summary> /// Callback method for asynchronous receive operation of handshake data. /// </summary> private void ReceiveHandshakeAsyncCallback(IAsyncResult asyncResult) { TransportProvider<Socket> udpServer = (TransportProvider<Socket>)asyncResult.AsyncState; // Received handshake data from client so we'll process it. try { // Update statistics and pointers. EndPoint client = Transport.CreateEndPoint(string.Empty, 0); udpServer.Statistics.UpdateBytesReceived(udpServer.Provider.EndReceiveFrom(asyncResult, ref client)); udpServer.ReceiveBufferLength = udpServer.Statistics.LastBytesReceived; // Process the received handshake message. Payload.ProcessReceived(ref udpServer.ReceiveBuffer, ref udpServer.ReceiveBufferOffset, ref udpServer.ReceiveBufferLength, Encryption, SharedSecret, Compression); HandshakeMessage handshake = new HandshakeMessage(); if (handshake.Initialize(udpServer.ReceiveBuffer, udpServer.ReceiveBufferOffset, udpServer.ReceiveBufferLength) != -1) { // Received handshake message is parsed successfully. if (handshake.ID != Guid.Empty) { // Create a random socket and connect it to the client. TransportProvider<Socket> udpClient = new TransportProvider<Socket>(); udpClient.ReceiveBuffer = new byte[ReceiveBufferSize]; udpClient.Secretkey = SharedSecret; udpClient.Provider = Transport.CreateSocket(m_configData["interface"], 0, ProtocolType.Udp); udpClient.Provider.Connect(client); // Authentication is successful; respond to the handshake. udpClient.ID = handshake.ID; handshake.ID = this.ServerID; if (SecureSession) { // Create a secret key for ciphering client data. udpClient.Secretkey = Guid.NewGuid().ToString(); handshake.Secretkey = udpClient.Secretkey; } // Prepare binary image of handshake response to be transmitted. udpClient.SendBuffer = handshake.BinaryImage; udpClient.SendBufferOffset = 0; udpClient.SendBufferLength = udpClient.SendBuffer.Length; Payload.ProcessTransmit(ref udpClient.SendBuffer, ref udpClient.SendBufferOffset, ref udpClient.SendBufferLength, Encryption, SharedSecret, Compression); // Transmit the prepared and processed handshake response message. udpClient.Provider.SendTo(udpClient.SendBuffer, udpClient.Provider.RemoteEndPoint); // Handshake process is complete and client is considered connected. lock (m_udpClients) { m_udpClients.Add(udpClient.ID, udpClient); } OnClientConnected(udpClient.ID); try { ReceivePayloadOneAsync(udpClient); } catch { // Receive will fail if client disconnected before handshake is complete. TerminateConnection(udpClient, true); } } else { // Validation during handshake failed. OnHandshakeProcessUnsuccessful(); } } else { // Handshake message could not be parsed. OnHandshakeProcessUnsuccessful(); } // Resume receiving of client handshake messages. ReceiveHandshakeAsync(udpServer); } catch { // Server socket has been terminated. udpServer.Reset(); OnServerStopped(); } }
/// <summary> /// Initiate method for asynchronous receive operation of payload data from any endpoint. /// </summary> private void ReceivePayloadAnyAsync(TransportProvider<Socket> worker) { worker.Provider.BeginReceiveFrom(worker.ReceiveBuffer, worker.ReceiveBufferOffset, worker.ReceiveBuffer.Length, SocketFlags.None, ref m_udpClientEndPoint, ReceivePayloadAnyAsyncCallback, worker); }
/// <summary> /// Starts the <see cref="UdpServer"/> synchronously and begins accepting client connections asynchronously. /// </summary> /// <exception cref="InvalidOperationException">Attempt is made to <see cref="Start()"/> the <see cref="UdpServer"/> when it is running.</exception> public override void Start() { if (CurrentState == ServerState.NotRunning) { // Initialize if unitialized. Initialize(); // Create end-point for receiving data. m_udpClientEndPoint = Transport.CreateEndPoint(string.Empty, 0); // Bind server socket to local end-point. m_udpServer = new TransportProvider<Socket>(); m_udpServer.ID = this.ServerID; m_udpServer.ReceiveBuffer = new byte[ReceiveBufferSize]; m_udpServer.Provider = Transport.CreateSocket(m_configData["interface"], int.Parse(m_configData["port"]), ProtocolType.Udp); // Notify that the server has been started successfully. OnServerStarted(); if (Handshake) { // Listen for incoming data if server endpoint is bound to a local interface. m_receivedGoodbye = DoGoodbyeCheck; if (m_udpServer.Provider.LocalEndPoint != null) ReceiveHandshakeAsync(m_udpServer); } else { // Listen for incoming data if server endpoint is bound to a local interface. m_receivedGoodbye = NoGoodbyeCheck; if (m_udpServer.Provider.LocalEndPoint != null) ReceivePayloadAnyAsync(m_udpServer); // When handshake is not to be performed, we process the static list to clients. foreach (string clientString in m_configData["clients"].Replace(" ", "").Split(',')) { try { Match endpoint = Regex.Match(clientString, Transport.EndpointFormatRegex); if (endpoint != Match.Empty) { TransportProvider<Socket> udpClient = new TransportProvider<Socket>(); udpClient.Secretkey = SharedSecret; udpClient.ReceiveBuffer = new byte[ReceiveBufferSize]; udpClient.Provider = Transport.CreateSocket(m_configData["interface"], 0, ProtocolType.Udp); // Disable SocketError.ConnectionReset exception from being thrown when the enpoint is not listening. udpClient.Provider.IOControl(SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null); // Connect socket to the client endpoint so communication on the socket is restricted to a single endpoint. udpClient.Provider.Connect(Transport.CreateEndPoint(endpoint.Groups["host"].Value, int.Parse(endpoint.Groups["port"].Value))); lock (m_udpClients) { m_udpClients.Add(udpClient.ID, udpClient); } OnClientConnected(udpClient.ID); ReceivePayloadOneAsync(udpClient); } } catch { // Ignore invalid client entries. } } } } else { throw new InvalidOperationException("Server is currently running"); } }
/// <summary> /// Initiate method for asynchronous receive operation of handshake data. /// </summary> private void ReceiveHandshakeAsync(TransportProvider<Socket> worker) { // Receive data asynchronously. EndPoint client = Transport.CreateEndPoint(string.Empty, 0); worker.Provider.BeginReceiveFrom(worker.ReceiveBuffer, worker.ReceiveBufferOffset, worker.ReceiveBuffer.Length, SocketFlags.None, ref client, ReceiveHandshakeAsyncCallback, worker); }
private TransportProvider<EndPoint> AddUdpClient(EndPoint udpClientEndPoint) { TransportProvider<EndPoint> udpClient = new TransportProvider<EndPoint>(); IPEndPoint udpClientIPEndPoint = udpClientEndPoint as IPEndPoint; UdpClientInfo udpClientInfo; // Set up client udpClient.SetReceiveBuffer(ReceiveBufferSize); udpClient.SetSendBuffer(SendBufferSize); udpClient.Provider = udpClientIPEndPoint; // If the IP specified for the client is a multicast IP, subscribe to the specified multicast group. if ((object)udpClientIPEndPoint != null && Transport.IsMulticastIP(udpClientIPEndPoint.Address)) { SocketOptionLevel level = udpClientIPEndPoint.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP; string multicastSource; if (m_configData.TryGetValue("multicastSource", out multicastSource)) { IPAddress sourceAddress = IPAddress.Parse(multicastSource); IPAddress localAddress = (udpClientIPEndPoint.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any); if (sourceAddress.AddressFamily != udpClientIPEndPoint.AddressFamily) throw new InvalidOperationException($"Source address \"{sourceAddress}\" is not in the same IP format as server address \"{udpClientIPEndPoint.Address}\""); if (localAddress.AddressFamily != udpClientIPEndPoint.AddressFamily) throw new InvalidOperationException($"Local address \"{localAddress}\" is not in the same IP format as server address \"{udpClientIPEndPoint.Address}\""); using (BlockAllocatedMemoryStream membershipAddresses = new BlockAllocatedMemoryStream()) { byte[] serverAddressBytes = udpClientIPEndPoint.Address.GetAddressBytes(); byte[] sourceAddressBytes = sourceAddress.GetAddressBytes(); byte[] localAddressBytes = localAddress.GetAddressBytes(); membershipAddresses.Write(serverAddressBytes, 0, serverAddressBytes.Length); membershipAddresses.Write(sourceAddressBytes, 0, sourceAddressBytes.Length); membershipAddresses.Write(localAddressBytes, 0, localAddressBytes.Length); udpClient.MulticastMembershipAddresses = membershipAddresses.ToArray(); } // Execute multicast subscribe for specific source m_udpServer.Provider.SetSocketOption(level, SocketOptionName.AddSourceMembership, udpClient.MulticastMembershipAddresses); m_udpServer.Provider.SetSocketOption(level, SocketOptionName.MulticastTimeToLive, int.Parse(m_configData["multicastTimeToLive"])); } else { // Execute multicast subscribe for any source m_udpServer.Provider.SetSocketOption(level, SocketOptionName.AddMembership, new MulticastOption(udpClientIPEndPoint.Address)); m_udpServer.Provider.SetSocketOption(level, SocketOptionName.MulticastTimeToLive, int.Parse(m_configData["multicastTimeToLive"])); } } // Create client info object udpClientInfo = new UdpClientInfo { Client = udpClient, SendArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction(), SendLock = new object(), SendQueue = new ConcurrentQueue<UdpServerPayload>() }; udpClientInfo.DumpPayloadsOperation = new ShortSynchronizedOperation(() => { UdpServerPayload payload; // Check to see if the client has reached the maximum send queue size. if (m_maxSendQueueSize > 0 && udpClientInfo.SendQueue.Count >= m_maxSendQueueSize) { for (int i = 0; i < m_maxSendQueueSize; i++) { if (udpClientInfo.SendQueue.TryDequeue(out payload)) { payload.WaitHandle.Set(); payload.WaitHandle.Dispose(); payload.WaitHandle = null; } } throw new InvalidOperationException($"Client {udpClientInfo.Client.ID} connected to UDP server reached maximum send queue size. {m_maxSendQueueSize} payloads dumped from the queue."); } }, ex => OnSendClientDataException(udpClientInfo.Client.ID, ex)); // Set up SocketAsyncEventArgs udpClientInfo.SendArgs.RemoteEndPoint = udpClient.Provider; udpClientInfo.SendArgs.SetBuffer(udpClient.SendBuffer, 0, udpClient.SendBufferSize); udpClientInfo.SendArgs.Completed += m_sendHandler; // Add new client to the lookup m_clientInfoLookup.TryAdd(udpClient.ID, udpClientInfo); OnClientConnected(udpClient.ID); return udpClient; }
/// <summary> /// Starts the <see cref="UdpServer"/> synchronously and begins accepting client connections asynchronously. /// </summary> /// <exception cref="InvalidOperationException">Attempt is made to <see cref="Start()"/> the <see cref="UdpServer"/> when it is running.</exception> public override void Start() { if (CurrentState == ServerState.NotRunning) { int maxSendQueueSize; // Initialize if unitialized if (!Initialized) Initialize(); // Overwrite config file if max send queue size exists in connection string. if (m_configData.ContainsKey("maxSendQueueSize") && int.TryParse(m_configData["maxSendQueueSize"], out maxSendQueueSize)) m_maxSendQueueSize = maxSendQueueSize; // Bind server socket to local end-point m_udpServer = new TransportProvider<Socket>(); m_udpServer.SetReceiveBuffer(ReceiveBufferSize); m_udpServer.Provider = Transport.CreateSocket(m_configData["interface"], int.Parse(m_configData["port"]), ProtocolType.Udp, m_ipStack, m_allowDualStackSocket); // Disable SocketError.ConnectionReset exception from being thrown when the endpoint is not listening m_udpServer.Provider.IOControl(SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null); // Notify that the server has been started successfully OnServerStarted(); if ((object)m_udpServer.Provider.LocalEndPoint != null) { m_receiveArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction(); m_receiveArgs.SocketFlags = SocketFlags.None; m_receiveArgs.Completed += m_receiveHandler; ReceivePayloadAsync(m_receiveArgs); } // We process the static list to clients. foreach (string clientString in m_configData["clients"].Replace(" ", "").Split(',')) { try { Match endpoint = Regex.Match(clientString, Transport.EndpointFormatRegex); if (endpoint != Match.Empty) { UdpClientInfo clientInfo; TransportProvider<EndPoint> udpClient = new TransportProvider<EndPoint>(); IPEndPoint clientEndpoint = Transport.CreateEndPoint(endpoint.Groups["host"].Value, int.Parse(endpoint.Groups["port"].Value), m_ipStack); udpClient.SetReceiveBuffer(ReceiveBufferSize); udpClient.SetSendBuffer(SendBufferSize); udpClient.Provider = clientEndpoint; // If the IP specified for the client is a multicast IP, subscribe to the specified multicast group. if (Transport.IsMulticastIP(clientEndpoint.Address)) { string multicastSource; if (m_configData.TryGetValue("multicastSource", out multicastSource)) { IPAddress sourceAddress = IPAddress.Parse(multicastSource); IPAddress localAddress = (clientEndpoint.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any); if (sourceAddress.AddressFamily != clientEndpoint.AddressFamily) throw new InvalidOperationException(string.Format("Source address \"{0}\" is not in the same IP format as server address \"{1}\"", sourceAddress, clientEndpoint.Address)); if (localAddress.AddressFamily != clientEndpoint.AddressFamily) throw new InvalidOperationException(string.Format("Local address \"{0}\" is not in the same IP format as server address \"{1}\"", localAddress, clientEndpoint.Address)); MemoryStream membershipAddresses = new MemoryStream(); byte[] serverAddressBytes = clientEndpoint.Address.GetAddressBytes(); byte[] sourceAddressBytes = sourceAddress.GetAddressBytes(); byte[] localAddressBytes = localAddress.GetAddressBytes(); membershipAddresses.Write(serverAddressBytes, 0, serverAddressBytes.Length); membershipAddresses.Write(sourceAddressBytes, 0, sourceAddressBytes.Length); membershipAddresses.Write(localAddressBytes, 0, localAddressBytes.Length); udpClient.MulticastMembershipAddresses = membershipAddresses.ToArray(); // Execute multicast subscribe for specific source SocketOptionLevel level = clientEndpoint.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP; m_udpServer.Provider.SetSocketOption(level, SocketOptionName.AddSourceMembership, udpClient.MulticastMembershipAddresses); m_udpServer.Provider.SetSocketOption(level, SocketOptionName.MulticastTimeToLive, int.Parse(m_configData["multicastTimeToLive"])); } else { // Execute multicast subscribe for any source SocketOptionLevel level = clientEndpoint.AddressFamily == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP; m_udpServer.Provider.SetSocketOption(level, SocketOptionName.AddMembership, new MulticastOption(clientEndpoint.Address)); m_udpServer.Provider.SetSocketOption(level, SocketOptionName.MulticastTimeToLive, int.Parse(m_configData["multicastTimeToLive"])); } } clientInfo = new UdpClientInfo() { Client = udpClient, SendArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction(), SendLock = new SpinLock(), SendQueue = new ConcurrentQueue<UdpServerPayload>() }; clientInfo.SendArgs.RemoteEndPoint = udpClient.Provider; clientInfo.SendArgs.SetBuffer(udpClient.SendBuffer, 0, udpClient.SendBufferSize); clientInfo.SendArgs.Completed += m_sendHandler; m_clientInfoLookup.TryAdd(udpClient.ID, clientInfo); OnClientConnected(udpClient.ID); } } catch (Exception ex) { string errorMessage = string.Format("Unable to connect to client {0}: {1}", clientString, ex.Message); OnClientConnectingException(new Exception(errorMessage, ex)); } } } else { throw new InvalidOperationException("Server is currently running"); } }
/// <summary> /// Callback method for asynchronous accept operation. /// </summary> private void ProcessAccept() { TransportProvider<SslStream> client = new TransportProvider<SslStream>(); IPEndPoint remoteEndPoint = null; NetworkStream netStream; Tuple<TransportProvider<SslStream>, IPEndPoint> asyncState; try { if (CurrentState == ServerState.NotRunning) return; if (m_acceptArgs.SocketError != SocketError.Success) { // Error is unrecoverable. // We need to make sure to restart the // server before we throw the error. SocketError error = m_acceptArgs.SocketError; ThreadPool.QueueUserWorkItem(state => ReStart()); throw new SocketException((int)error); } // Process the newly connected client. remoteEndPoint = m_acceptArgs.AcceptSocket.RemoteEndPoint as IPEndPoint; netStream = new NetworkStream(m_acceptArgs.AcceptSocket); client.Provider = new SslStream(netStream, false, m_remoteCertificateValidationCallback, m_localCertificateSelectionCallback); asyncState = new Tuple<TransportProvider<SslStream>, IPEndPoint>(client, remoteEndPoint); client.Provider.BeginAuthenticateAsServer(m_certificate, true, m_enabledSslProtocols, m_checkCertificateRevocation, ProcessAuthenticate, asyncState); // Return to accepting new connections. m_acceptArgs.AcceptSocket = null; if (!m_tcpServer.AcceptAsync(m_acceptArgs)) { ThreadPool.QueueUserWorkItem(state => ProcessAccept()); } } catch (Exception ex) { // Notify of the exception. if ((object)remoteEndPoint != null) { string clientAddress = remoteEndPoint.Address.ToString(); string errorMessage = string.Format("Unable to accept connection to client [{0}]: {1}", clientAddress, ex.Message); OnClientConnectingException(new Exception(errorMessage, ex)); } TerminateConnection(client, false); } }
/// <summary> /// Initiate method for asynchronous receive operation of payload data in "payload-aware" mode. /// </summary> private void ReceivePayloadAwareAsync(TransportProvider<TlsSocket> client, bool waitingForHeader) { client.Provider.SslStream.BeginRead(client.ReceiveBuffer, client.BytesReceived, client.ReceiveBufferSize - client.BytesReceived, ProcessReceivePayloadAware, new Tuple<Guid, bool>(client.ID, waitingForHeader)); }
/// <summary> /// Callback method for asynchronous receive operation of payload data from any endpoint. /// </summary> private void ReceivePayloadAnyAsyncCallback(IAsyncResult asyncResult) { TransportProvider<Socket> udpServer = (TransportProvider<Socket>)asyncResult.AsyncState; try { // Update statistics and pointers. udpServer.Statistics.UpdateBytesReceived(udpServer.Provider.EndReceiveFrom(asyncResult, ref m_udpClientEndPoint)); udpServer.ReceiveBufferLength = udpServer.Statistics.LastBytesReceived; // Get a local copy of all connected clients. TransportProvider<Socket>[] clients = null; lock (m_udpClients) { clients = new TransportProvider<Socket>[m_udpClients.Count]; m_udpClients.Values.CopyTo(clients, 0); } // Search connected clients for a client connected to the end-point from where this data is received. foreach (TransportProvider<Socket> client in clients) { if (client.Provider.RemoteEndPoint.Equals(m_udpClientEndPoint)) { // Found a match, notify of data. OnReceiveClientDataComplete(client.ID, udpServer.ReceiveBuffer, udpServer.ReceiveBufferLength); break; } } // Resume receive operation on the server socket. ReceivePayloadAnyAsync(udpServer); } catch { // Server socket has been terminated. udpServer.Reset(); OnServerStopped(); } }
/// <summary> /// Initiate method for asynchronous receive operation of payload data in "payload-unaware" mode. /// </summary> private void ReceivePayloadUnawareAsync(TransportProvider<TlsSocket> client) { client.Provider.SslStream.BeginRead(client.ReceiveBuffer, 0, client.ReceiveBufferSize, ProcessReceivePayloadUnaware, client); }
/// <summary> /// Initiate method for asynchronous receive operation of payload data from a single endpoint. /// </summary> private void ReceivePayloadOneAsync(TransportProvider<Socket> worker) { EndPoint client = worker.Provider.RemoteEndPoint; if (ReceiveTimeout == -1) { // Wait for data indefinitely. worker.Provider.BeginReceiveFrom(worker.ReceiveBuffer, worker.ReceiveBufferOffset, worker.ReceiveBuffer.Length, SocketFlags.None, ref client, ReceivePayloadOneAsyncCallback, worker); } else { // Wait for data with a timeout. worker.WaitAsync(ReceiveTimeout, ReceivePayloadOneAsyncCallback, worker.Provider.BeginReceiveFrom(worker.ReceiveBuffer, worker.ReceiveBufferOffset, worker.ReceiveBuffer.Length, SocketFlags.None, ref client, ReceivePayloadOneAsyncCallback, worker)); } }
/// <summary> /// Gets the <see cref="TransportProvider{TlsSocket}"/> object associated with the specified client ID. /// </summary> /// <param name="clientID">ID of the client.</param> /// <param name="tlsClient">The TLS client.</param> /// <returns>An <see cref="TransportProvider{TlsSocket}"/> object.</returns> /// <exception cref="InvalidOperationException">Client does not exist for the specified <paramref name="clientID"/>.</exception> public bool TryGetClient(Guid clientID, out TransportProvider<TlsSocket> tlsClient) { TlsClientInfo clientInfo; bool clientExists = m_clientInfoLookup.TryGetValue(clientID, out clientInfo); if (clientExists) tlsClient = clientInfo.Client; else tlsClient = null; return clientExists; }
/// <summary> /// Delegate that gets called to verify client disconnect when <see cref="ServerBase.Handshake"/> is turned off. /// </summary> private bool NoGoodbyeCheck(TransportProvider<Socket> client) { return false; }
/// <summary> /// Starts the <see cref="UdpServer"/> synchronously and begins accepting client connections asynchronously. /// </summary> /// <exception cref="InvalidOperationException">Attempt is made to <see cref="Start()"/> the <see cref="UdpServer"/> when it is running.</exception> public override void Start() { if (CurrentState == ServerState.NotRunning) { ClientIdentificationMode clientIdentificationMode; int maxSendQueueSize; // Initialize if uninitialized if (!Initialized) Initialize(); // Overwrite config file if client identification mode exists in connection string. if (m_configData.ContainsKey("identifyClientsBy") && Enum.TryParse(m_configData["identifyClientsBy"], true, out clientIdentificationMode)) m_clientIdentificationMode = clientIdentificationMode; // Overwrite config file if client end points are dynamic if (m_configData.ContainsKey("dynamicClientEndPoints")) m_dynamicClientEndPoints = m_configData["dynamicClientEndPoints"].ParseBoolean(); // Overwrite config file if max send queue size exists in connection string. if (m_configData.ContainsKey("maxSendQueueSize") && int.TryParse(m_configData["maxSendQueueSize"], out maxSendQueueSize)) m_maxSendQueueSize = maxSendQueueSize; // Bind server socket to local end-point m_udpServer = new TransportProvider<Socket>(); m_udpServer.SetReceiveBuffer(ReceiveBufferSize); m_udpServer.Provider = Transport.CreateSocket(m_configData["interface"], int.Parse(m_configData["port"]), ProtocolType.Udp, m_ipStack, m_allowDualStackSocket); m_udpServer.Provider.ReceiveBufferSize = ReceiveBufferSize; // Disable SocketError.ConnectionReset exception from being thrown when the endpoint is not listening // Fix MONO bug with SIO_UDP_CONNRESET try { m_udpServer.Provider.IOControl(SIO_UDP_CONNRESET, new[] { Convert.ToByte(false) }, null); } catch { } // Notify that the server has been started successfully OnServerStarted(); if ((object)m_udpServer.Provider.LocalEndPoint != null) { m_receiveArgs = FastObjectFactory<SocketAsyncEventArgs>.CreateObjectFunction(); m_receiveArgs.SocketFlags = SocketFlags.None; m_receiveArgs.Completed += m_receiveHandler; ReceivePayloadAsync(m_receiveArgs); } // Determine whether we have a static or dynamic client list m_dynamicClientList = !m_configData.ContainsKey("clients"); if (m_dynamicClientList) { m_dynamicClientEndPoints = true; } else { // We process the static list of clients. foreach (string clientString in m_configData["clients"].Replace(" ", "").Split(',')) { try { Match endpoint = Regex.Match(clientString, Transport.EndpointFormatRegex); int port; if (endpoint != Match.Empty) AddUdpClient(endpoint.Groups["host"].Value, int.Parse(endpoint.Groups["port"].Value)); else if (int.TryParse(clientString, out port)) AddUdpClient(null, port); else AddUdpClient(clientString, 0); } catch (Exception ex) { string errorMessage = $"Unable to connect to client {clientString}: {ex.Message}"; OnClientConnectingException(new Exception(errorMessage, ex)); } } } } else { throw new InvalidOperationException("Server is currently running"); } }
/// <summary> /// Delegate that gets called to verify client disconnect when <see cref="ServerBase.Handshake"/> is turned on. /// </summary> private bool DoGoodbyeCheck(TransportProvider<Socket> client) { // Process data received in the buffer. int offset = client.ReceiveBufferOffset; int length = client.ReceiveBufferLength; byte[] buffer = client.ReceiveBuffer.BlockCopy(0, length); Payload.ProcessReceived(ref buffer, ref offset, ref length, Encryption, client.Secretkey, Compression); // Check if data is for goodbye message. return (new GoodbyeMessage().Initialize(buffer, offset, length) != -1); }
/// <summary> /// Processes the termination of client. /// </summary> private void TerminateConnection(TransportProvider<Socket> client, SocketAsyncEventArgs args, bool raiseEvent) { TcpClientInfo clientInfo; try { if (m_clientInfoLookup.TryRemove(client.ID, out clientInfo)) { client.Reset(); clientInfo.SendArgs.Dispose(); } if (raiseEvent) OnClientDisconnected(client.ID); } finally { DisposeReceiveArgs(args); } }
/// <summary> /// Processes the termination of client. /// </summary> private void TerminateConnection(TransportProvider<Socket> client, bool raiseEvent) { client.Reset(); if (raiseEvent) OnClientDisconnected(client.ID); lock (m_tcpClients) { if (m_tcpClients.ContainsKey(client.ID)) m_tcpClients.Remove(client.ID); } }
/// <summary> /// Initiate method for asynchronous receive operation of handshake data. /// </summary> private void ReceiveHandshakeAsync(TransportProvider<Socket> worker) { // Prepare buffer used for receiving data. worker.ReceiveBufferOffset = 0; worker.ReceiveBufferLength = -1; worker.ReceiveBuffer = new byte[ReceiveBufferSize]; // Receive data asynchronously with a timeout. worker.WaitAsync(HandshakeTimeout, ReceiveHandshakeAsyncCallback, worker.Provider.BeginReceive(worker.ReceiveBuffer, worker.ReceiveBufferOffset, worker.ReceiveBuffer.Length, SocketFlags.None, ReceiveHandshakeAsyncCallback, worker)); }
public CustomTransportListener(ConnectionListener listener, TransportProvider provider) { this.Listener = listener; this.provider = provider; }
/// <summary> /// Initiate method for asynchronous receive operation of payload data in "payload-unaware" mode. /// </summary> private void ReceivePayloadUnawareAsync(TransportProvider<Socket> worker) { if (ReceiveTimeout == -1) { // Wait for data indefinitely. worker.Provider.BeginReceive(worker.ReceiveBuffer, worker.ReceiveBufferOffset, worker.ReceiveBuffer.Length - worker.ReceiveBufferOffset, SocketFlags.None, ReceivePayloadUnawareAsyncCallback, worker); } else { // Wait for data with a timeout. worker.WaitAsync(ReceiveTimeout, ReceivePayloadUnawareAsyncCallback, worker.Provider.BeginReceive(worker.ReceiveBuffer, worker.ReceiveBufferOffset, worker.ReceiveBuffer.Length - worker.ReceiveBufferOffset, SocketFlags.None, ReceivePayloadUnawareAsyncCallback, worker)); } }
/// <summary> /// Gets the <see cref="TransportProvider{EndPoint}"/> object associated with the specified client ID. /// </summary> /// <param name="clientID">ID of the client.</param> /// <param name="udpClient">The UDP client.</param> /// <returns>An <see cref="TransportProvider{EndPoint}"/> object.</returns> /// <exception cref="InvalidOperationException">Client does not exist for the specified <paramref name="clientID"/>.</exception> public bool TryGetClient(Guid clientID, out TransportProvider<EndPoint> udpClient) { UdpClientInfo clientInfo; bool clientExists; clientExists = m_clientInfoLookup.TryGetValue(clientID, out clientInfo); if (clientExists) udpClient = clientInfo.Client; else udpClient = null; return clientExists; }
/// <summary> /// Initializes a new instance of the <see cref="TcpClient"/> class. /// </summary> /// <param name="connectString">Connect string of the <see cref="TcpClient"/>. See <see cref="DefaultConnectionString"/> for format.</param> public TcpClient(string connectString) : base(TransportProtocol.Tcp, connectString) { m_sendLock = new SpinLock(); m_sendQueue = new ConcurrentQueue<TcpClientPayload>(); m_payloadAware = DefaultPayloadAware; m_payloadMarker = Payload.DefaultMarker; m_integratedSecurity = DefaultIntegratedSecurity; m_allowDualStackSocket = DefaultAllowDualStackSocket; m_maxSendQueueSize = DefaultMaxSendQueueSize; m_tcpClient = new TransportProvider<Socket>(); m_connectHandler = (o, args) => ProcessConnect(); m_sendHandler = (o, args) => ProcessSend(); m_receivePayloadAwareHandler = (o, args) => ProcessReceivePayloadAware(); m_receivePayloadUnawareHandler = (o, args) => ProcessReceivePayloadUnaware(); }
/// <summary> /// Gets the <see cref="TransportProvider{Socket}"/> object associated with the specified client ID. /// </summary> /// <param name="clientID">ID of the client.</param> /// <param name="clientInfo">Client information.</param> /// <returns><c>true</c> if client exists; otherwise, <c>false</c>.</returns> public bool TryGetClient(Guid clientID, out TransportProvider<DateTime> clientInfo) { return m_clientInfoLookup.TryGetValue(clientID, out clientInfo); }