public void WriteMoreDataThanCredited_OnlyCreditedDataWritten() { using (Stream transport = new QueueStream()) using (WriteQueue queue = new WriteQueue(transport)) { Task pumpTask = queue.PumpToStreamAsync(); OutputStream output = new OutputStream(1, Framing.Priority.Pri1, queue); FrameReader reader = new FrameReader(transport, false, CancellationToken.None); int dataLength = 0x1FFFF; // More than the 0x10000 default Task writeTask = output.WriteAsync(new byte[dataLength], 0, dataLength); Assert.False(writeTask.IsCompleted); Frame frame = reader.ReadFrameAsync().Result; Assert.False(frame.IsControl); Assert.Equal(0x10000, frame.FrameLength); Task<Frame> nextFrameTask = reader.ReadFrameAsync(); Assert.False(nextFrameTask.IsCompleted); // Free up some space output.AddFlowControlCredit(10); frame = nextFrameTask.Result; Assert.False(frame.IsControl); Assert.Equal(10, frame.FrameLength); nextFrameTask = reader.ReadFrameAsync(); Assert.False(nextFrameTask.IsCompleted); } }
public void WriteMultipleData_OneFramePerWrite() { using (Stream transport = new QueueStream()) using (WriteQueue queue = new WriteQueue(transport)) { Task pumpTask = queue.PumpToStreamAsync(); Stream output = new OutputStream(1, Framing.Priority.Pri1, queue); FrameReader reader = new FrameReader(transport, false, CancellationToken.None); int dataLength = 100; output.Write(new byte[dataLength], 0, dataLength); output.Write(new byte[dataLength * 2], 0, dataLength * 2); output.Write(new byte[dataLength * 3], 0, dataLength * 3); Frame frame = reader.ReadFrameAsync().Result; Assert.False(frame.IsControl); Assert.Equal(dataLength, frame.FrameLength); frame = reader.ReadFrameAsync().Result; Assert.False(frame.IsControl); Assert.Equal(dataLength * 2, frame.FrameLength); frame = reader.ReadFrameAsync().Result; Assert.False(frame.IsControl); Assert.Equal(dataLength * 3, frame.FrameLength); } }
public void StreamException_AfterSendingHeaders_Reset() { MemoryStream rawStream = new MemoryStream(); WriteQueue writeQueue = new WriteQueue(rawStream); HeaderWriter headerWriter = new HeaderWriter(writeQueue); Task pumpTask = writeQueue.PumpToStreamAsync(); Http2ServerStream stream = new Http2ServerStream(1, new TransportInformation(), CreateEnvironment(), writeQueue, headerWriter, CancellationToken.None); Task task = stream.Run(env => { new OwinResponse(env).Write("Hello World"); throw new NotImplementedException(); }); Assert.True(task.IsCompleted); Assert.False(task.IsFaulted); writeQueue.FlushAsync(Priority.Pri7).Wait(); rawStream.Seek(0, SeekOrigin.Begin); FrameReader reader = new FrameReader(rawStream, true, CancellationToken.None); SynReplyFrame reply = (SynReplyFrame)reader.ReadFrameAsync().Result; var headers = FrameHelpers.DeserializeHeaderBlock(new CompressionProcessor().Decompress(reply.CompressedHeaders)); Assert.Equal(2, headers.Count); Assert.Equal(":status", headers[0].Key); Assert.Equal("200 OK", headers[0].Value); Assert.False(reply.IsFin); DataFrame data = (DataFrame)reader.ReadFrameAsync().Result; Assert.Equal("Hello World", FrameHelpers.GetAsciiAt(data.Data)); RstStreamFrame reset = (RstStreamFrame)reader.ReadFrameAsync().Result; Assert.Equal(ResetStatusCode.InternalError, reset.StatusCode); }
public void StreamException_BeforeSendingHeaders_500Response() { MemoryStream rawStream = new MemoryStream(); WriteQueue writeQueue = new WriteQueue(rawStream); HeaderWriter headerWriter = new HeaderWriter(writeQueue); Task pumpTask = writeQueue.PumpToStreamAsync(); Http2ServerStream stream = new Http2ServerStream(1, new TransportInformation(), CreateEnvironment(), writeQueue, headerWriter, CancellationToken.None); Task task = stream.Run(env => { throw new NotImplementedException(); }); Assert.True(task.IsCompleted); Assert.False(task.IsFaulted); writeQueue.FlushAsync(Priority.Pri7).Wait(); rawStream.Seek(0, SeekOrigin.Begin); FrameReader reader = new FrameReader(rawStream, true, CancellationToken.None); Frame frame = reader.ReadFrameAsync().Result; Assert.True(frame.IsControl); ControlFrame controlFrame = (ControlFrame)frame; Assert.Equal(ControlFrameType.SynReply, controlFrame.FrameType); SynReplyFrame reply = (SynReplyFrame)controlFrame; CompressionProcessor compresser = new CompressionProcessor(); var headers = FrameHelpers.DeserializeHeaderBlock(compresser.Decompress(reply.CompressedHeaders)); Assert.Equal(2, headers.Count); Assert.Equal(":status", headers[0].Key); Assert.Equal("500 Internal Server Error", headers[0].Value); Assert.True(reply.IsFin); }
public void CancelRequestAfterReceivingHeaders_ResetSent() { MemoryStream rawStream = new MemoryStream(); WriteQueue writeQueue = new WriteQueue(rawStream); HeaderWriter headerWriter = new HeaderWriter(writeQueue); Task pumpTask = writeQueue.PumpToStreamAsync(); CancellationTokenSource cts = new CancellationTokenSource(); Http2ClientStream clientStream = new Http2ClientStream(1, Priority.Pri3, writeQueue, headerWriter, cts.Token); clientStream.StartRequest(GenerateHeaders(), 0, false); Task<IList<KeyValuePair<string, string>>> responseTask = clientStream.GetResponseAsync(); writeQueue.FlushAsync(Priority.Pri7).Wait(); clientStream.SetReply(GenerateHeaders(), false); var response = responseTask.Result; cts.Cancel(); writeQueue.FlushAsync(Priority.Pri7).Wait(); rawStream.Seek(0, SeekOrigin.Begin); FrameReader reader = new FrameReader(rawStream, true, CancellationToken.None); SynStreamFrame synFrame = (SynStreamFrame)reader.ReadFrameAsync().Result; Assert.True(synFrame.IsFin); RstStreamFrame rstFrame = (RstStreamFrame)reader.ReadFrameAsync().Result; Assert.Equal(ResetStatusCode.Cancel, rstFrame.StatusCode); }
public Http2Session(SecureSocket sessionSocket, ConnectionEnd end, bool usePriorities, bool useFlowControl, IDictionary<string, object> handshakeResult = null) { _ourEnd = end; _usePriorities = usePriorities; _useFlowControl = useFlowControl; _handshakeHeaders = new Dictionary<string, string>(16); ApplyHandshakeResults(handshakeResult); if (_ourEnd == ConnectionEnd.Client) { _remoteEnd = ConnectionEnd.Server; _lastId = -1; // Streams opened by client are odd } else { _remoteEnd = ConnectionEnd.Client; _lastId = 0; // Streams opened by server are even } _goAwayReceived = false; _settingsManager = new SettingsManager(); _comprProc = new CompressionProcessor(_ourEnd); _sessionSocket = sessionSocket; _frameReader = new FrameReader(_sessionSocket); ActiveStreams = new ActiveStreams(); _writeQueue = new WriteQueue(_sessionSocket, ActiveStreams, _usePriorities); if (_sessionSocket != null && sessionSocket.SecureProtocol == SecureProtocol.None) { OurMaxConcurrentStreams = int.Parse(_handshakeHeaders[":max_concurrent_streams"]); RemoteMaxConcurrentStreams = int.Parse(_handshakeHeaders[":max_concurrent_streams"]); InitialWindowSize = int.Parse(_handshakeHeaders[":initial_window_size"]); } else { OurMaxConcurrentStreams = 100; //Spec recommends value 100 by default RemoteMaxConcurrentStreams = 100; InitialWindowSize = 2000000; } _flowControlManager = new FlowControlManager(this); if (!_useFlowControl) { _flowControlManager.Options = (byte) FlowControlOptions.DontUseFlowControl; } SessionWindowSize = 0; _toBeContinuedHeaders = new HeadersList(); }