Beispiel #1
0
        private async Task ReadingLoop()
        {
            try
            {
                if (_state.ProcessHandshake())
                {
                    var w = _connection.Output.Alloc();
                    await w.FlushAsync();
                }
                while (true)
                {
                    var result = await _connection.Input.ReadAsync();

                    var buffer = result.Buffer;
                    if (buffer.IsEmpty && result.IsCompleted)
                    {
                        _connection.Input.Advance(buffer.End);
                        return;
                    }
                    try
                    {
                        while (RecordHandler.ReadRecord(ref buffer, out var messageBuffer) == RecordState.Record)
                        {
                            switch (RecordHandler.CurrentRecordType)
                            {
                            case RecordType.Handshake:
                                var handshakeWriter = _handshakeInput.Writer.Alloc();
                                handshakeWriter.Append(messageBuffer);
                                handshakeWriter.Commit();
                                if (_state.ProcessHandshake())
                                {
                                    var w = _connection.Output.Alloc();
                                    await w.FlushAsync();
                                }
                                if (_state.HandshakeComplete)
                                {
                                    var ignore = ReadingApplicationDataLoop();
                                    _handshakeComplete.TrySetResult(this);
                                }
                                break;

                            case RecordType.Application:
                                if (!_state.HandshakeComplete)
                                {
                                    Alerts.AlertException.ThrowUnexpectedMessage(RecordType.Application);
                                }
                                var applicationWriter = _outputPipe.Writer.Alloc();
                                applicationWriter.Append(messageBuffer);
                                await applicationWriter.FlushAsync();

                                break;

                            case RecordType.ChangeCipherSpec:
                                _state.ChangeCipherSpec();
                                break;

                            case RecordType.Alert:
                                if (buffer.ReadBigEndian <byte>() == 0)
                                {
                                    return;
                                }
                                throw new Alerts.AlertException(buffer);

                            default:
                                Alerts.AlertException.ThrowUnexpectedMessage(RecordHandler.CurrentRecordType);
                                break;
                            }
                        }
                    }
                    catch (Alerts.AlertException alert)
                    {
                        if (!alert.ReceivedFromPeer)
                        {
                            await RecordHandler.WriteAlert(alert);

                            _handshakeComplete.TrySetResult(this);
                        }
                        return;
                    }
                    finally
                    {
                        _connection.Input.Advance(buffer.Start, buffer.End);
                    }
                }
            }
            finally
            {
                _inputPipe.Reader.Complete();
                CloseHandshakePipes();
                Dispose();
            }
        }