예제 #1
0
        public async Task WriteTrailersAsync(IEnumerable <HeaderField> headers)
        {
            HeaderValidationResult hvr = HeaderValidator.ValidateTrailingHeaders(headers);

            if (hvr != HeaderValidationResult.Ok)
            {
                throw new Exception(hvr.ToString());
            }

            var removeStream = false;

            await writeMutex.WaitAsync();

            try
            {
                lock (stateMutex)
                {
                    if (!dataSent)
                    {
                        throw new Exception("试图在没有数据的情况下写入");
                    }

                    switch (state)
                    {
                    case StreamState.Open:
                        state = StreamState.HalfClosedLocal;
                        break;

                    case StreamState.HalfClosedRemote:
                        state        = StreamState.HalfClosedRemote;
                        state        = StreamState.Closed;
                        removeStream = true;
                        break;

                    case StreamState.Idle:
                    case StreamState.ReservedRemote:
                    case StreamState.HalfClosedLocal:
                    case StreamState.Closed:
                        throw new Exception("发送的状态无效");

                    case StreamState.Reset:
                        throw new StreamResetException();

                    case StreamState.ReservedLocal:

                        throw new Exception("意外状态:发送数据后保留本地");
                    }
                }

                await SendHeaders(headers, true); // TODO: Use result
            }
            finally
            {
                writeMutex.Release();
                if (removeStream)
                {
                    connection.UnregisterStream(this);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// 处理传入头的接收
        /// </summary>
        public Http2Error?ProcessHeaders(
            CompleteHeadersFrameData headers)
        {
            var wakeupDataWaiter    = false;
            var wakeupHeaderWaiter  = false;
            var wakeupTrailerWaiter = false;
            var removeStream        = false;

            lock (stateMutex)
            {
                switch (state)
                {
                case StreamState.ReservedLocal:
                case StreamState.ReservedRemote:
                    return(new Http2Error
                    {
                        StreamId = Id,
                        Code = ErrorCode.InternalError,
                        Message = "接收到的头帧处于未覆盖的推送约定状态",
                    });

                case StreamState.Idle:
                case StreamState.Open:
                case StreamState.HalfClosedLocal:
                    if (headersReceived != HeaderReceptionState.ReceivedAllHeaders)
                    {
                        HeaderValidationResult hvr;
                        if (connection.IsServer)
                        {
                            hvr = HeaderValidator.ValidateRequestHeaders(headers.Headers);
                        }
                        else
                        {
                            hvr = HeaderValidator.ValidateResponseHeaders(headers.Headers);
                        }
                        if (hvr != HeaderValidationResult.Ok)
                        {
                            return(new Http2Error
                            {
                                StreamId = Id,
                                Code = ErrorCode.ProtocolError,
                                Message = "Received invalid headers",
                            });
                        }

                        if (!connection.config.IsServer &&
                            headers.Headers.IsInformationalHeaders())
                        {
                            headersReceived =
                                HeaderReceptionState.ReceivedInformationalHeaders;
                        }
                        else
                        {
                            headersReceived =
                                HeaderReceptionState.ReceivedAllHeaders;
                        }
                        wakeupHeaderWaiter      = true;
                        declaredInContentLength = headers.Headers.GetContentLength();
                        inHeaders = headers.Headers;
                    }
                    else if (!dataReceived)
                    {
                        return(new Http2Error
                        {
                            StreamId = Id,
                            Code = ErrorCode.ProtocolError,
                            Message = "接收的无标题",
                        });
                    }
                    else
                    {
                        if (!headers.EndOfStream)
                        {
                            return(new Http2Error
                            {
                                StreamId = Id,
                                Code = ErrorCode.ProtocolError,
                                Message = "接收到没有endofstream标志",
                            });
                        }
                        var hvr = HeaderValidator.ValidateTrailingHeaders(headers.Headers);
                        if (hvr != HeaderValidationResult.Ok)
                        {
                            return(new Http2Error
                            {
                                StreamId = Id,
                                Code = ErrorCode.ProtocolError,
                                Message = "接收到无效",
                            });
                        }


                        if (declaredInContentLength >= 0 &&
                            declaredInContentLength != totalInData)
                        {
                            return(new Http2Error
                            {
                                StreamId = Id,
                                Code = ErrorCode.ProtocolError,
                                Message =
                                    "数据帧的长度与内容长度不匹配",
                            });
                        }

                        wakeupTrailerWaiter = true;
                        inTrailers          = headers.Headers;
                    }

                    if (state == StreamState.Idle)
                    {
                        state = StreamState.Open;
                    }
                    if (headers.EndOfStream)
                    {
                        if (state == StreamState.HalfClosedLocal)
                        {
                            state        = StreamState.Closed;
                            removeStream = true;
                        }
                        else
                        {
                            state = StreamState.HalfClosedRemote;
                        }
                        wakeupTrailerWaiter = true;
                        wakeupDataWaiter    = true;
                    }
                    break;

                case StreamState.HalfClosedRemote:
                case StreamState.Closed:
                    return(new Http2Error
                    {
                        Code = ErrorCode.StreamClosed,
                        StreamId = Id,
                        Message = "已接收封闭流的头",
                    });

                case StreamState.Reset:
                    break;

                default:
                    throw new Exception("未处理的流状态");
                }
            }

            if (wakeupHeaderWaiter)
            {
                readHeadersPossible.Set();
            }
            if (wakeupDataWaiter)
            {
                readDataPossible.Set();
            }
            if (wakeupTrailerWaiter)
            {
                readTrailersPossible.Set();
            }

            if (removeStream)
            {
                connection.UnregisterStream(this);
            }

            return(null);
        }