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);
        }
Example #6
0
        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();
        }