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; }
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; }
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; }
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; }
/// <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); }
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); }
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); }