public async Task <bool> Send([NotNull] byte[] data, CancellationToken token = default(CancellationToken)) { if (_state != PipeState.Connected) { return(false); } OverlappingPipeServerStream stream = _stream; if (stream == null) { return(false); } await stream.WriteAsync(data, token).ConfigureAwait(false); return(true); }
/// <summary> /// Starts this instance. /// </summary> public void Start() { CancellationTokenSource cts = _cancellationTokenSource; if (cts == null) return; CancellationToken token = cts.Token; _serverTask = Task.Run( async () => { // The disconnect GUID can be set by a disconnect request if the client requests it. Guid disconnectGuid = Guid.Empty; // Create pipe access rule to allow everyone to connect - may want to change this later try { // Create pipe stream. using (OverlappingPipeServerStream stream = new OverlappingPipeServerStream( _server.Name, _server.MaximumConnections, PipeTransmissionMode.Message, InBufferSize, OutBufferSize, _server._pipeSecurity)) { _state = PipeState.Open; // Wait for connection await stream.Connect(token).ConfigureAwait(false); if (!token.IsCancellationRequested) { // Connect this connection to the service. _connectionGuid = _server.Service.Connect(this); if (_connectionGuid != Guid.Empty) { ConnectRequest connectRequest = null; // Set the stream. _stream = stream; _server.Add(); _state = PipeState.AwaitingConnect; try { // Keep going as long as we're connected. while (stream.IsConnected && !token.IsCancellationRequested && _server.Service.State != ServiceControllerStatus.Stopped && _connectionGuid != Guid.Empty) { // Read data in. byte[] data = await stream.ReadAsync(token).ConfigureAwait(false); if (data == null || token.IsCancellationRequested || _server.Service.State == ServiceControllerStatus.Stopped || _connectionGuid == Guid.Empty) break; // Deserialize the incoming message. Message message = Message.Deserialize(data); Request request = message as Request; // We only accept requests, anything else is a protocol error and so we must disconnect. if (request == null) break; if (connectRequest == null) { // We require a connect request to start connectRequest = request as ConnectRequest; if (connectRequest == null) break; _state = PipeState.Connected; _connectionDescription = connectRequest.Description; Log.Add( LoggingLevel.Notification, () => ServiceResources.Not_NamedPipeConnection_Connection, _connectionDescription); await Send( new ConnectResponse(request.ID, _server.Service.ServiceName), token) .ConfigureAwait(false); continue; } CommandRequest commandRequest = request as CommandRequest; if (commandRequest != null) { if (!string.IsNullOrWhiteSpace(commandRequest.CommandLine)) _commands.TryAdd( commandRequest.ID, new ConnectedCommand( _connectionGuid, _server.Service, this, commandRequest, token)); continue; } CommandCancelRequest commandCancelRequest = request as CommandCancelRequest; if (commandCancelRequest != null) { ConnectedCommand cancelled; if (_commands.TryRemove( commandCancelRequest.CancelCommandId, out cancelled)) // ReSharper disable once PossibleNullReferenceException cancelled.Cancel(commandCancelRequest); continue; } DisconnectRequest disconnectRequest = request as DisconnectRequest; if (disconnectRequest != null) { // Set the guid for disconnect. disconnectGuid = disconnectRequest.ID; break; } } } catch (TaskCanceledException) { } if (stream.IsConnected) try { // Try to send disconnect response. using (CancellationTokenSource dts = Constants.FireAndForgetTokenSource) await Send( new DisconnectResponse(disconnectGuid), dts.Token) .ConfigureAwait(false); } catch (TaskCanceledException) { } } } // Remove the stream. _stream = null; _state = PipeState.Closed; } } catch (TaskCanceledException) { // Don't log cancellation. } catch (IOException ioe) { if (!token.IsCancellationRequested) // Common exception caused by sudden disconnect, lower level Log.Add( ioe, LoggingLevel.Information, () => ServiceResources.Err_NamedPipeConnection_Failed); } catch (Exception exception) { if (!token.IsCancellationRequested) Log.Add( exception, LoggingLevel.Error, () => ServiceResources.Err_NamedPipeConnection_Failed); } finally { Dispose(); } }, token); }
/// <summary> /// Starts this instance. /// </summary> public void Start() { CancellationTokenSource cts = _cancellationTokenSource; if (cts == null) { return; } CancellationToken token = cts.Token; _serverTask = Task.Run( async() => { // The disconnect GUID can be set by a disconnect request if the client requests it. Guid disconnectGuid = Guid.Empty; // Create pipe access rule to allow everyone to connect - may want to change this later try { // Create pipe stream. using (OverlappingPipeServerStream stream = new OverlappingPipeServerStream( _server.Name, _server.MaximumConnections, PipeTransmissionMode.Message, InBufferSize, OutBufferSize, _server._pipeSecurity)) { _state = PipeState.Open; // Wait for connection await stream.Connect(token).ConfigureAwait(false); if (!token.IsCancellationRequested) { // Connect this connection to the service. _connectionGuid = _server.Service.Connect(this); if (_connectionGuid != Guid.Empty) { ConnectRequest connectRequest = null; // Set the stream. _stream = stream; _server.Add(); _state = PipeState.AwaitingConnect; try { // Keep going as long as we're connected. while (stream.IsConnected && !token.IsCancellationRequested && _server.Service.State != ServiceControllerStatus.Stopped && _connectionGuid != Guid.Empty) { // Read data in. byte[] data = await stream.ReadAsync(token).ConfigureAwait(false); if (data == null || token.IsCancellationRequested || _server.Service.State == ServiceControllerStatus.Stopped || _connectionGuid == Guid.Empty) { break; } // Deserialize the incoming message. Message message = Message.Deserialize(data); Request request = message as Request; // We only accept requests, anything else is a protocol error and so we must disconnect. if (request == null) { break; } if (connectRequest == null) { // We require a connect request to start connectRequest = request as ConnectRequest; if (connectRequest == null) { break; } _state = PipeState.Connected; _connectionDescription = connectRequest.Description; Log.Add( LoggingLevel.Notification, () => ServiceResources.Not_NamedPipeConnection_Connection, _connectionDescription); await Send( new ConnectResponse(request.ID, _server.Service.ServiceName), token) .ConfigureAwait(false); continue; } CommandRequest commandRequest = request as CommandRequest; if (commandRequest != null) { if (!string.IsNullOrWhiteSpace(commandRequest.CommandLine)) { _commands.TryAdd( commandRequest.ID, new ConnectedCommand( _connectionGuid, _server.Service, this, commandRequest, token)); } continue; } CommandCancelRequest commandCancelRequest = request as CommandCancelRequest; if (commandCancelRequest != null) { ConnectedCommand cancelled; if (_commands.TryRemove( commandCancelRequest.CancelCommandId, out cancelled)) { // ReSharper disable once PossibleNullReferenceException cancelled.Cancel(commandCancelRequest); } continue; } DisconnectRequest disconnectRequest = request as DisconnectRequest; if (disconnectRequest != null) { // Set the guid for disconnect. disconnectGuid = disconnectRequest.ID; break; } } } catch (TaskCanceledException) { } if (stream.IsConnected) { try { // Try to send disconnect response. using (CancellationTokenSource dts = Constants.FireAndForgetTokenSource) await Send( new DisconnectResponse(disconnectGuid), dts.Token) .ConfigureAwait(false); } catch (TaskCanceledException) { } } } } // Remove the stream. _stream = null; _state = PipeState.Closed; } } catch (TaskCanceledException) { // Don't log cancellation. } catch (IOException ioe) { if (!token.IsCancellationRequested) { // Common exception caused by sudden disconnect, lower level Log.Add( ioe, LoggingLevel.Information, () => ServiceResources.Err_NamedPipeConnection_Failed); } } catch (Exception exception) { if (!token.IsCancellationRequested) { Log.Add( exception, LoggingLevel.Error, () => ServiceResources.Err_NamedPipeConnection_Failed); } } finally { Dispose(); } }, token); }