Beispiel #1
0
        private async Task HandleConnectionAsync(SocketConnection connection)
        {
            try
            {
                var middlewareTask = _dispatcher.OnConnection(connection);
                var transportTask  = connection.StartAsync();

                await transportTask;
                await middlewareTask;

                connection.Dispose();
            }
            catch (Exception ex)
            {
                _trace.LogCritical(ex, $"Unexpected exception in {nameof(SocketTransport)}.{nameof(HandleConnectionAsync)}.");
            }
        }
Beispiel #2
0
        public async Task StartAsync(IConnectionDispatcher dispatcher)
        {
            Exception sendError = null;

            try
            {
                dispatcher.OnConnection(this);

                // Spawn send and receive logic
                Task             receiveTask = DoReceive();
                Task <Exception> sendTask    = DoSend();

                // If the sending task completes then close the receive
                // We don't need to do this in the other direction because the kestrel
                // will trigger the output closing once the input is complete.
                if (await Task.WhenAny(receiveTask, sendTask) == sendTask)
                {
                    // Tell the reader it's being aborted
                    _socket.Dispose();
                }

                // Now wait for both to complete
                await receiveTask;
                sendError = await sendTask;

                // Dispose the socket(should noop if already called)
                _socket.Dispose();
                _receiver.Dispose();
                _sender.Dispose();
                ThreadPool.QueueUserWorkItem(state => ((QuicConnection)state).CancelConnectionClosedToken(), this);
            }
            catch (Exception ex)
            {
                _logger.LogError(0, ex, $"Unexpected exception in {nameof(QuicConnection)}.{nameof(StartAsync)}.");
            }
            finally
            {
                // Complete the output after disposing the socket
                Output.Complete(sendError);
            }
        }
Beispiel #3
0
        public async Task StartAsync(IConnectionDispatcher connectionDispatcher)
        {
            try
            {
                connectionDispatcher.OnConnection(this);

                // Spawn send and receive logic
                var receiveTask = DoReceive();
                var sendTask    = DoSend();

                // Now wait for both to complete
                await receiveTask;
                await sendTask;

                _receiver.Dispose();
                _sender.Dispose();
                ThreadPool.QueueUserWorkItem(state => ((SocketConnection)state).CancelConnectionClosedToken(), this);
            }
            catch (Exception ex)
            {
                _trace.LogError(0, ex, $"Unexpected exception in {nameof(SocketConnection)}.{nameof(StartAsync)}.");
            }
        }
Beispiel #4
0
        public void ProcessPacket(TcpHeaderWithOptions header, ReadOnlySpan <byte> data)
        {
            // If there is backpressure just drop the packet
            if (!_flushTask.IsCompleted)
            {
                return;
            }

            _echoTimestamp = header.TimeStamp;
            switch (_state)
            {
            case TcpConnectionState.Listen:
                _maxSegmentSize        = header.MaximumSegmentSize <= 50 || header.MaximumSegmentSize > 1460 ? 1460 : header.MaximumSegmentSize;
                _sendSequenceNumber    = GetRandomSequenceStart();
                _receiveSequenceNumber = header.Header.SequenceNumber;
                // We know we checked for syn in the upper layer so we can ignore that for now
                _partialTcpHeader = Network.Header.Tcp.Create((ushort)LocalPort, (ushort)RemotePort);
                WriteSyncAckPacket();
                _state = TcpConnectionState.Syn_Rcvd;
                break;

            case TcpConnectionState.Syn_Rcvd:
                if (header.Header.SYN)
                {
                    //Console.WriteLine("Another Syn made");
                    return;
                }
                _connectionDispatcher.OnConnection(this);
                var ignore = TransmitLoop();
                _state = TcpConnectionState.Established;
                break;

            case TcpConnectionState.Established:
                if (header.Header.FIN)
                {
                    _receiveSequenceNumber++;
                    _state = TcpConnectionState.Fin_Wait_1;
                    return;
                }
                if (header.Header.RST)
                {
                    //Console.WriteLine("Got RST Should shut down!");
                    return;
                }

                // First lets update our acked squence number;
                _sendAckSequenceNumber = header.Header.AcknowledgmentNumber;

                if (_receiveSequenceNumber != header.Header.SequenceNumber)
                {
                    // We are just going to drop this and wait for a resend
                    return;
                }
                unchecked { _receiveSequenceNumber += (uint)data.Length; }
                var output = Input.GetMemory(data.Length);
                data.CopyTo(output.Span);
                Input.Advance(data.Length);
                // need to do something with the task and make sure we don't overlap the writes
                var task = Input.FlushAsync();
                if (!task.IsCompleted)
                {
                    _flushTask = task.AsTask();
                }
                PendingAck          = true;
                _totalBytesWritten += data.Length;
                break;

            case TcpConnectionState.Fin_Wait_1:
            case TcpConnectionState.Fin_Wait_2:
                break;

            default:
                throw new NotImplementedException($"Unknown tcp state?? {_state}");
            }
        }