/// <summary> /// Waits for a client to connect to the pipe. /// </summary> /// <param name="cancellationToken">A token to cancel the request.</param> /// <exception cref="IOException">Thrown when the connection fails.</exception> public async Task WaitForConnectionAsync(CancellationToken cancellationToken = default) { PipeOptions pipeOptionsToPass; if (this.options == null) { pipeOptionsToPass = PipeOptions.Asynchronous; } else { pipeOptionsToPass = this.options.Value | PipeOptions.Asynchronous; } this.rawPipeStream = new NamedPipeServerStream(this.pipeName, PipeDirection.InOut, 5, PipeTransmissionMode.Byte, pipeOptionsToPass); this.rawPipeStream.ReadMode = PipeTransmissionMode.Byte; //this.logger.Log(() => $"Set up named pipe server '{this.pipeName}'."); await this.rawPipeStream.WaitForConnectionAsync(cancellationToken).ConfigureAwait(false); //this.logger.Log(() => $"Connected to client '{this.pipeName}'."); var wrappedPipeStream = new PipeStreamWrapper(this.rawPipeStream, this.logger); this.Invoker = new MethodInvoker <TRequesting>(wrappedPipeStream, this.messageProcessor); var requestHandler = new RequestHandler <THandling>(wrappedPipeStream, this.handlerFactoryFunc); this.messageProcessor.StartProcessing(wrappedPipeStream); }
/// <summary> /// Connects the pipe to the server. /// </summary> /// <param name="cancellationToken">A token to cancel the request.</param> /// <exception cref="IOException">Thrown when the connection fails.</exception> public async Task ConnectAsync(CancellationToken cancellationToken = default) { if (this.State != PipeState.NotOpened) { throw new InvalidOperationException("Can only call ConnectAsync once"); } //this.logger.Log(() => $"Connecting to named pipe '{this.pipeName}' on machine '{this.serverName}'"); if (this.options != null) { this.rawPipeStream = new NamedPipeClientStream(this.serverName, this.pipeName, PipeDirection.InOut, this.options.Value | PipeOptions.Asynchronous, this.impersonationLevel.Value, this.inheritability.Value); } else { this.rawPipeStream = new NamedPipeClientStream(this.serverName, this.pipeName, PipeDirection.InOut, PipeOptions.Asynchronous); } await this.rawPipeStream.ConnectAsync(cancellationToken).ConfigureAwait(false); //this.logger.Log(() => "Connected."); this.rawPipeStream.ReadMode = PipeTransmissionMode.Byte; this.wrappedPipeStream = new PipeStreamWrapper(this.rawPipeStream, this.logger); this.Invoker = new MethodInvoker <TRequesting>(this.wrappedPipeStream, this.messageProcessor); this.messageProcessor.StartProcessing(wrappedPipeStream); }
/// <summary> /// Initializes a new instance of the <see cref="MethodInvoker" /> class. /// </summary> /// <param name="pipeStreamWrapper">The pipe stream wrapper to use for invocation and response handling.</param> public MethodInvoker(PipeStreamWrapper pipeStreamWrapper, PipeMessageProcessor pipeHost) { this.pipeStreamWrapper = pipeStreamWrapper; this.pipeStreamWrapper.ResponseHandler = this; this.pipeHost = pipeHost; }
/// <summary> /// Initializes a new instance of the <see cref="RequestHandler"/> class. /// </summary> /// <param name="pipeStreamWrapper">The underlying pipe stream wrapper.</param> /// <param name="handlerFactoryFunc"></param> public RequestHandler(PipeStreamWrapper pipeStreamWrapper, Func <THandling> handlerFactoryFunc) { this.pipeStreamWrapper = pipeStreamWrapper; this.handlerFactoryFunc = handlerFactoryFunc; this.pipeStreamWrapper.RequestHandler = this; }
/// <summary> /// Starts the processing loop on the pipe. /// </summary> public async void StartProcessing(PipeStreamWrapper pipeStreamWrapper) { if (this.State != PipeState.NotOpened) { nlogger_.Error("Can only call connect once for this pipe"); throw new InvalidOperationException("Can only call connect once"); } this.State = PipeState.Connected; try { this.workLoopCancellationTokenSource = new CancellationTokenSource(); // Process messages until canceled. while (true) { this.workLoopCancellationTokenSource.Token.ThrowIfCancellationRequested(); await pipeStreamWrapper.ProcessMessageAsync(this.workLoopCancellationTokenSource.Token).ConfigureAwait(false); } } catch (OperationCanceledException) { //nlogger_.Error("PipeMessageProcessor.StartProcessing() OperationCanceledException"); // This is a normal dispose. this.State = PipeState.Closed; if (this.pipeCloseCompletionSource != null) { this.pipeCloseCompletionSource.TrySetResult(null); } } catch (Exception e) { //nlogger_.Error("PipeMessageProcessor.StartProcessing() Exception - Going to be Pipe closed with error"); this.State = PipeState.Faulted; this.PipeFault = e; if (this.pipeCloseCompletionSource != null) { if (!(e is IOException)) { e = new IOException("Pipe closed with error", e); } this.pipeCloseCompletionSource.TrySetException(e); } nlogger_.Error($"PipeMessageProcessor - Exception Message: [{e.Message}] | Stack: [{e.StackTrace}] | InnerException: [{e.InnerException}]"); } }