コード例 #1
0
ファイル: Http2Stream.cs プロジェクト: zhangrl/http2-katana
        public void WriteWindowUpdate(Int32 windowSize)
        {
            if (windowSize <= 0)
            {
                throw new ArgumentOutOfRangeException("windowSize should be greater than 0");
            }

            if (windowSize > Constants.MaxWindowSize)
            {
                throw new ProtocolError(ResetStatusCode.FlowControlError, "window size is too large");
            }

            //09 -> 6.9.4.  Ending Flow Control
            //After a receiver reads in a frame that marks the end of a stream (for
            //example, a data stream with a END_STREAM flag set), it MUST cease
            //transmission of WINDOW_UPDATE frames for that stream.
            if (Closed)
            {
                return;
            }

            //TODO handle idle state

            var frame = new WindowUpdateFrame(_id, windowSize);

            _writeQueue.WriteFrame(frame);

            Http2Logger.LogDebug("Sending WINDOW_UPDATE: stream id={0}, delta={1}", frame.StreamId, frame.Delta);

            if (OnFrameSent != null)
            {
                OnFrameSent(this, new FrameSentEventArgs(frame));
            }
        }
コード例 #2
0
        private void HandleRstFrame(RstStreamFrame resetFrame, out Http2Stream stream)
        {
            Http2Logger.LogDebug("RST_STREAM frame: stream id={0}, status code={1}",
                                 resetFrame.StreamId, resetFrame.StatusCode);

            /* 12 -> 6.4
             * RST_STREAM frames MUST be associated with a stream.  If a RST_STREAM
             * frame is received with a stream identifier of 0x0, the recipient MUST
             * treat this as a connection error of type PROTOCOL_ERROR. */
            if (resetFrame.StreamId == 0)
            {
                throw new ProtocolError(ResetStatusCode.ProtocolError, "Rst frame with stream id=0");
            }

            stream = GetStream(resetFrame.StreamId);

            if (stream.Closed)
            {
                /* 12 -> 5.4.2
                 * An endpoint MUST NOT send a RST_STREAM in response to an RST_STREAM
                 * frame, to avoid looping. */
                if (!stream.WasRstSent)
                {
                    throw new Http2StreamNotFoundException(resetFrame.StreamId);
                }
                return;
            }

            if (!(stream.ReservedRemote || stream.Opened || stream.HalfClosedLocal))
            {
                throw new ProtocolError(ResetStatusCode.ProtocolError, "Rst for non opened or reserved stream");
            }

            stream.Close(ResetStatusCode.None);
        }
コード例 #3
0
ファイル: Http2Stream.cs プロジェクト: zhangrl/http2-katana
        public void UpdateWindowSize(Int32 delta)
        {
            if (IsFlowControlEnabled)
            {
                //09 -> 6.9.1.  The Flow Control Window
                //A sender MUST NOT allow a flow control window to exceed 2^31 - 1
                //bytes.  If a sender receives a WINDOW_UPDATE that causes a flow
                //control window to exceed this maximum it MUST terminate either the
                //stream or the connection, as appropriate.  For streams, the sender
                //sends a RST_STREAM with the error code of FLOW_CONTROL_ERROR code;
                //for the connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code.
                WindowSize += delta;

                if (WindowSize > Constants.MaxWindowSize)
                {
                    Http2Logger.LogDebug("Incorrect window size : {0}", WindowSize);
                    throw new ProtocolError(ResetStatusCode.FlowControlError, String.Format("Incorrect window size : {0}", WindowSize));
                }
            }

            //Unblock stream if it was blocked by flowCtrlManager
            if (WindowSize > 0 && IsFlowControlBlocked)
            {
                IsFlowControlBlocked = false;
            }
        }
コード例 #4
0
ファイル: Http2Stream.cs プロジェクト: zhangrl/http2-katana
        /// <summary>
        /// Writes the data frame. Method is used for pushing unshipped frames.
        /// If flow control manager has blocked stream, frames are adding to the unshippedFrames collection.
        /// After window update for that stream they will be delivered.
        /// </summary>
        /// <param name="dataFrame">The data frame.</param>
        private void WriteDataFrame(DataFrame dataFrame)
        {
            if (dataFrame == null)
            {
                throw new ArgumentNullException("dataFrame is null");
            }

            if (Closed)
            {
                return;
            }

            if (!IsFlowControlBlocked)
            {
                _writeQueue.WriteFrame(dataFrame);
                SentDataAmount += dataFrame.Data.Count;

                _flowCrtlManager.DataFrameSentHandler(this, new DataFrameSentEventArgs(dataFrame));

                if (dataFrame.IsEndStream)
                {
                    Http2Logger.LogDebug("Bytes sent: {0}", SentDataAmount);
                    HalfClosedLocal = true;
                }

                if (OnFrameSent != null)
                {
                    OnFrameSent(this, new FrameSentEventArgs(dataFrame));
                }
            }
            else
            {
                _unshippedFrames.Enqueue(dataFrame);
            }
        }
コード例 #5
0
ファイル: Http2Stream.cs プロジェクト: zhangrl/http2-katana
        public void Close(ResetStatusCode code)
        {
            if (Closed || Idle)
            {
                return;
            }

            OnFrameSent = null;

            Http2Logger.LogDebug("Total outgoing data frames volume " + SentDataAmount);
            Http2Logger.LogDebug("Total frames sent: {0}", FramesSent);
            Http2Logger.LogDebug("Total frames received: {0}", FramesReceived);

            if (code == ResetStatusCode.Cancel || code == ResetStatusCode.InternalError)
            {
                WriteRst(code);
            }

            _flowCrtlManager.StreamClosedHandler(this);

            Closed = true;

            if (OnClose != null)
            {
                OnClose(this, new StreamClosedEventArgs(_id));
            }

            OnClose = null;

            Http2Logger.LogDebug("Stream closed " + _id);
        }
コード例 #6
0
        /// <summary>
        /// Writes the SETTINGS frame.
        /// </summary>
        /// <param name="settings">The settings pairs.</param>
        /// <param name="isAck">The ACK flag.</param>
        public void WriteSettings(SettingsPair[] settings, bool isAck)
        {
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }

            var frame = new SettingsFrame(new List <SettingsPair>(settings), isAck);

            Http2Logger.LogDebug("Sending SETTINGS frame: stream id={0}, payload len={1}, is ack={2}, count={3}",
                                 frame.StreamId, frame.PayloadLength, frame.IsAck, frame.EntryCount);

            foreach (var s in settings)
            {
                Http2Logger.LogDebug("{0}: {1}", s.Id.ToString(), s.Value);
            }

            _writeQueue.WriteFrame(frame);

            if (!isAck && !_settingsAckReceived.WaitOne(60000))
            {
                WriteGoAway(ResetStatusCode.SettingsTimeout);
                Dispose();
            }

            _settingsAckReceived.Reset();

            if (OnSettingsSent != null)
            {
                OnSettingsSent(this, new SettingsSentEventArgs(frame));
            }
        }
コード例 #7
0
        /// <summary>
        /// Writes the data frame.
        /// If flow control manager has blocked stream, frames are adding to the unshippedFrames collection.
        /// After window update for that stream they will be delivered.
        /// </summary>
        /// <param name="dataFrame">The data frame.</param>
        public void WriteDataFrame(DataFrame dataFrame)
        {
            if (IsFlowControlBlocked == false)
            {
                _writeQueue.WriteFrame(dataFrame);
                SentDataAmount += dataFrame.FrameLength;

                _flowCrtlManager.DataFrameSentHandler(this, new DataFrameSentEventArgs(dataFrame));

                if (dataFrame.IsEndStream)
                {
                    Http2Logger.LogDebug("Transfer end");
                    EndStreamSent = true;
                }

                if (OnFrameSent != null)
                {
                    OnFrameSent(this, new FrameSentArgs(dataFrame));
                }
            }
            else
            {
                _unshippedFrames.Enqueue(dataFrame);
            }
        }
コード例 #8
0
        /// <summary>
        /// Starts session.
        /// </summary>
        /// <returns></returns>
        public Task Start()
        {
            Http2Logger.LogDebug("Session start");
            //Write settings. Settings must be the first frame in session.

            if (_useFlowControl)
            {
                WriteSettings(new[]
                {
                    new SettingsPair(SettingsFlags.None, SettingsIds.InitialWindowSize, 200000)
                });
            }
            else
            {
                WriteSettings(new[]
                {
                    new SettingsPair(SettingsFlags.None, SettingsIds.InitialWindowSize, 200000),
                    new SettingsPair(SettingsFlags.None, SettingsIds.FlowControlOptions, (byte)FlowControlOptions.DontUseFlowControl)
                });
            }
            // Listen for incoming Http/2.0 frames
            var incomingTask = new Task(PumpIncommingData);
            // Send outgoing Http/2.0 frames
            var outgoingTask = new Task(() => PumpOutgoingData());

            incomingTask.Start();
            outgoingTask.Start();

            return(Task.WhenAll(incomingTask, outgoingTask));
        }
コード例 #9
0
        private void HandlePingFrame(PingFrame pingFrame)
        {
            Http2Logger.LogDebug("PING frame: stream id={0}, payload={1}", pingFrame.StreamId,
                                 pingFrame.Payload.Count);

            /* 12 -> 6.7
             * PING frames are not associated with any individual stream.  If a PING
             * frame is received with a stream identifier field value other than
             * 0x0, the recipient MUST respond with a connection error of type PROTOCOL_ERROR. */
            if (pingFrame.StreamId != 0)
            {
                throw new ProtocolError(ResetStatusCode.ProtocolError,
                                        "Incoming ping frame with stream id != 0");
            }

            if (pingFrame.PayloadLength != PingFrame.DefPayloadLength)
            {
                throw new ProtocolError(ResetStatusCode.FrameSizeError, "Ping payload size is not equal to 8");
            }

            if (pingFrame.IsAck)
            {
                _pingReceived.Set();
            }
            else
            {
                var pingAckFrame = new PingFrame(true, pingFrame.Payload.ToArray());
                _writeQueue.WriteFrame(pingAckFrame);
            }
        }
コード例 #10
0
        private void StartResponse()
        {
            Debug.Assert(!_responseStarted, "Response started more than once");
            _responseStarted = true;
            Http2Logger.LogDebug("Transfer begin");

            SendHeaders(final: false);
        }
コード例 #11
0
ファイル: Http2Stream.cs プロジェクト: zhangrl/http2-katana
        /// <summary>
        /// Writes the data frame.
        /// If flow control manager has blocked stream, frames are adding to the unshippedFrames collection.
        /// After window update for that stream they will be delivered.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="isEndStream">if set to <c>true</c> [is fin].</param>
        public void WriteDataFrame(ArraySegment <byte> data, bool isEndStream)
        {
            if (data.Array == null)
            {
                throw new ArgumentNullException("data is null");
            }

            if (Closed)
            {
                return;
            }

            var dataFrame = new DataFrame(_id, data, isEndStream, true);

            Http2Logger.LogDebug(
                "Sending DATA frame: stream id={0}, payload len={1}, has pad={2}, pad high={3}, pad low={4}, " +
                "end stream={5}", dataFrame.StreamId, dataFrame.PayloadLength,
                dataFrame.HasPadding, dataFrame.PadHigh, dataFrame.PadLow, dataFrame.IsEndStream);

            //We cant let lesser frame that were passed through flow control window
            //be sent before greater frames that were not passed through flow control window

            //09 -> 6.9.1.  The Flow Control Window
            //The sender MUST NOT
            //send a flow controlled frame with a length that exceeds the space
            //available in either of the flow control windows advertised by the receiver.
            if (_unshippedFrames.Count != 0 || WindowSize - dataFrame.Data.Count < 0)
            {
                _unshippedFrames.Enqueue(dataFrame);
                return;
            }

            if (!IsFlowControlBlocked)
            {
                _writeQueue.WriteFrame(dataFrame);
                SentDataAmount += dataFrame.Data.Count;

                _flowCrtlManager.DataFrameSentHandler(this, new DataFrameSentEventArgs(dataFrame));

                if (dataFrame.IsEndStream)
                {
                    Http2Logger.LogDebug("Transfer end");
                    Http2Logger.LogDebug("Sent bytes: {0}", SentDataAmount);
                    HalfClosedLocal = true;
                }

                if (OnFrameSent != null)
                {
                    OnFrameSent(this, new FrameSentEventArgs(dataFrame));
                }
            }
            else
            {
                _unshippedFrames.Enqueue(dataFrame);
            }
        }
コード例 #12
0
        /// <summary>
        /// Accepts client and deals handshake with it.
        /// </summary>
        internal void Accept()
        {
            SecureSocket incomingClient;

            using (var monitor = new ALPNExtensionMonitor())
            {
                incomingClient = _server.AcceptSocket(monitor);
            }
            Http2Logger.LogDebug("New connection accepted");
            Task.Run(() => HandleAcceptedClient(incomingClient));
        }
コード例 #13
0
        private void HandleWindowUpdateFrame(WindowUpdateFrame windowUpdateFrame, out Http2Stream stream)
        {
            Http2Logger.LogDebug("WINDOW_UPDATE frame: stream id={0}, delta={1}", windowUpdateFrame.StreamId,
                                 windowUpdateFrame.Delta);

            if (!_useFlowControl)
            {
                stream = null;
                return;
            }

            // TODO Remove this hack

            /* The WINDOW_UPDATE frame can be specific to a stream or to the entire
             * connection.  In the former case, the frame's stream identifier
             * indicates the affected stream; in the latter, the value "0" indicates
             * that the _entire connection_ is the subject of the frame. */
            if (windowUpdateFrame.StreamId == 0)
            {
                _flowControlManager.StreamsInitialWindowSize += windowUpdateFrame.Delta;
                stream = null;
                return;
            }

            stream = GetStream(windowUpdateFrame.StreamId);

            /* 12 -> 6.9
             * WINDOW_UPDATE can be sent by a peer that has sent a frame bearing the
             * END_STREAM flag.  This means that a receiver could receive a
             * WINDOW_UPDATE frame on a "half closed (remote)" or "closed" stream.
             * A receiver MUST NOT treat this as an error. */

            if (!(stream.Opened || stream.HalfClosedRemote || stream.HalfClosedLocal || stream.Closed))
            {
                throw new ProtocolError(ResetStatusCode.ProtocolError, "window update in incorrect state");
            }

            //09 -> 6.9.  WINDOW_UPDATE
            //The payload of a WINDOW_UPDATE frame is one reserved bit, plus an
            //unsigned 31-bit integer indicating the number of bytes that the
            //sender can transmit in addition to the existing flow control window.
            //The legal range for the increment to the flow control window is 1 to
            //2^31 - 1 (0x7fffffff) bytes.
            if (!(0 < windowUpdateFrame.Delta && windowUpdateFrame.Delta <= Constants.MaxPriority))
            {
                Http2Logger.LogDebug("Incorrect window update delta : {0}", windowUpdateFrame.Delta);
                throw new ProtocolError(ResetStatusCode.FlowControlError, String.Format("Incorrect window update delta : {0}", windowUpdateFrame.Delta));
            }

            stream.UpdateWindowSize(windowUpdateFrame.Delta);
            stream.PumpUnshippedFrames();
        }
コード例 #14
0
ファイル: Http11Manager.cs プロジェクト: skoant/http2-katana
        public static void Http11SendResponse(SecureSocket socket)
        {
            string[] headers  = GetHttp11Headers(socket);
            string   filename = GetFileName(headers);


            if (headers.Length == 0)
            {
                Http2Logger.LogError("Request headers empty!");
            }

            string path        = Path.GetFullPath(AssemblyPath + @"\root" + filename);
            string contentType = ContentTypes.GetTypeFromFileName(filename);

            if (!File.Exists(path))
            {
                Http2Logger.LogError("File " + filename + " not found");
                SendResponse(socket, new byte[0], StatusCode.Code404NotFound, contentType);
                socket.Close();
                return;
            }

            try
            {
                using (var sr = new StreamReader(path))
                {
                    string file = sr.ReadToEnd();

                    var fileBytes = Encoding.UTF8.GetBytes(file);

                    int sent = SendResponse(socket, fileBytes, StatusCode.Code200Ok, contentType);
                    Http2Logger.LogDebug(string.Format("Sent: {0} bytes", sent));
                    Http2Logger.LogInfo("File sent: " + filename);

                    socket.Close();

                    if (OnSocketClosed != null)
                    {
                        OnSocketClosed(null, new SocketCloseEventArgs());
                    }
                }
            }
            catch (Exception ex)
            {
                var msgBytes = Encoding.UTF8.GetBytes(ex.Message);
                SendResponse(socket, msgBytes, StatusCode.Code500InternalServerError, contentType);
                Http2Logger.LogError(ex.Message);
            }
        }
コード例 #15
0
        private void HandleRequest(Stream incomingClient, string alpnSelectedProtocol, bool backToHttp11)
        {
            //Server checks selected protocol and calls http2 or http11 layer
            if (backToHttp11 || alpnSelectedProtocol == Protocols.Http1)
            {
                Http2Logger.LogDebug("Selected protocol: HTTP/1.1");

                new Http11ProtocolOwinAdapter(incomingClient, SslProtocols.Tls, _next.Invoke).ProcessRequest();
                return;
            }

            //ALPN selected http2. No need to perform upgrade handshake.
            Http2Logger.LogDebug("Selected protocol (ALPN): http/2");
            OpenHttp2Session(incomingClient);
        }
コード例 #16
0
        /// <summary>
        /// Writes the GOAWAY frame.
        /// </summary>
        /// <param name="code">The Reset Status code.</param>
        public void WriteGoAway(ResetStatusCode code)
        {
            //if there were no streams opened
            if (_lastId == -1)
            {
                _lastId = 0; //then set lastId to 0 as spec tells. (See GoAway chapter)
            }

            var frame = new GoAwayFrame(_lastId, code);

            Http2Logger.LogDebug("Sending GOAWAY frame: stream id={0}, code={1}, last good id={2}",
                                 frame.StreamId, frame.StatusCode, frame.LastGoodStreamId);

            _writeQueue.WriteFrame(frame);
        }
コード例 #17
0
        private async void OpenHttp2Session(SecureSocket incomingClient, IDictionary <string, object> handshakeResult)
        {
            Http2Logger.LogDebug("Handshake successful");
            _session = new Http2Session(incomingClient, ConnectionEnd.Server, _usePriorities, _useFlowControl, handshakeResult);
            _session.OnFrameReceived += FrameReceivedHandler;

            try
            {
                await _session.Start();
            }
            catch (Exception)
            {
                Http2Logger.LogError("Client was disconnected");
            }
        }
コード例 #18
0
        private void HandleGoAwayFrame(GoAwayFrame goAwayFrame)
        {
            Http2Logger.LogDebug("GOAWAY frame: stream id={0}, status code={1}", goAwayFrame.StreamId,
                                 goAwayFrame.StatusCode);

            if (goAwayFrame.StreamId != 0)
            {
                throw new ProtocolError(ResetStatusCode.ProtocolError, "GoAway Stream id should always be null");
            }

            _goAwayReceived = true;

            Http2Logger.LogDebug("last successful id = {0}", goAwayFrame.LastGoodStreamId);
            Dispose();
        }
コード例 #19
0
        public void HandleHttp11Response(byte[] responseBinaryHeaders, int offset, int length)
        {
            var bytes = new byte[offset + length];

            Buffer.BlockCopy(responseBinaryHeaders, 0, bytes, offset, length);
            var response = ParseHeadersAndReadResponseBody(bytes);

            //TODO Handle headers somehow if it's needed
            using (var stream = new FileStream(AssemblyName + _path, FileMode.Create))
            {
                stream.Write(response.Value, 0, response.Value.Length);
            }

            Http2Logger.LogDebug("Response was saved as {0}", _path);
        }
コード例 #20
0
        // If no response headers have been sent yet, send them.
        internal void FinishResponse()
        {
            if (!_responseStarted)
            {
                Http2Logger.LogDebug("Transfer begin");

                SendHeaders(final: true);

                Http2Logger.LogDebug("Transfer end");
            }
            else
            {
                // End the data stream.
                _protocolStream.WriteDataFrame(new ArraySegment <byte>(new byte[0]), isEndStream: true);
            }
        }
コード例 #21
0
        private void HandleBlockedFrame(Frame blockedFrame)
        {
            Http2Logger.LogDebug("BLOCKED frame: stream id={0}, payload len={1}",
                                 blockedFrame.StreamId, blockedFrame.PayloadLength);

            /* 12 -> 6.12
             * The BLOCKED frame defines no flags and contains no payload. A
             * receiver MUST treat the receipt of a BLOCKED frame with a payload as
             * a connection error of type FRAME_SIZE_ERROR. */
            if (blockedFrame.PayloadLength > 0)
            {
                throw new ProtocolError(ResetStatusCode.FrameSizeError, "Blocked frame with non-zero payload");
            }

            // TODO: receiving BLCOKED frame is not implemented.
            // see https://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.12
        }
コード例 #22
0
        public virtual void Dispose()
        {
            if (_isDisposed)
            {
                return;
            }

            if (_session != null)
            {
                _session.Dispose();
            }

            OnFirstSettingsSent = null;

            _isDisposed = true;

            Http2Logger.LogDebug("Adapter disposed");
        }
コード例 #23
0
        private void Close(ResetStatusCode status)
        {
            if (_disposed)
            {
                return;
            }

            Http2Logger.LogDebug("Session closing");
            _disposed = true;

            // Dispose of all streams
            foreach (Http2Stream stream in ActiveStreams.Values)
            {
                //Cancel all opened streams
                stream.WriteRst(ResetStatusCode.Cancel);
                stream.Dispose();
            }

            OnSettingsSent  = null;
            OnFrameReceived = null;
            OnFrameSent     = null;

            if (!_goAwayReceived)
            {
                WriteGoAway(status);

                if (_writeQueue != null)
                {
                    _writeQueue.Flush();
                    _writeQueue.Dispose();
                }
            }

            _comprProc.Dispose();
            _sessionSocket.Close();

            if (OnSessionDisposed != null)
            {
                OnSessionDisposed(this, null);
            }
            OnSessionDisposed = null;

            Http2Logger.LogDebug("Session closed");
        }
コード例 #24
0
        private void HandleDataFrame(DataFrame dataFrame, out Http2Stream stream)
        {
            Http2Logger.LogDebug("DATA frame: stream id={0}, payload len={1}, has pad={2}, pad high={3}, pad low={4}, " +
                                 "end stream={5}", dataFrame.StreamId, dataFrame.PayloadLength,
                                 dataFrame.HasPadding, dataFrame.PadHigh, dataFrame.PadLow, dataFrame.IsEndStream);

            /* 12 -> 6.1
             * DATA frames MUST be associated with a stream. If a DATA frame is
             * received whose stream identifier field is 0x0, the recipient MUST
             * respond with a connection error of type PROTOCOL_ERROR. */
            if (dataFrame.StreamId == 0)
            {
                throw new ProtocolError(ResetStatusCode.ProtocolError,
                                        "Incoming continuation frame with stream id=0");
            }

            /* 12 -> 6.1
             * An endpoint that has not enabled DATA frame compression MUST
             * treat the receipt of a DATA frame with the COMPRESSED flag set as a
             * connection error of type PROTOCOL_ERROR. */
            if (dataFrame.IsCompressed)
            {
                throw new ProtocolError(ResetStatusCode.ProtocolError,
                                        "GZIP compression is not enabled");
            }

            stream = GetStream(dataFrame.StreamId);

            if (stream.Closed)
            {
                throw new Http2StreamNotFoundException(dataFrame.StreamId);
            }

            if (!(stream.Opened || stream.HalfClosedLocal))
            {
                throw new ProtocolError(ResetStatusCode.ProtocolError, "data in non opened or half closed local stream");
            }


            if (stream.IsFlowControlEnabled && !dataFrame.IsEndStream)
            {
                stream.WriteWindowUpdate(Constants.MaxFramePayloadSize);
            }
        }
コード例 #25
0
        /// <summary>
        /// Pumps the incomming data and calls dispatch for it
        /// </summary>
        private void PumpIncommingData()
        {
            while (!_goAwayReceived && !_disposed)
            {
                Frame frame;
                try
                {
                    frame = _frameReader.ReadFrame();

                    if (!_wasResponseReceived)
                    {
                        _wasResponseReceived = true;
                    }
                }
                catch (IOException)
                {
                    //Connection was closed by the remote endpoint
                    Http2Logger.LogInfo("Connection was closed by the remote endpoint");
                    Dispose();
                    break;
                }
                catch (Exception)
                {
                    // Read failure, abort the connection/session.
                    Http2Logger.LogInfo("Read failure, abort the connection/session");
                    Dispose();
                    break;
                }

                if (frame != null)
                {
                    DispatchIncomingFrame(frame);
                }
                else
                {
                    // Looks like connection was lost
                    Dispose();
                    break;
                }
            }

            Http2Logger.LogDebug("Read thread finished");
        }
コード例 #26
0
        /// <summary>
        /// Pumps the outgoing data to write queue
        /// </summary>
        /// <returns></returns>
        private void PumpOutgoingData()
        {
            try
            {
                _writeQueue.PumpToStream(_cancelSessionToken);
            }
            catch (OperationCanceledException)
            {
                Http2Logger.LogError("Handling session was cancelled");
                Dispose();
            }
            catch (Exception)
            {
                Http2Logger.LogError("Sending frame was cancelled because connection was lost");
                Dispose();
            }

            Http2Logger.LogDebug("Write thread finished");
        }
コード例 #27
0
        /// <summary>
        /// Pings session.
        /// </summary>
        /// <returns></returns>
        public TimeSpan Ping()
        {
            var pingFrame = new PingFrame(false);

            _writeQueue.WriteFrame(pingFrame);
            var now = DateTime.UtcNow;

            if (!_pingReceived.WaitOne(3000))
            {
                //Remote endpoint was not answer at time.
                Dispose();
            }
            _pingReceived.Reset();

            var newNow = DateTime.UtcNow;

            Http2Logger.LogDebug("Ping: " + (newNow - now).Milliseconds);
            return(newNow - now);
        }
コード例 #28
0
        private void Listen()
        {
            Http2Logger.LogInfo("Server running at port " + _port);
            _server.Start();
            while (!_disposed)
            {
                try
                {
                    var client = new HttpConnectingClient(_server, _next.Invoke, _serverCert, _isSecure, _useHandshake, _usePriorities, _useFlowControl);
                    client.Accept(_cancelAccept.Token);
                }
                catch (Exception ex)
                {
                    Http2Logger.LogError("Unhandled exception was caught: " + ex.Message);
                }
            }

            Http2Logger.LogDebug("Listen thread was finished");
        }
コード例 #29
0
        private async void OpenHttp2Session(Stream incomingClientStream)
        {
            Http2Logger.LogDebug("Handshake successful");
            using (var messageHandler = new Http2OwinMessageHandler(incomingClientStream, ConnectionEnd.Server,
                                                                    incomingClientStream is SslStream, _next,
                                                                    _cancelClientHandling.Token))
            {
                try
                {
                    await messageHandler.StartSessionAsync();
                }
                catch (Exception)
                {
                    Http2Logger.LogError("Client was disconnected");
                }
            }

            // GC.Collect();
        }
コード例 #30
0
        public void Dispose()
        {
            if (Disposed)
            {
                return;
            }

            Http2Logger.LogDebug("Total outgoing data frames volume " + SentDataAmount);

            if (OnClose != null)
            {
                OnClose(this, new StreamClosedEventArgs(_id));
            }

            Http2Logger.LogDebug("Stream closed " + _id);

            OnClose = null;
            _flowCrtlManager.StreamClosedHandler(this);
            Disposed = true;
        }