Exemplo n.º 1
0
        /// <summary>
        /// リクエストフレームを入力
        /// </summary>
        /// <param name="frame">リクエストフレーム</param>
        public void HandleRequest(IHttp2Frame frame)
        {
            lock (this.streams)
            {
                Debug.WriteLine($"Request : {frame.ToString()}");

                if (frame.Header.StreamID == 0)
                {
                    this.requestControlStreamReader.HandleFrame(frame);
                }
                else
                {
                    if (frame is Http2RstStreamFrame rstFrame &&
                        (rstFrame.ErrorCode == Http2ErrorCode.Cancel || rstFrame.ErrorCode == Http2ErrorCode.RefusedStream))
                    {
                        // PushPromise で予約した ID に対するキャンセル RFC7540 8.2.2
                        if (this.pushPromises.TryRemove(frame.Header.StreamID, out _))
                        {
                            return;
                        }
                    }
                    if (!this.streams.ContainsKey(frame.Header.StreamID))
                    {
                        this.AddStreamReader(frame);
                    }
                    this.streams[frame.Header.StreamID].HandleRequest(frame);
                }
            }
        }
Exemplo n.º 2
0
 public static void AssertEqualsAndRelease(IHttp2Frame expected, IHttp2Frame actual)
 {
     try
     {
         Assert.Equal(expected, actual);
     }
     finally
     {
         ReferenceCountUtil.Release(expected);
         ReferenceCountUtil.Release(actual);
         // Will return -1 when not implements ReferenceCounted.
         Assert.True(RefCnt(expected) <= 0);
         Assert.True(RefCnt(actual) <= 0);
     }
 }
Exemplo n.º 3
0
        /// <summary>
        /// レスポンスフレームを入力
        /// </summary>
        /// <param name="frame">レスポンスフレーム</param>
        public void HandleResponse(IHttp2Frame frame)
        {
            lock (this.streams)
            {
                Debug.WriteLine($"Response: {frame.ToString()}");

                if (frame.Header.StreamID == 0)
                {
                    this.responseControlStreamReader.HandleFrame(frame);
                }
                else
                {
                    if (!this.streams.ContainsKey(frame.Header.StreamID))
                    {
                        this.AddStreamReader(frame);
                    }
                    this.streams[frame.Header.StreamID].HandleResponse(frame);
                }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// ストリームリストに新規の <see cref="Http2StreamReader"/> を追加
        /// </summary>
        /// <param name="frame">フレーム</param>
        private void AddStreamReader(IHttp2Frame frame)
        {
            Http2StreamReader reader;

            if (this.pushPromises.TryRemove(frame.Header.StreamID, out var request))
            {
                this.HttpRequestSent?.Invoke(request);
                // PUSH_PROMISE による予約済みストリーム
                reader = new Http2StreamReader(frame.Header.StreamID, this.requestHpackDecoder, this.responseHpackDecoder, this.maxCaptureSize, request);
            }
            else
            {
                // 通常のストリーム
                reader = new Http2StreamReader(frame.Header.StreamID, this.requestHpackDecoder, this.responseHpackDecoder, this.maxCaptureSize);
            }
            reader.PushPromise                += this.OnPushPromise;
            reader.HttpRequestSent            += this.OnHttpRequestSent;
            reader.HttpResponseSent           += this.OnHttpResponseSent;
            reader.ClientWebSocketMessageSent += this.OnClientWebSocketMessageSent;
            reader.ServerWebSocketMessageSent += this.OnServerWebSocketMessageSent;
            reader.Reset += this.OnResetStream;
            this.streams.TryAdd(frame.Header.StreamID, reader);
        }
Exemplo n.º 5
0
        /// <summary>
        /// フレームを入力
        /// </summary>
        /// <param name="frame">入力するフレーム</param>
        public void HandleFrame(IHttp2Frame frame)
        {
            lock (this.lockObject)
            {
                if (frame.Header.StreamID != 0)
                {
                    return;
                }

                this.Frames.Add(frame);

                if (frame is Http2SettingsFrame settingsFrame &&
                    settingsFrame.IsAck)
                {
                    IReadOnlyList <(Http2SettingKey Key, uint Value)> settings = default;
                    // ACK が前後しても大丈夫なようにする
                    if (settingsFrame.IsAck)
                    {
                        settings = this.Partner.Frames
                                   .OfType <Http2SettingsFrame>()
                                   .Where(x => !x.IsAck)
                                   .LastOrDefault()
                                   ?.Settings;
                    }
                    else if (this.Frames.OfType <Http2SettingsFrame>().Count(x => !x.IsAck)
                             == this.Frames.OfType <Http2SettingsFrame>().Count(x => x.IsAck))
                    {
                        settings = settingsFrame.Settings;
                    }
                    if (settings?.Any(x => x.Key == Http2SettingKey.HeaderTableSize) ?? false)
                    {
                        var size = settings.First(x => x.Key == Http2SettingKey.HeaderTableSize).Value;
                        this.UpdateDynamicTableSize?.Invoke(size);
                    }
                }
            }
        }
Exemplo n.º 6
0
 public static bool HasFlag(this IHttp2Frame frame, byte flag)
 => (frame.Header.Flags & flag) == flag;
Exemplo n.º 7
0
        /// <summary>
        /// ペイロードデータから HTTP/2 フレームを作成
        /// </summary>
        /// <param name="payload"></param>
        /// <returns></returns>
        public IHttp2Frame CreateFrame(byte[] payload)
        {
            if (payload.Length != this.Length)
            {
                throw new ArgumentException("Invalid Length.");
            }

            IHttp2Frame frame = null;

            switch (this.Type)
            {
            case Http2FrameType.Data:
                frame = new Http2DataFrame(this, payload);
                break;

            case Http2FrameType.Headers:
                frame = new Http2HeadersFrame(this, payload);
                break;

            case Http2FrameType.Priority:
                frame = new Http2PriorityFrame(this, payload);
                break;

            case Http2FrameType.RstStream:
                frame = new Http2RstStreamFrame(this, payload);
                break;

            case Http2FrameType.Settings:
                frame = new Http2SettingsFrame(this, payload);
                break;

            case Http2FrameType.PushPromise:
                frame = new Http2PushPromiseFrame(this, payload);
                break;

            case Http2FrameType.Ping:
                frame = new Http2PingFrame(this, payload);
                break;

            case Http2FrameType.Goaway:
                frame = new Http2GoawayFrame(this, payload);
                break;

            case Http2FrameType.WindowUpdate:
                frame = new Http2WindowUpdateFrame(this, payload);
                break;

            case Http2FrameType.Continuation:
                frame = new Http2ContinuationFrame(this, payload);
                break;

            case Http2FrameType.Altsvc:
                frame = new Http2AltsvcFrame(this, payload);
                break;

            case Http2FrameType.Origin:
                frame = new Http2OriginFrame(this, payload);
                break;

            default:
                frame = new Http2UnknownFrame(this, payload);
                break;
            }
            return(frame);
        }