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);
            }
        }
Пример #2
0
        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);
            }
        }
Пример #3
0
        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);
        }