示例#1
0
        public override async Task OnConnectedAsync(ConnectionContext connection)
        {
            var ctx = new MConnectionContext(connection);

            try
            {
                await Handle(ctx);
            }
            catch (Exception e)
            {
                if (ctx.ConnectionClosed.IsCancellationRequested || ctx.LocalEndPoint == null || ctx.RemoteEndPoint == null)
                {
                }
                else
                {
                    throw;
                }
            }
        }
示例#2
0
        private async Task Handle(MConnectionContext ctx)
        {
            ReadHandshake(ctx);

            if (ctx.ConnectionClosed.IsCancellationRequested)
            {
                return;
            }

            _logger.LogInformation(
                $"Received handshake, {ctx.ProtocolVersion}, {ctx.ServerAddress}:{ctx.Port}");

            bool isBackendUp = true;

            using var backendClient = new TcpClient();
            backendClient.NoDelay   = true;
            var connectAttempt = backendClient.BeginConnect(_hostname, _port, null, null);

            isBackendUp = connectAttempt.AsyncWaitHandle.WaitOne(100);

            if (isBackendUp)
            {
                backendClient.EndConnect(connectAttempt);
            }

            if (ctx.Stage == 1 && !isBackendUp)
            {
                ctx.Items["flush"] = false;
                ctx.Items["close"] = false;
                while (!ctx.ConnectionClosed.IsCancellationRequested)
                {
                    ReadResult readResult;
                    try
                    {
                        readResult = await ctx.Transport.Input.ReadAsync();
                    }
                    catch (Exception e)
                    {
                        return;
                    }
                    if (readResult.IsCanceled || readResult.IsCompleted)
                    {
                        _logger.LogInformation("Connection Closed");
                        return;
                    }

                    var buffer = readResult.Buffer;
                    HandlePacket(buffer, ctx);

                    if ((bool)ctx.Items["flush"])
                    {
                        await ctx.Transport.Output.FlushAsync();

                        ctx.Items["flush"] = false;
                    }

                    if ((bool)ctx.Items["close"] /* we don't specifically close, we just hand it back to kestrel to deal with */)
                    {
                        return;
                    }
                }
            }

            await using var backendStream = backendClient.GetStream();

            WriteHandshake(backendStream, ctx.ProtocolVersion, ctx.ServerAddress, ctx.Port, ctx.Stage);

            var reader = PipeReader.Create(backendStream);
            var writer = PipeWriter.Create(backendStream);

            await Task.WhenAny(ctx.Transport.Input.CopyToAsync(writer),
                               reader.CopyToAsync(ctx.Transport.Output));

            await reader.CompleteAsync();

            await writer.CompleteAsync();
        }