Beispiel #1
0
        public void Removed()
        {
            if (this.uploadStreamInfo.Stream != null)
            {
                this.uploadStreamInfo.Stream.Dispose();
                this.uploadStreamInfo = new HTTPRequest.UploadStreamInfo();
            }

            this.outgoing.Clear();

            HTTPManager.Logger.Information("HTTP2Stream", "Stream removed: " + this.Id.ToString());
        }
Beispiel #2
0
        private void ProcessState(List <HTTP2FrameHeaderAndPayload> outgoingFrames)
        {
            switch (this.State)
            {
            case HTTP2StreamStates.Idle:

                UInt32 initiatedInitialWindowSize = this.settings.InitiatedMySettings[HTTP2Settings.INITIAL_WINDOW_SIZE];
                this.localWindow = initiatedInitialWindowSize;
                // window update with a zero increment would be an error (https://httpwg.org/specs/rfc7540.html#WINDOW_UPDATE)
                //if (HTTP2Connection.MaxValueFor31Bits > initiatedInitialWindowSize)
                //    this.outgoing.Enqueue(HTTP2FrameHelper.CreateWindowUpdateFrame(this.Id, HTTP2Connection.MaxValueFor31Bits - initiatedInitialWindowSize));
                //this.localWindow = HTTP2Connection.MaxValueFor31Bits;

#if !BESTHTTP_DISABLE_CACHING
                // Setup cache control headers before we send out the request
                if (!this.AssignedRequest.DisableCache)
                {
                    HTTPCacheService.SetHeaders(this.AssignedRequest);
                }
#endif

                // hpack encode the request's header
                this.encoder.Encode(this, this.AssignedRequest, this.outgoing, this.Id);

                // HTTP/2 uses DATA frames to carry message payloads.
                // The chunked transfer encoding defined in Section 4.1 of [RFC7230] MUST NOT be used in HTTP/2.
                this.uploadStreamInfo = this.AssignedRequest.GetUpStream();

                //this.State = HTTP2StreamStates.Open;

                if (this.uploadStreamInfo.Stream == null)
                {
                    this.State = HTTP2StreamStates.HalfClosedLocal;
                }
                else
                {
                    this.State = HTTP2StreamStates.Open;
                }
                break;

            case HTTP2StreamStates.Open:
                // remote Window can be negative! See https://httpwg.org/specs/rfc7540.html#InitialWindowSize
                if (this.remoteWindow <= 0)
                {
                    HTTPManager.Logger.Warning("HTTP2Stream", string.Format("[{0}] Skipping data sending as remote Window is {1}!", this.Id, this.remoteWindow));
                    return;
                }

                // This step will send one frame per OpenState call.

                Int64 maxFrameSize = Math.Min(this.remoteWindow, this.settings.RemoteSettings[HTTP2Settings.MAX_FRAME_SIZE]);

                HTTP2FrameHeaderAndPayload frame = new HTTP2FrameHeaderAndPayload();
                frame.Type     = HTTP2FrameTypes.DATA;
                frame.StreamId = this.Id;

                frame.Payload = BufferPool.Get(maxFrameSize, true);

                int readCount = this.uploadStreamInfo.Stream.Read(frame.Payload, 0, (int)Math.Min(maxFrameSize, int.MaxValue));
                if (readCount <= 0)
                {
                    BufferPool.Release(frame.Payload);
                    frame.Payload       = null;
                    frame.PayloadLength = 0;
                }
                else
                {
                    frame.PayloadLength = (UInt32)readCount;
                }

                frame.PayloadOffset  = 0;
                frame.DontUseMemPool = false;

                if (readCount <= 0)
                {
                    this.uploadStreamInfo.Stream.Dispose();
                    this.uploadStreamInfo = new HTTPRequest.UploadStreamInfo();

                    frame.Flags = (byte)(HTTP2DataFlags.END_STREAM);

                    this.State = HTTP2StreamStates.HalfClosedLocal;
                }

                this.outgoing.Enqueue(frame);

                this.remoteWindow -= frame.PayloadLength;

                this.sentData += frame.PayloadLength;

                if (this.AssignedRequest.OnUploadProgress != null)
                {
                    RequestEventHelper.EnqueueRequestEvent(new RequestEventInfo(this.AssignedRequest, RequestEvents.UploadProgress, this.sentData, this.uploadStreamInfo.Length));
                }

                //HTTPManager.Logger.Information("HTTP2Stream", string.Format("[{0}] New DATA frame created! remoteWindow: {1:N0}", this.Id, this.remoteWindow));
                break;

            case HTTP2StreamStates.HalfClosedLocal:
                if (this.TimeSpentInCurrentState >= CloseStreamAfter && !this.isStreamedDownload)
                {
                    this.State = HTTP2StreamStates.Closed;
                }
                break;

            case HTTP2StreamStates.HalfClosedRemote:
                break;

            case HTTP2StreamStates.Closed:
                break;
            }
        }