public TcpConnectionManager(string connectionName, Guid connectionId, ITcpDispatcher dispatcher, IPublisher publisher, string targetHost, EndPoint remoteEndPoint, TcpClientConnector connector, bool useSsl, Func <X509Certificate, X509Chain, SslPolicyErrors, ValueTuple <bool, string> > sslServerCertValidator, Func <X509CertificateCollection> sslClientCertificatesSelector, IPublisher networkSendQueue, IAuthenticationProvider authProvider, AuthorizationGateway authorization, TimeSpan heartbeatInterval, TimeSpan heartbeatTimeout, Action <TcpConnectionManager> onConnectionEstablished, Action <TcpConnectionManager, SocketError> onConnectionClosed) { Ensure.NotEmptyGuid(connectionId, "connectionId"); Ensure.NotNull(dispatcher, "dispatcher"); Ensure.NotNull(publisher, "publisher"); Ensure.NotNull(authProvider, "authProvider"); Ensure.NotNull(authorization, "authorization"); Ensure.NotNull(remoteEndPoint, "remoteEndPoint"); Ensure.NotNull(connector, "connector"); ConnectionId = connectionId; ConnectionName = connectionName; _tcpEnvelope = new SendOverTcpEnvelope(this, networkSendQueue); _publisher = publisher; _dispatcher = dispatcher; _authProvider = authProvider; _authorization = authorization; _framer = new LengthPrefixMessageFramer(); _framer.RegisterMessageArrivedCallback(OnMessageArrived); _weakThisEnvelope = new SendToWeakThisEnvelope(this); _heartbeatInterval = heartbeatInterval; _heartbeatTimeout = heartbeatTimeout; _connectionPendingSendBytesThreshold = ESConsts.UnrestrictedPendingSendBytes; _connectionQueueSizeThreshold = ESConsts.MaxConnectionQueueSize; _connectionEstablished = onConnectionEstablished; _connectionClosed = onConnectionClosed; RemoteEndPoint = remoteEndPoint; _connection = useSsl ? connector.ConnectSslTo(ConnectionId, targetHost, remoteEndPoint.ResolveDnsToIPAddress(), ConnectionTimeout, sslServerCertValidator, sslClientCertificatesSelector, OnConnectionEstablished, OnConnectionFailed) : connector.ConnectTo(ConnectionId, remoteEndPoint.ResolveDnsToIPAddress(), ConnectionTimeout, OnConnectionEstablished, OnConnectionFailed); _connection.ConnectionClosed += OnConnectionClosed; if (_connection.IsClosed) { OnConnectionClosed(_connection, SocketError.Success); } }
public TcpConnectionManager(string connectionName, Guid connectionId, ITcpDispatcher dispatcher, IPublisher publisher, IPEndPoint remoteEndPoint, TcpClientConnector connector, bool useSsl, string sslTargetHost, bool sslValidateServer, IPublisher networkSendQueue, IAuthenticationProvider authProvider, TimeSpan heartbeatInterval, TimeSpan heartbeatTimeout, Action <TcpConnectionManager> onConnectionEstablished, Action <TcpConnectionManager, SocketError> onConnectionClosed) { Ensure.NotEmptyGuid(connectionId, "connectionId"); Ensure.NotNull(dispatcher, "dispatcher"); Ensure.NotNull(publisher, "publisher"); Ensure.NotNull(authProvider, "authProvider"); Ensure.NotNull(remoteEndPoint, "remoteEndPoint"); Ensure.NotNull(connector, "connector"); if (useSsl) { Ensure.NotNull(sslTargetHost, "sslTargetHost"); } ConnectionId = connectionId; ConnectionName = connectionName; _tcpEnvelope = new SendOverTcpEnvelope(this, networkSendQueue); _publisher = publisher; _dispatcher = dispatcher; _authProvider = authProvider; _framer = new LengthPrefixMessageFramer(); _framer.RegisterMessageArrivedCallback(OnMessageArrived); _weakThisEnvelope = new SendToWeakThisEnvelope(this); _heartbeatInterval = heartbeatInterval; _heartbeatTimeout = heartbeatTimeout; _connectionPendingSendBytesThreshold = ESConsts.UnrestrictedPendingSendBytes; _connectionQueueSizeThreshold = ESConsts.MaxConnectionQueueSize; _connectionEstablished = onConnectionEstablished; _connectionClosed = onConnectionClosed; RemoteEndPoint = remoteEndPoint; _connection = useSsl ? connector.ConnectSslTo(ConnectionId, remoteEndPoint, ConnectionTimeout, sslTargetHost, sslValidateServer, OnConnectionEstablished, OnConnectionFailed) : connector.ConnectTo(ConnectionId, remoteEndPoint, ConnectionTimeout, OnConnectionEstablished, OnConnectionFailed); _connection.ConnectionClosed += OnConnectionClosed; if (_connection.IsClosed) { OnConnectionClosed(_connection, SocketError.Success); } }
public Connection CreateTcpConnection(CommandProcessorContext context, Action <Connection, TcpPackage> handlePackage, Action <Connection> connectionEstablished = null, Action <Connection, SocketError> connectionClosed = null, bool failContextOnError = true, IPEndPoint tcpEndPoint = null) { var connectionCreatedEvent = new ManualResetEventSlim(false); Connection typedConnection = null; Action <ITcpConnection> onConnectionEstablished = conn => { // we execute callback on ThreadPool because on FreeBSD it can be called synchronously // causing deadlock ThreadPool.QueueUserWorkItem(_ => { if (!InteractiveMode) { Log.Information( "TcpTypedConnection: connected to [{remoteEndPoint}, L{localEndPoint}, {connectionId:B}].", conn.RemoteEndPoint, conn.LocalEndPoint, conn.ConnectionId); } if (connectionEstablished != null) { if (!connectionCreatedEvent.Wait(10000)) { throw new Exception("TcpTypedConnection: creation took too long!"); } connectionEstablished(typedConnection); } }); }; Action <ITcpConnection, SocketError> onConnectionFailed = (conn, error) => { Log.Error( "TcpTypedConnection: connection to [{remoteEndPoint}, L{localEndPoint}, {connectionId:B}] failed. Error: {e}.", conn.RemoteEndPoint, conn.LocalEndPoint, conn.ConnectionId, error); if (connectionClosed != null) { connectionClosed(null, error); } if (failContextOnError) { context.Fail(reason: string.Format("Socket connection failed with error {0}.", error)); } }; ITcpConnection connection; if (UseSsl) { if (string.IsNullOrEmpty(TargetHost)) { context.Fail(reason: "TargetHost is required if using SSL"); } connection = _connector.ConnectSslTo( Guid.NewGuid(), tcpEndPoint ?? TcpEndpoint, TcpConnectionManager.ConnectionTimeout, TargetHost, ValidateServer, onConnectionEstablished, onConnectionFailed, verbose: !InteractiveMode); } else { connection = _connector.ConnectTo( Guid.NewGuid(), tcpEndPoint ?? TcpEndpoint, TcpConnectionManager.ConnectionTimeout, onConnectionEstablished, onConnectionFailed, verbose: !InteractiveMode); } typedConnection = new Connection(connection, new RawMessageFormatter(_bufferManager), new LengthPrefixMessageFramer()); typedConnection.ConnectionClosed += (conn, error) => { if (!InteractiveMode || error != SocketError.Success) { Log.Information( "TcpTypedConnection: connection [{remoteEndPoint}, L{localEndPoint}] was closed {status}", conn.RemoteEndPoint, conn.LocalEndPoint, error == SocketError.Success ? "cleanly." : "with error: " + error + "."); } if (connectionClosed != null) { connectionClosed(conn, error); } else { Log.Information("connectionClosed callback was null"); } }; connectionCreatedEvent.Set(); typedConnection.ReceiveAsync( (conn, pkg) => { var package = new TcpPackage(); bool validPackage = false; try { package = TcpPackage.FromArraySegment(new ArraySegment <byte>(pkg)); validPackage = true; if (package.Command == TcpCommand.HeartbeatRequestCommand) { var resp = new TcpPackage(TcpCommand.HeartbeatResponseCommand, Guid.NewGuid(), null); conn.EnqueueSend(resp.AsByteArray()); return; } handlePackage(conn, package); } catch (Exception ex) { Log.Information(ex, "TcpTypedConnection: [{remoteEndPoint}, L{localEndPoint}] ERROR for {package}. Connection will be closed.", conn.RemoteEndPoint, conn.LocalEndPoint, validPackage ? package.Command as object : "<invalid package>"); conn.Close(ex.Message); if (failContextOnError) { context.Fail(ex); } } }); return(typedConnection); }