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 CancelRequestAfterReceivingFin_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(), true);

            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);

            // TODO: Should we send a reset after sending and receiving a fin?
            // Because the write queue gets purged, we're not positive our fin got sent.
            RstStreamFrame rstFrame = (RstStreamFrame)reader.ReadFrameAsync().Result;
            Assert.Equal(ResetStatusCode.Cancel, rstFrame.StatusCode);
        }
        public void CancelRequestAfterSendingHeaders_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 responseTask = clientStream.GetResponseAsync();
            writeQueue.FlushAsync(Priority.Pri7).Wait();

            cts.Cancel();
            Assert.True(responseTask.IsCanceled);
            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);
        }
 protected Http2BaseStream(int id, WriteQueue writeQueue, HeaderWriter headerWriter, CancellationToken cancel)
 {
     _id = id;
     _writeQueue = writeQueue;
     _cancel = cancel;
     _headerWriter = headerWriter;
 }
 public Http2ClientStream(int id, Priority priority, WriteQueue writeQueue, HeaderWriter headerWriter, CancellationToken cancel)
     : base(id, writeQueue, headerWriter, cancel)
 {
     _priority = priority;
     _responseTask = new TaskCompletionSource<IList<KeyValuePair<string, string>>>();
     _outputStream = new OutputStream(id, _priority, writeQueue);
     _cancellation = _cancel.Register(Cancel, this);
 }