public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { var output = _writer.Alloc(); output.Write(new Span <byte>(buffer, offset, count)); await output.FlushAsync(); }
public static async Task CopyToAsync(this IPipelineReader input, IPipelineWriter output) { while (true) { var result = await input.ReadAsync(); var inputBuffer = result.Buffer; var fin = result.IsCompleted; try { if (inputBuffer.IsEmpty && fin) { return; } var buffer = output.Alloc(); buffer.Append(inputBuffer); await buffer.FlushAsync(); } finally { input.Advance(inputBuffer.End); } } }
public static Task WriteAsync(this IPipelineWriter output, Span <byte> source) { var writeBuffer = output.Alloc(); writeBuffer.Write(source); return(writeBuffer.FlushAsync()); }
private Task EndResponse() { var buffer = _output.Alloc(); if (!HasStarted) { WriteBeginResponseHeaders(buffer); } if (_autoChunk) { WriteEndResponse(buffer); } return(buffer.FlushAsync()); }
private void EnsureBuffer() { if (_needAlloc) { _writableBuffer = _writer.Alloc(); _needAlloc = false; } }
private static async Task CopyCompletedAsync(IPipelineReader input, IPipelineWriter output) { var result = await input.ReadAsync(); var inputBuffer = result.Buffer; while (true) { try { if (inputBuffer.IsEmpty && result.IsCompleted) { return; } var buffer = output.Alloc(); buffer.Append(inputBuffer); await buffer.FlushAsync(); } finally { input.Advance(inputBuffer.End); } var awaiter = input.ReadAsync(); if (!awaiter.IsCompleted) { // No more data break; } result = await input.ReadAsync(); inputBuffer = result.Buffer; } }
public override async Task HandleHandshakeMessage(HandshakeType handshakeMessageType, ReadableBuffer buffer, IPipelineWriter pipe) { WritableBuffer writer; switch (State) { case StateType.None: if (handshakeMessageType != HandshakeType.client_hello) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, "Tls 12 didnt get a client hello"); } Hello.ReadClientHelloTls12(buffer, this); if (CipherSuite == null) { //Couldn't agree a set of ciphers Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "Could not agree on a cipher suite during reading client hello"); } this.StartHandshakeHash(buffer); //Write server hello _state = StateType.SendServerHello; writer = pipe.Alloc(); this.WriteHandshake(ref writer, HandshakeType.server_hello, Hello.SendServerHello12); this.WriteHandshake(ref writer, HandshakeType.certificate, ServerHandshakeTls12.SendCertificates); if (CipherSuite.ExchangeType == KeyExchangeType.Ecdhe || CipherSuite.ExchangeType == KeyExchangeType.Dhe) { this.WriteHandshake(ref writer, HandshakeType.server_key_exchange, ServerHandshakeTls12.SendKeyExchange); } await writer.FlushAsync(); break; default: Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, $"Not in any known state {State} that we expected a handshake messge from {handshakeMessageType}"); break; } }
public async Task Execute(IPipelineReader reader, IPipelineWriter writer) { while (true) { var result = await reader.ReadAsync(); var inputBuffer = result.Buffer; if (inputBuffer.IsEmpty) { if (result.IsCompleted) { break; } reader.Advance(inputBuffer.End); continue; } var writerBuffer = writer.Alloc(); var memory = inputBuffer.First; unsafe { // TODO: Pin pointer if not pinned void *inPointer; if (memory.TryGetPointer(out inPointer)) { _deflater.SetInput((IntPtr)inPointer, memory.Length); } else { throw new InvalidOperationException("Pointer needs to be pinned"); } } while (!_deflater.NeedsInput()) { unsafe { void *outPointer; writerBuffer.Ensure(); if (writerBuffer.Memory.TryGetPointer(out outPointer)) { int written = _deflater.ReadDeflateOutput((IntPtr)outPointer, writerBuffer.Memory.Length); writerBuffer.Advance(written); } else { throw new InvalidOperationException("Pointer needs to be pinned"); } } } var consumed = memory.Length - _deflater.AvailableInput; inputBuffer = inputBuffer.Slice(0, consumed); reader.Advance(inputBuffer.End); await writerBuffer.FlushAsync(); } bool flushed = false; do { // Need to do more stuff here var writerBuffer = writer.Alloc(); unsafe { void *pointer; writerBuffer.Ensure(); var memory = writerBuffer.Memory; if (memory.TryGetPointer(out pointer)) { int compressedBytes; flushed = _deflater.Flush((IntPtr)pointer, memory.Length, out compressedBytes); writerBuffer.Advance(compressedBytes); } else { throw new InvalidOperationException("Pointer needs to be pinned"); } } await writerBuffer.FlushAsync(); }while (flushed); bool finished = false; do { // Need to do more stuff here var writerBuffer = writer.Alloc(); unsafe { void *pointer; writerBuffer.Ensure(); var memory = writerBuffer.Memory; if (memory.TryGetPointer(out pointer)) { int compressedBytes; finished = _deflater.Finish((IntPtr)pointer, memory.Length, out compressedBytes); writerBuffer.Advance(compressedBytes); } } await writerBuffer.FlushAsync(); }while (!finished); reader.Complete(); writer.Complete(); _deflater.Dispose(); }
public async Task Execute(IPipelineReader reader, IPipelineWriter writer) { while (true) { var result = await reader.ReadAsync(); var inputBuffer = result.Buffer; if (inputBuffer.IsEmpty) { if (result.IsCompleted) { break; } reader.Advance(inputBuffer.End); continue; } var writerBuffer = writer.Alloc(); var memory = inputBuffer.First; if (memory.Length > 0) { unsafe { void *pointer; if (memory.TryGetPointer(out pointer)) { _inflater.SetInput((IntPtr)pointer, memory.Length); void *writePointer; writerBuffer.Ensure(); if (writerBuffer.Memory.TryGetPointer(out writePointer)) { int written = _inflater.Inflate((IntPtr)writePointer, writerBuffer.Memory.Length); writerBuffer.Advance(written); } else { throw new InvalidOperationException("Pointer needs to be pinned"); } } else { throw new InvalidOperationException("Pointer needs to be pinned"); } var consumed = memory.Length - _inflater.AvailableInput; inputBuffer = inputBuffer.Slice(0, consumed); } } reader.Advance(inputBuffer.End); await writerBuffer.FlushAsync(); } reader.Complete(); writer.Complete(); _inflater.Dispose(); }
public async Task Execute(IPipelineReader reader, IPipelineWriter writer) { while (true) { var result = await reader.ReadAsync(); var inputBuffer = result.Buffer; if (inputBuffer.IsEmpty) { if (result.IsCompleted) { break; } reader.Advance(inputBuffer.End); continue; } var writerBuffer = writer.Alloc(); var memory = inputBuffer.First; unsafe { // TODO: Pin pointer if not pinned void* inPointer; if (memory.TryGetPointer(out inPointer)) { _deflater.SetInput((IntPtr)inPointer, memory.Length); } else { throw new InvalidOperationException("Pointer needs to be pinned"); } } while (!_deflater.NeedsInput()) { unsafe { void* outPointer; writerBuffer.Ensure(); if (writerBuffer.Memory.TryGetPointer(out outPointer)) { int written = _deflater.ReadDeflateOutput((IntPtr)outPointer, writerBuffer.Memory.Length); writerBuffer.Advance(written); } else { throw new InvalidOperationException("Pointer needs to be pinned"); } } } var consumed = memory.Length - _deflater.AvailableInput; inputBuffer = inputBuffer.Slice(0, consumed); reader.Advance(inputBuffer.End); await writerBuffer.FlushAsync(); } bool flushed = false; do { // Need to do more stuff here var writerBuffer = writer.Alloc(); unsafe { void* pointer; writerBuffer.Ensure(); var memory = writerBuffer.Memory; if (memory.TryGetPointer(out pointer)) { int compressedBytes; flushed = _deflater.Flush((IntPtr)pointer, memory.Length, out compressedBytes); writerBuffer.Advance(compressedBytes); } else { throw new InvalidOperationException("Pointer needs to be pinned"); } } await writerBuffer.FlushAsync(); } while (flushed); bool finished = false; do { // Need to do more stuff here var writerBuffer = writer.Alloc(); unsafe { void* pointer; writerBuffer.Ensure(); var memory = writerBuffer.Memory; if (memory.TryGetPointer(out pointer)) { int compressedBytes; finished = _deflater.Finish((IntPtr)pointer, memory.Length, out compressedBytes); writerBuffer.Advance(compressedBytes); } } await writerBuffer.FlushAsync(); } while (!finished); reader.Complete(); writer.Complete(); _deflater.Dispose(); }
public async Task Execute(IPipelineReader reader, IPipelineWriter writer) { while (true) { var result = await reader.ReadAsync(); var inputBuffer = result.Buffer; if (inputBuffer.IsEmpty) { if (result.IsCompleted) { break; } reader.Advance(inputBuffer.End); continue; } var writerBuffer = writer.Alloc(); var memory = inputBuffer.First; if (memory.Length > 0) { unsafe { void* pointer; if (memory.TryGetPointer(out pointer)) { _inflater.SetInput((IntPtr)pointer, memory.Length); void* writePointer; writerBuffer.Ensure(); if (writerBuffer.Memory.TryGetPointer(out writePointer)) { int written = _inflater.Inflate((IntPtr)writePointer, writerBuffer.Memory.Length); writerBuffer.Advance(written); } else { throw new InvalidOperationException("Pointer needs to be pinned"); } } else { throw new InvalidOperationException("Pointer needs to be pinned"); } var consumed = memory.Length - _inflater.AvailableInput; inputBuffer = inputBuffer.Slice(0, consumed); } } reader.Advance(inputBuffer.End); await writerBuffer.FlushAsync(); } reader.Complete(); writer.Complete(); _inflater.Dispose(); }
public async Task HandleHandshakeMessage(HandshakeType handshakeMessageType, ReadableBuffer buffer, IPipelineWriter pipe) { switch (State) { case StateType.WaitServerHello: if (handshakeMessageType == HandshakeType.server_hello) { Hello.ReadServerHello(buffer, this); GenerateHandshakeKeys(); State = StateType.WaitEncryptedExtensions; return; } break; case StateType.WaitEncryptedExtensions: if (handshakeMessageType == HandshakeType.encrypted_extensions) { HandshakeContext(buffer); State = StateType.WaitServerVerification; return; } break; case StateType.WaitServerVerification: if (handshakeMessageType == HandshakeType.certificate) { Handshake.Certificates.ReadCertificates(buffer, Listener); HandshakeContext(buffer); return; } if (handshakeMessageType == HandshakeType.certificate_verify) { HandshakeContext(buffer); State = StateType.WaitServerFinished; return; } break; case StateType.WaitServerFinished: if (handshakeMessageType == HandshakeType.finished) { HandshakeContext(buffer); var hash = new byte[HandshakeHash.HashSize]; HandshakeHash.InterimHash(hash); var writer = pipe.Alloc(); ServerHandshakeTls13.ServerFinished(ref writer, this, KeySchedule.GenerateClientFinishedKey()); _dataForCurrentScheduleSent.Reset(); await writer.FlushAsync(); await _dataForCurrentScheduleSent; GenerateApplicationKeys(hash); KeySchedule.GenerateResumptionSecret(); HandshakeHash.Dispose(); HandshakeHash = null; State = StateType.HandshakeComplete; return; } break; case StateType.HandshakeComplete: if (handshakeMessageType == HandshakeType.new_session_ticket) { Listener.ResumptionProvider.RegisterSessionTicket(buffer); return; } break; } Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, ""); }
public override async Task HandleHandshakeMessage(HandshakeType handshakeMessageType, ReadableBuffer buffer, IPipelineWriter pipe) { WritableBuffer writer; switch (State) { case StateType.None: case StateType.WaitHelloRetry: if (handshakeMessageType != HandshakeType.client_hello) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, $"State is wait hello retry but got {handshakeMessageType}"); } Hello.ReadClientHelloTls13(buffer, this); if (CipherSuite == null) { //Couldn't agree a set of ciphers Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "Could not agree on a cipher suite during reading client hello"); } this.StartHandshakeHash(buffer); //If we can't agree on a schedule we will have to send a hello retry and try again if (!NegotiationComplete()) { writer = pipe.Alloc(); this.WriteHandshake(ref writer, HandshakeType.hello_retry_request, Hello.SendHelloRetry); _state = StateType.WaitHelloRetry; await writer.FlushAsync(); return; } if (PskIdentity != -1 && EarlyDataSupported) { KeySchedule.GenerateEarlyTrafficKey(ref _readKey); Console.WriteLine("Generated Early Traffic Key"); } //Write the server hello, the last of the unencrypted messages _state = StateType.SendServerHello; writer = pipe.Alloc(); this.WriteHandshake(ref writer, HandshakeType.server_hello, Hello.SendServerHello13); //block our next actions because we need to have sent the message before changing keys DataForCurrentScheduleSent.Reset(); await writer.FlushAsync(); await DataForCurrentScheduleSent; _state = StateType.ServerAuthentication; //Generate the encryption keys and send the next set of messages GenerateHandshakeKeys(); writer = pipe.Alloc(); ServerHandshakeTls13.SendFlightOne(ref writer, this); ServerHandshakeTls13.SendFlightOne2(ref writer, this); DataForCurrentScheduleSent.Reset(); await writer.FlushAsync(); await DataForCurrentScheduleSent; writer = pipe.Alloc(); ServerHandshakeTls13.SendFlightOne3(ref writer, this); ServerHandshakeTls13.ServerFinished(ref writer, this, KeySchedule.GenerateServerFinishKey()); DataForCurrentScheduleSent.Reset(); await writer.FlushAsync(); await DataForCurrentScheduleSent; GenerateServerApplicationKey(); if (EarlyDataSupported && PskIdentity != -1) { _state = StateType.WaitEarlyDataFinished; } else { _state = StateType.WaitClientFinished; } return; case StateType.WaitClientFinished: if (handshakeMessageType != HandshakeType.finished) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, $"Waiting for client finished but received {handshakeMessageType}"); } Finished.ReadClientFinished(buffer, this); _readKey?.Dispose(); _readKey = KeySchedule.GenerateClientApplicationKey(); //Hash the finish message now we have made the traffic keys //Then we can make the resumption secret HandshakeHash.HashData(buffer); KeySchedule.GenerateResumptionSecret(); HandshakeHash.Dispose(); HandshakeHash = null; //Send a new session ticket writer = pipe.Alloc(); this.WriteHandshake(ref writer, HandshakeType.new_session_ticket, SessionKeys.CreateNewSessionKey); await writer.FlushAsync(); _state = StateType.HandshakeComplete; break; default: Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, $"Not in any known state {State} that we expected a handshake messge from {handshakeMessageType}"); break; } }