Ejemplo n.º 1
0
        /// <summary>
        /// Relay all received by one stream to another stream.
        /// </summary>
        public static Task RelayToAsync(
            this INetworkStream readStream,
            INetworkStream writeStream,
            CancellationToken token)
        {
            return(Task.Run(async() =>
            {
                // Use a buffer that is as large as possible, but does not exceed
                // any of the two stream's capabilities.
                int bufferSize = Math.Min(
                    writeStream.MaxWriteSize,
                    Math.Max(
                        MaxBufferSize,
                        readStream.MinReadSize));

                var buffer = new byte[bufferSize];

                while (true)
                {
                    token.ThrowIfCancellationRequested();

                    try
                    {
                        TraceSources.Compute.TraceVerbose(
                            "NetworkStream [{0} > {1}]: Reading...",
                            readStream,
                            writeStream);

                        int bytesRead = await readStream.ReadAsync(
                            buffer,
                            0,
                            buffer.Length,
                            token).ConfigureAwait(false);

                        if (bytesRead > 0)
                        {
                            TraceSources.Compute.TraceVerbose(
                                "NetworkStream [{0} > {1}]: Relaying {2} bytes",
                                readStream,
                                writeStream,
                                bytesRead);

                            await writeStream.WriteAsync(buffer, 0, bytesRead, token).ConfigureAwait(false);
                        }
                        else
                        {
                            TraceSources.Compute.TraceVerbose(
                                "NetworkStream [{0} > {1}]: gracefully closed connection",
                                readStream,
                                writeStream);

                            // Propagate.
                            await writeStream.CloseAsync(token).ConfigureAwait(false);

                            break;
                        }
                    }
                    catch (NetworkStreamClosedException e)
                    {
                        TraceSources.Compute.TraceWarning(
                            "NetworkStream [{0} > {1}]: forcefully closed connection: {2}",
                            readStream,
                            writeStream,
                            e.Message);

                        // Propagate.
                        await writeStream.CloseAsync(token).ConfigureAwait(false);

                        break;
                    }
                    catch (Exception e)
                    {
                        TraceSources.Compute.TraceWarning(
                            "NetworkStream [{0} > {1}]: Caught unhandled exception: {2} {3}",
                            readStream,
                            writeStream,
                            e.Message,
                            e.StackTrace);

                        throw;
                    }
                }
            }));
        }