Esempio n. 1
0
        private void WriteHeadersFrame(IChannelHandlerContext ctx, IHttp2HeadersFrame headersFrame, IPromise promise)
        {
            if (Http2CodecUtil.IsStreamIdValid(headersFrame.Stream.Id))
            {
                _ = Encoder.WriteHeadersAsync(ctx, headersFrame.Stream.Id, headersFrame.Headers, headersFrame.Padding,
                                              headersFrame.IsEndStream, promise);
            }
            else
            {
                var stream     = (DefaultHttp2FrameStream)headersFrame.Stream;
                var connection = Connection;
                var streamId   = connection.Local.IncrementAndGetNextStreamId;
                if (streamId < 0)
                {
                    promise.SetException(new Http2NoMoreStreamIdsException());

                    // Simulate a GOAWAY being received due to stream exhaustion on this connection. We use the maximum
                    // valid stream ID for the current peer.
                    OnHttp2Frame(ctx, new DefaultHttp2GoAwayFrame(connection.IsServer ? int.MaxValue :
                                                                  int.MaxValue - 1, Http2Error.NoError,
                                                                  ByteBufferUtil.WriteAscii(ctx.Allocator, "Stream IDs exhausted on local stream creation")));
                    return;
                }
                stream.Id = streamId;

                // Use a Map to store all pending streams as we may have multiple. This is needed as if we would store the
                // stream in a field directly we may override the stored field before onStreamAdded(...) was called
                // and so not correctly set the property for the buffered stream.
                //
                // See https://github.com/netty/netty/issues/8692
                var result = _frameStreamToInitializeMap.TryAdd(streamId, stream);

                // We should not re-use ids.
                Debug.Assert(result);

                _ = Encoder.WriteHeadersAsync(ctx, streamId, headersFrame.Headers, headersFrame.Padding,
                                              headersFrame.IsEndStream, promise);
                if (!promise.IsCompleted)
                {
                    _ = Interlocked.Increment(ref v_numBufferedStreams);
                    // Clean up the stream being initialized if writing the headers fails and also
                    // decrement the number of buffered streams.
                    _ = promise.Task.ContinueWith(ResetNufferedStreamsAction, (this, streamId), TaskContinuationOptions.ExecuteSynchronously);
                }
                else
                {
                    HandleHeaderFuture(promise.Task, streamId);
                }
            }
        }