Beispiel #1
0
        /// <inheritdoc />
        public async Task SendResponseAsync(HttpResponse response)
        {
            manager.ServerConfiguration.AddServerHeaders(response);
            var frames = HeaderHelper.GenerateFrames(response, frameIdentifier, manager.MaximumFrameSize, response.DataStream == null);

            foreach (var frame in frames)
            {
                manager.SendFrame(frame);
            }

            frames = GenerateDataFrames(response);
            foreach (var frame in frames)
            {
                manager.SendFrame(frame);
            }
        }
Beispiel #2
0
        private void ReadHeadersFrame([NotNull] Frame frame)
        {
            if (frame.Identifier == 0)
            {
                throw new ConnectionException(frame.Identifier, ErrorCode.Protocol);
            }

            var endStream  = frame.Flags.HasFlag(FrameFlags.EndStream);
            var endHeaders = frame.Flags.HasFlag(FrameFlags.EndHeaders);
            var padded     = frame.Flags.HasFlag(FrameFlags.Padded);
            var priority   = frame.Flags.HasFlag(FrameFlags.Priority);

            var stream = GetStream(frame.Identifier);

            switch (stream.State)
            {
            case StreamState.Idle:
                break;

            case StreamState.HeadersExpectingContinuation:
                throw new ConnectionException(frame.Identifier, ErrorCode.Protocol);

            case StreamState.Open:
                if (!endStream)
                {
                    throw new ConnectionException(frame.Identifier, ErrorCode.Protocol);
                }

                if (!endHeaders)
                {
                    throw new NotImplementedException();
                }
                stream.State = StreamState.HalfClosedRemote;
                stream.TwoWayStream.CloseRead();
                // TODO: Read chunked headers
                return;

            case StreamState.HalfClosedRemote:
            case StreamState.Reset:
            case StreamState.Closed:
                throw new ConnectionException(frame.Identifier, ErrorCode.Protocol);

            default:
                throw new ArgumentOutOfRangeException();
            }

            byte        paddingLength = 0;
            StreamState nextState;

            if (endStream)
            {
                nextState = StreamState.HalfClosedRemote;
            }
            else if (endHeaders)
            {
                nextState = StreamState.Open;
            }
            else
            {
                nextState = StreamState.HeadersExpectingContinuation;
            }

            if (padded)
            {
                paddingLength = frame.ReadByte();
            }

            if (priority)
            {
                var streamDependancy = frame.ReadUInt32();
                var exclusive        = streamDependancy & 0x80000000;
                streamDependancy &= 0x7FFFFFFF;
                var weight = frame.ReadByte();

                // TODO
            }

            if (paddingLength + frame.Pointer > frame.Length)
            {
                throw new ConnectionException(frame.Identifier, ErrorCode.Protocol);
            }

            try
            {
                var headerHelper  = new HeaderHelper(frame);
                var readAllStatus = false;
                while (frame.Pointer < frame.Length - paddingLength)
                {
                    var(headerName, headerValue) = headerHelper.ReadValue();

                    switch (headerName)
                    {
                    case ":authority":
                        if (readAllStatus)
                        {
                            throw new StreamException(frame.Identifier, ErrorCode.Protocol);
                        }
                        stream.Authority = headerValue;
                        break;

                    case ":method":
                        if (readAllStatus)
                        {
                            throw new StreamException(frame.Identifier, ErrorCode.Protocol);
                        }
                        stream.Method = headerValue;
                        break;

                    case ":path":
                        if (readAllStatus)
                        {
                            throw new StreamException(frame.Identifier, ErrorCode.Protocol);
                        }
                        stream.Path = headerValue;
                        break;

                    case ":scheme":
                        if (readAllStatus)
                        {
                            throw new StreamException(frame.Identifier, ErrorCode.Protocol);
                        }
                        stream.Scheme = headerValue;
                        break;

                    case ":status":
                        throw new StreamException(frame.Identifier, ErrorCode.Protocol);

                    default:
                        if (headerName.StartsWith(":", StringComparison.InvariantCulture))
                        {
                            throw new StreamException(frame.Identifier, ErrorCode.Protocol);
                        }
                        readAllStatus = true;
                        stream.Headers.Add((headerName, headerValue));
                        break;
                    }
                }
            }
            catch (CompressionException e)
            {
                throw new ConnectionException(frame.Identifier, ErrorCode.Compression, e);
            }

            stream.State = nextState;

            if (endHeaders)
            {
                taskFactory.StartNew(() => stream.SendHeaders(processClient));
            }
        }