Пример #1
0
        public bool TryProcess(CommandProcessorContext context, string[] args, out int exitCode)
        {
            var commandName = args[0].ToUpper();
            var commandArgs = args.Skip(1).ToArray();

            ICmdProcessor commandProcessor;
            if (!_processors.TryGetValue(commandName, out commandProcessor))
            {
                _log.Info("Unknown command: {0}.", commandName);
                if (_regCommandsProcessor != null)
                    _regCommandsProcessor.Execute(context, new string[0]);
                exitCode = 1;
                return false;
            }

            int exitC = 0;
            var executedEvent = new AutoResetEvent(false);

            ThreadPool.QueueUserWorkItem(_ =>
            {
                try
                {
                    var syntaxOk = commandProcessor.Execute(context, commandArgs);
                    if (syntaxOk)
                    {
                        exitC = context.ExitCode;
                    }
                    else
                    {
                        exitC = 1;
                        _log.Info("Usage of {0}:{1}{2}", commandName, Environment.NewLine, commandProcessor.Usage);
                    }
                    executedEvent.Set();
                }
                catch (Exception exc)
                {
                    _log.ErrorException(exc, "Error while executing command {0}.", commandName);
                    exitC = -1;
                    executedEvent.Set();
                }
            });

            executedEvent.WaitOne(1000);
            context.WaitForCompletion();

            if (!string.IsNullOrWhiteSpace(context.Reason))
                _log.Error("Error during execution of command: {0}.", context.Reason);
            if (context.Error != null)
            {
                _log.ErrorException(context.Error, "Error during execution of command");

                var details = new StringBuilder();
                BuildFullException(context.Error, details);
                _log.Error("Details: {0}", details.ToString());
            }
            
            exitCode = exitC == 0 ? context.ExitCode : exitC;
            return true;
        }
Пример #2
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;

            var connection = _connector.ConnectTo(
                Guid.NewGuid(),
                tcpEndPoint ?? TcpEndpoint,
                conn =>
                {
                    // we execute callback on ThreadPool because on FreeBSD it can be called synchronously
                    // causing deadlock
                    ThreadPool.QueueUserWorkItem(_ => 
                    {
                        if (!InteractiveMode)
                            Log.Info("Connected to [{0}, L{1}].", conn.RemoteEndPoint, conn.LocalEndPoint);
                        if (connectionEstablished != null)
                        {
                            if (!connectionCreatedEvent.Wait(10000))
                                throw new Exception("TcpTypedConnection creation took too long!");
                            connectionEstablished(typedConnection);
                        }
                    });
                },
                (conn, error) =>
                {
                    var message = string.Format("Connection to [{0}, L{1}] failed. Error: {2}.",
                                                conn.RemoteEndPoint, conn.LocalEndPoint, error);
                    Log.Error(message);

                    if (connectionClosed != null)
                        connectionClosed(null, error);

                    if (failContextOnError)
                        context.Fail(reason: string.Format("Socket connection failed with error {0}.", error));
                },
                verbose: !InteractiveMode);

            typedConnection = new Connection(connection, new RawMessageFormatter(_bufferManager), new LengthPrefixMessageFramer());
            typedConnection.ConnectionClosed +=
                (conn, error) =>
                {
                    if (!InteractiveMode || error != SocketError.Success)
                    {
                        Log.Info("Connection [{0}, L{1}] was closed {2}",
                                 conn.RemoteEndPoint, conn.LocalEndPoint,
                                 error == SocketError.Success ? "cleanly." : "with error: " + error + ".");
                    }

                    if (connectionClosed != null)
                        connectionClosed(conn, error);
                    else
                        Log.Info("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.InfoException(ex,
                                          "[{0}, L{1}] ERROR for {2}. 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;
        }
Пример #3
0
        private int Execute(string[] args)
        {
            Log.Info("Processing command: {0}.", string.Join(" ", args));

            var context = new CommandProcessorContext(this, Log, new ManualResetEventSlim(true));

            int exitCode;
            if (_commands.TryProcess(context, args, out exitCode))
            {
                Log.Info("Command exited with code {0}.", exitCode);
                return exitCode;
            }

            return exitCode;
        }
Пример #4
0
        public Connection CreateTcpConnection(CommandProcessorContext context, 
                                              Action<Connection, TcpPackage> handlePackage,
                                              Action<Connection> connectionEstablished = null,
                                              Action<Connection, SocketError> connectionClosed = null,
                                              bool failContextOnError = true)
        {
            var connectionCreatedEvent = new AutoResetEvent(false);
            Connection typedConnection = null;

            var connection = _connector.ConnectTo(
                TcpEndpoint,
                conn =>
                {
                    Log.Info("Connected to [{0}].", conn.EffectiveEndPoint);
                    if (connectionEstablished != null)
                    {
                        connectionCreatedEvent.WaitOne(500);
                        connectionEstablished(typedConnection);
                    }
                },
                (conn, error) =>
                {
                    var message = string.Format("Connection to [{0}] failed. Error: {1}.",
                                                conn.EffectiveEndPoint,
                                                error);
                    Log.Error(message);

                    if (connectionClosed != null)
                        connectionClosed(null, error);

                    if (failContextOnError)
                        context.Fail(reason: string.Format("Socket connection failed with error {0}.", error));
                });

            typedConnection = new Connection(connection, new RawMessageFormatter(_bufferManager), new LengthPrefixMessageFramer());
            typedConnection.ConnectionClosed +=
                (conn, error) =>
                {
                    Log.Info("Connection [{0}] was closed {1}",
                                conn.EffectiveEndPoint,
                                error == SocketError.Success ? "cleanly." : "with error: " + error + ".");

                    if (connectionClosed != null)
                        connectionClosed(conn, error);
                    else
                        Log.Info("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.InfoException(ex,
                                          "[{0}] ERROR for {1}. Connection will be closed.",
                                          conn.EffectiveEndPoint,
                                          validPackage ? package.Command as object : "<invalid package>");
                        conn.Close();

                        if (failContextOnError)
                            context.Fail(ex);
                    }
                });

            return typedConnection;
        }
Пример #5
0
        /// <summary>
        /// Creates a new raw TCP connection
        /// </summary>
        /// <param name="context"></param>
        /// <param name="handlePackage"></param>
        /// <param name="connectionEstablished"></param>
        /// <param name="connectionClosed"></param>
        /// <param name="failContextOnError"></param>
        /// <param name="tcpEndPoint"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        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));
                }
            };

            var            endpoint = tcpEndPoint ?? TcpEndpoint;
            ITcpConnection connection;

            if (_useSsl)
            {
                connection = _connector.ConnectSslTo(
                    Guid.NewGuid(),
                    endpoint.GetHost(),
                    endpoint.ResolveDnsToIPAddress(),
                    TcpConnectionManager.ConnectionTimeout,
                    (cert, chain, err) => (err == SslPolicyErrors.None || !_validateServer, err.ToString()),
                    () => null,
                    onConnectionEstablished,
                    onConnectionFailed,
                    verbose: !_interactiveMode);
            }
            else
            {
                connection = _connector.ConnectTo(
                    Guid.NewGuid(),
                    endpoint.ResolveDnsToIPAddress(),
                    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);
        }
Пример #6
0
        public bool TryProcess(CommandProcessorContext context, string[] args, out int exitCode)
        {
            var commandName = args[0].ToUpper();
            var commandArgs = args.Skip(1).ToArray();

            ICmdProcessor commandProcessor;

            if (!_processors.TryGetValue(commandName, out commandProcessor))
            {
                _log.Information("Unknown command: {command}.", commandName);
                if (_regCommandsProcessor != null)
                {
                    _regCommandsProcessor.Execute(context, new string[0]);
                }
                exitCode = 1;
                return(false);
            }

            int exitC         = 0;
            var executedEvent = new AutoResetEvent(false);

            ThreadPool.QueueUserWorkItem(_ => {
                try {
                    var syntaxOk = commandProcessor.Execute(context, commandArgs);
                    if (syntaxOk)
                    {
                        exitC = context.ExitCode;
                    }
                    else
                    {
                        exitC = 1;
                        _log.Information("Usage of {command}:{newLine}{usage}", commandName, Environment.NewLine,
                                         commandProcessor.Usage);
                    }

                    executedEvent.Set();
                } catch (Exception exc) {
                    _log.Error(exc, "Error while executing command {command}.", commandName);
                    exitC = -1;
                    executedEvent.Set();
                }
            });

            executedEvent.WaitOne(1000);
            context.WaitForCompletion();

            if (!string.IsNullOrWhiteSpace(context.Reason))
            {
                _log.Error("Error during execution of command: {e}.", context.Reason);
            }
            if (context.Error != null)
            {
                _log.Error(context.Error, "Error during execution of command");

                var details = new StringBuilder();
                BuildFullException(context.Error, details);
                _log.Error("Details: {details}", details.ToString());
            }

            exitCode = exitC == 0 ? context.ExitCode : exitC;
            return(true);
        }
Пример #7
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 AutoResetEvent(false);
            Connection typedConnection        = null;

            var connection = _connector.ConnectTo(
                tcpEndPoint ?? TcpEndpoint,
                conn =>
            {
                Log.Info("Connected to [{0}].", conn.EffectiveEndPoint);
                if (connectionEstablished != null)
                {
                    connectionCreatedEvent.WaitOne(500);
                    connectionEstablished(typedConnection);
                }
            },
                (conn, error) =>
            {
                var message = string.Format("Connection to [{0}] failed. Error: {1}.",
                                            conn.EffectiveEndPoint,
                                            error);
                Log.Error(message);

                if (connectionClosed != null)
                {
                    connectionClosed(null, error);
                }

                if (failContextOnError)
                {
                    context.Fail(reason: string.Format("Socket connection failed with error {0}.", error));
                }
            });

            typedConnection = new Connection(connection, new RawMessageFormatter(_bufferManager), new LengthPrefixMessageFramer());
            typedConnection.ConnectionClosed +=
                (conn, error) =>
            {
                Log.Info("Connection [{0}] was closed {1}",
                         conn.EffectiveEndPoint,
                         error == SocketError.Success ? "cleanly." : "with error: " + error + ".");

                if (connectionClosed != null)
                {
                    connectionClosed(conn, error);
                }
                else
                {
                    Log.Info("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.InfoException(ex,
                                      "[{0}] ERROR for {1}. Connection will be closed.",
                                      conn.EffectiveEndPoint,
                                      validPackage ? package.Command as object : "<invalid package>");
                    conn.Close();

                    if (failContextOnError)
                    {
                        context.Fail(ex);
                    }
                }
            });

            return(typedConnection);
        }