/// <summary> /// Creates a bidirectionally open stream, /// where the headers in both directions have already been sent but /// no data. /// </summary> public static async Task <Result> CreateConnectionAndStream( bool isServer, ILoggerProvider loggerProvider, IBufferedPipe iPipe, IBufferedPipe oPipe, Settings?localSettings = null, Settings?remoteSettings = null, HuffmanStrategy huffmanStrategy = HuffmanStrategy.Never) { var result = new Result(); if (isServer) { var r1 = await ServerStreamTests.StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, iPipe, oPipe, localSettings, remoteSettings, huffmanStrategy); // Headers have been received but not sent await r1.stream.WriteHeadersAsync(DefaultStatusHeaders, false); await oPipe.ReadAndDiscardHeaders(1u, false); result.conn = r1.conn; result.hEncoder = r1.hEncoder; result.stream = r1.stream; } else { var r1 = await ClientStreamTests.StreamCreator.CreateConnectionAndStream( StreamState.Open, loggerProvider, iPipe, oPipe, localSettings, remoteSettings, huffmanStrategy); // Headers have been sent but not yet received await iPipe.WriteHeaders(r1.hEncoder, 1u, false, DefaultStatusHeaders, true); result.conn = r1.conn; result.hEncoder = r1.hEncoder; result.stream = r1.stream; } return(result); }
public static async Task <Connection> BuildEstablishedConnection( bool isServer, IBufferedPipe inputStream, IBufferedPipe outputStream, ILoggerProvider loggerProvider, Func <IStream, bool> streamListener = null, Settings?localSettings = null, Settings?remoteSettings = null, HuffmanStrategy huffmanStrategy = HuffmanStrategy.Never) { ILogger logger = null; if (loggerProvider != null) { logger = loggerProvider.CreateLogger("http2Con"); } if (streamListener == null) { streamListener = (s) => false; } var config = new ConnectionConfigurationBuilder(isServer) .UseStreamListener(streamListener) .UseHuffmanStrategy(huffmanStrategy) .UseSettings(localSettings ?? Settings.Default) .Build(); var conn = new Connection( config, inputStream, outputStream, new Connection.Options { Logger = logger, }); await PerformHandshakes( conn, inputStream, outputStream, remoteSettings); return(conn); }
public static async Task PerformHandshakes( this Connection connection, IBufferedPipe inputStream, IBufferedPipe outputStream, Settings?remoteSettings = null) { if (connection.IsServer) { await ClientPreface.WriteAsync(inputStream); } var rsettings = remoteSettings ?? Settings.Default; await inputStream.WriteSettings(rsettings); if (!connection.IsServer) { await outputStream.ReadAndDiscardPreface(); } await outputStream.ReadAndDiscardSettings(); await outputStream.AssertSettingsAck(); await inputStream.WriteSettingsAck(); }
public static async Task <Result> CreateClientConnectionAndStream( StreamState state, ILoggerProvider loggerProvider, IBufferedPipe iPipe, IBufferedPipe oPipe, Settings?localSettings = null, Settings?remoteSettings = null, HuffmanStrategy huffmanStrategy = HuffmanStrategy.Never) { if (state == StreamState.Idle) { throw new Exception("Not supported"); } var hEncoder = new Encoder(); var conn = await Http2ConnectionUtils.BuildEstablishedConnection( false, iPipe, oPipe, loggerProvider, null, localSettings : localSettings, remoteSettings : remoteSettings, huffmanStrategy : huffmanStrategy); var endOfStream = false; if (state == StreamState.HalfClosedLocal || state == StreamState.Closed) { endOfStream = true; } var stream = await conn.CreateStreamAsync( DefaultGetHeaders, endOfStream : endOfStream); await oPipe.ReadAndDiscardHeaders(1u, endOfStream); if (state == StreamState.HalfClosedRemote || state == StreamState.Closed) { var outBuf = new byte[Settings.Default.MaxFrameSize]; var result = hEncoder.EncodeInto( new ArraySegment <byte>(outBuf), DefaultStatusHeaders); await iPipe.WriteFrameHeaderWithTimeout( new FrameHeader { Type = FrameType.Headers, Flags = (byte)(HeadersFrameFlags.EndOfHeaders | HeadersFrameFlags.EndOfStream), StreamId = 1u, Length = result.UsedBytes, }); await iPipe.WriteAsync(new ArraySegment <byte>(outBuf, 0, result.UsedBytes)); var readHeadersTask = stream.ReadHeadersAsync(); var combined = await Task.WhenAny(readHeadersTask, Task.Delay( Http2ReadableStreamTestExtensions.ReadTimeout)); Assert.True(readHeadersTask == combined, "Expected to receive headers"); var headers = await readHeadersTask; Assert.True(headers.SequenceEqual(DefaultStatusHeaders)); } else if (state == StreamState.Reset) { await iPipe.WriteResetStream(1u, ErrorCode.Cancel); } return(new Result { hEncoder = hEncoder, conn = conn, stream = stream, }); }
public static async Task <Result> CreateServerConnectionAndStream(HeaderField[] getHeaders, StreamState state, ILoggerProvider loggerProvider, IBufferedPipe iPipe, IBufferedPipe oPipe, Settings?localSettings = null, Settings?remoteSettings = null, HuffmanStrategy huffmanStrategy = HuffmanStrategy.Never) { IStream stream = null; var handlerDone = new SemaphoreSlim(0); if (state == StreamState.Idle) { throw new Exception("Not supported"); } Func <IStream, bool> listener = (s) => { Task.Run(async() => { stream = s; try { await s.ReadHeadersAsync(); if (state == StreamState.Reset) { s.Cancel(); return; } if (state == StreamState.HalfClosedRemote || state == StreamState.Closed) { await s.ReadAllToArrayWithTimeout(); } if (state == StreamState.HalfClosedLocal || state == StreamState.Closed) { await s.WriteHeadersAsync( DefaultStatusHeaders, true); } } finally { handlerDone.Release(); } }); return(true); }; var conn = await Http2ConnectionUtils.BuildEstablishedConnection( true, iPipe, oPipe, loggerProvider, listener, localSettings : localSettings, remoteSettings : remoteSettings, huffmanStrategy : huffmanStrategy); var hEncoder = new Encoder(); await iPipe.WriteHeaders( hEncoder, 1, false, getHeaders); if (state == StreamState.HalfClosedRemote || state == StreamState.Closed) { await iPipe.WriteData(1u, 0, endOfStream : true); } var ok = await handlerDone.WaitAsync( Http2ReadableStreamTestExtensions.ReadTimeout); if (!ok) { throw new Exception("Stream handler did not finish"); } if (state == StreamState.HalfClosedLocal || state == StreamState.Closed) { // Consume the sent headers and data await oPipe.ReadAndDiscardHeaders(1u, true); } else if (state == StreamState.Reset) { // Consume the sent reset frame await oPipe.AssertResetStreamReception(1, ErrorCode.Cancel); } return(new Result { conn = conn, stream = stream, hEncoder = hEncoder, }); }
public FailingPipe(IBufferedPipe inner) { this.inner = inner; }