Exemple #1
0
        async Task BridgeSocketConnectionAsync(Socket socket)
        {
            EventTraceActivity bridgeActivity = BridgeEventSource.NewActivity("LocalForwardBridgeConnection");

            try
            {
                BridgeEventSource.Log.LocalForwardBridgeConnectionStarting(bridgeActivity, localEndpoint, HybridConnectionClient);

                socket.SendBufferSize = socket.ReceiveBufferSize = 65536;
                socket.SendTimeout    = 60000;
                var tcpstream = new NetworkStream(socket);

                using (var hybridConnectionStream = await HybridConnectionClient.CreateConnectionAsync())
                {
                    // read and write 4-byte header
                    hybridConnectionStream.WriteTimeout = 60000;

                    // write the 1.0 header with the portname for this connection
                    byte[] portNameBytes = Encoding.UTF8.GetBytes(PortName);
                    byte[] preamble      =
                    {
                        /*major*/ 1,
                        /*minor*/ 0,
                        /*stream */ 0,
                        (byte)portNameBytes.Length
                    };
                    await hybridConnectionStream.WriteAsync(preamble, 0, preamble.Length);

                    await hybridConnectionStream.WriteAsync(portNameBytes, 0, portNameBytes.Length);

                    byte[] replyPreamble = new byte[3];
                    for (int read = 0; read < replyPreamble.Length;)
                    {
                        var r = await hybridConnectionStream.ReadAsync(replyPreamble, read,
                                                                       replyPreamble.Length - read);

                        if (r == 0)
                        {
                            await hybridConnectionStream.ShutdownAsync(CancellationToken.None);

                            await hybridConnectionStream.CloseAsync(CancellationToken.None);

                            throw new InvalidOperationException($"Malformed preamble from server");
                        }
                        read += r;
                    }

                    if (!(replyPreamble[0] == 1 && replyPreamble[1] == 0 && replyPreamble[2] == 0))
                    {
                        // version not supported
                        await hybridConnectionStream.ShutdownAsync(CancellationToken.None);

                        await hybridConnectionStream.CloseAsync(CancellationToken.None);

                        throw new InvalidOperationException($"Unsupported protocol version: Server reply {replyPreamble[0]} {replyPreamble[1]} {replyPreamble[2]}");
                    }


                    BridgeEventSource.Log.LocalForwardBridgeConnectionStart(bridgeActivity, localEndpoint, HybridConnectionClient);

                    try
                    {
                        CancellationTokenSource socketAbort = new CancellationTokenSource();
                        await Task.WhenAll(
                            StreamPump.RunAsync(hybridConnectionStream, tcpstream,
                                                () => socket.Shutdown(SocketShutdown.Send), socketAbort.Token)
                            .ContinueWith((t) => socketAbort.Cancel(), TaskContinuationOptions.OnlyOnFaulted),
                            StreamPump.RunAsync(tcpstream, hybridConnectionStream,
                                                () => hybridConnectionStream?.Shutdown(), socketAbort.Token))
                        .ContinueWith((t) => socketAbort.Cancel(), TaskContinuationOptions.OnlyOnFaulted);

                        using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(1)))
                        {
                            await hybridConnectionStream.CloseAsync(cts.Token);
                        }
                    }
                    catch
                    {
                        if (socket.Connected)
                        {
                            socket.Close(0);
                        }
                        throw;
                    }
                }
                BridgeEventSource.Log.LocalForwardBridgeConnectionStop(bridgeActivity, localEndpoint, HybridConnectionClient);
            }
            catch (Exception e)
            {
                BridgeEventSource.Log.LocalForwardBridgeConnectionFailed(bridgeActivity, e);
            }
        }