| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent c50762c commit f14d78b
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2845,9 +2845,10 @@ changes: | |||
| 2845 | 2845 | This is a credit based limit, existing `Http2Stream`s may cause this | |
| 2846 | 2846 | limit to be exceeded, but new `Http2Stream` instances will be rejected | |
| 2847 | 2847 | while this limit is exceeded. The current number of `Http2Stream` sessions, | |
| 2848 | - the current memory use of the header compression tables, current data | ||
| 2849 | - queued to be sent, and unacknowledged `PING` and `SETTINGS` frames are all | ||
| 2850 | - counted towards the current limit. **Default:** `10`. | ||
| 2848 | + the current memory use of the header compression tables, header blocks | ||
| 2849 | + retained by open streams, current data queued to be sent, and | ||
| 2850 | + unacknowledged `PING` and `SETTINGS` frames are all counted towards the | ||
| 2851 | + current limit. **Default:** `10`. | ||
| 2851 | 2852 | * `maxHeaderListPairs` {number} Sets the maximum number of header entries. | |
| 2852 | 2853 | This is similar to [`server.maxHeadersCount`][] or | |
| 2853 | 2854 | [`request.maxHeadersCount`][] in the `node:http` module. The minimum value | |
@@ -3034,9 +3035,10 @@ changes: | |||
| 3034 | 3035 | credit based limit, existing `Http2Stream`s may cause this | |
| 3035 | 3036 | limit to be exceeded, but new `Http2Stream` instances will be rejected | |
| 3036 | 3037 | while this limit is exceeded. The current number of `Http2Stream` sessions, | |
| 3037 | - the current memory use of the header compression tables, current data | ||
| 3038 | - queued to be sent, and unacknowledged `PING` and `SETTINGS` frames are all | ||
| 3039 | - counted towards the current limit. **Default:** `10`. | ||
| 3038 | + the current memory use of the header compression tables, header blocks | ||
| 3039 | + retained by open streams, current data queued to be sent, and | ||
| 3040 | + unacknowledged `PING` and `SETTINGS` frames are all counted towards the | ||
| 3041 | + current limit. **Default:** `10`. | ||
| 3040 | 3042 | * `maxHeaderListPairs` {number} Sets the maximum number of header entries. | |
| 3041 | 3043 | This is similar to [`server.maxHeadersCount`][] or | |
| 3042 | 3044 | [`request.maxHeadersCount`][] in the `node:http` module. The minimum value | |
@@ -3196,9 +3198,10 @@ changes: | |||
| 3196 | 3198 | This is a credit based limit, existing `Http2Stream`s may cause this | |
| 3197 | 3199 | limit to be exceeded, but new `Http2Stream` instances will be rejected | |
| 3198 | 3200 | while this limit is exceeded. The current number of `Http2Stream` sessions, | |
| 3199 | - the current memory use of the header compression tables, current data | ||
| 3200 | - queued to be sent, and unacknowledged `PING` and `SETTINGS` frames are all | ||
| 3201 | - counted towards the current limit. **Default:** `10`. | ||
| 3201 | + the current memory use of the header compression tables, header blocks | ||
| 3202 | + retained by open streams, current data queued to be sent, and | ||
| 3203 | + unacknowledged `PING` and `SETTINGS` frames are all counted towards the | ||
| 3204 | + current limit. **Default:** `10`. | ||
| 3202 | 3205 | * `maxHeaderListPairs` {number} Sets the maximum number of header entries. | |
| 3203 | 3206 | This is similar to [`server.maxHeadersCount`][] or | |
| 3204 | 3207 | [`request.maxHeadersCount`][] in the `node:http` module. The minimum value | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -907,6 +907,14 @@ BaseObjectPtr<Http2Stream> Http2Session::RemoveStream(int32_t id) { | |||
| 907 | 907 | stream = FindStream(id); | |
| 908 | 908 | if (stream) { | |
| 909 | 909 | streams_.erase(id); | |
| 910 | + if (stream->current_headers_length_ > 0) { | ||
| 911 | + DecrementCurrentSessionMemory(stream->current_headers_length_); | ||
| 912 | + stream->current_headers_length_ = 0; | ||
| 913 | + } | ||
| 914 | + if (stream->retained_headers_length_ > 0) { | ||
| 915 | + DecrementCurrentSessionMemory(stream->retained_headers_length_); | ||
| 916 | + stream->retained_headers_length_ = 0; | ||
| 917 | + } | ||
| 910 | 918 | DecrementCurrentSessionMemory(sizeof(*stream)); | |
| 911 | 919 | } | |
| 912 | 920 | return stream; | |
@@ -1553,7 +1561,10 @@ void Http2Session::HandleHeadersFrame(const nghttp2_frame* frame) { | |||
| 1553 | 1561 | }); | |
| 1554 | 1562 | CHECK_EQ(stream->headers_count(), 0); | |
| 1555 | 1563 | ||
| 1556 | - DecrementCurrentSessionMemory(stream->current_headers_length_); | ||
| 1564 | + // Keep the header block charged against maxSessionMemory while the | ||
| 1565 | + // corresponding JS objects can still keep it alive for the lifetime of | ||
| 1566 | + // the stream. | ||
| 1567 | + stream->retained_headers_length_ += stream->current_headers_length_; | ||
| 1557 | 1568 | stream->current_headers_length_ = 0; | |
| 1558 | 1569 | ||
| 1559 | 1570 | Local<Value> args[] = { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -485,9 +485,11 @@ class Http2Stream : public AsyncWrap, | |||
| 485 | 485 | ||
| 486 | 486 | // The Current Headers block... As headers are received for this stream, | |
| 487 | 487 | // they are temporarily stored here until the OnFrameReceived is called | |
| 488 | - // signalling the end of the HEADERS frame | ||
| 488 | + // signalling the end of the HEADERS frame. | ||
| 489 | 489 | nghttp2_headers_category current_headers_category_ = NGHTTP2_HCAT_HEADERS; | |
| 490 | 490 | uint32_t current_headers_length_ = 0; // total number of octets | |
| 491 | + // Charged against maxSessionMemory while headers stay alive in JS. | ||
| 492 | + uint64_t retained_headers_length_ = 0; | ||
| 491 | 493 | std::vector<Http2Header> current_headers_; | |
| 492 | 494 | ||
| 493 | 495 | // This keeps track of the amount of data read from the socket while the | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,69 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const common = require('../common'); | ||
| 4 | + if (!common.hasCrypto) | ||
| 5 | + common.skip('missing crypto'); | ||
| 6 | + | ||
| 7 | + const Countdown = require('../common/countdown'); | ||
| 8 | + const assert = require('assert'); | ||
| 9 | + const http2 = require('http2'); | ||
| 10 | + | ||
| 11 | + const { | ||
| 12 | + NGHTTP2_ENHANCE_YOUR_CALM, | ||
| 13 | + } = http2.constants; | ||
| 14 | + | ||
| 15 | + // Regression test: header blocks retained by stalled streams should continue | ||
| 16 | + // to count against maxSessionMemory after they have been handed to JS. | ||
| 17 | + const maxSessionMemory = 1; | ||
| 18 | + const totalRequests = 400; | ||
| 19 | + const cookieCrumbs = 120; | ||
| 20 | + | ||
| 21 | + let accepted = 0; | ||
| 22 | + let rejected = 0; | ||
| 23 | + | ||
| 24 | + const server = http2.createServer({ maxSessionMemory }); | ||
| 25 | + server.on('stream', (stream) => { | ||
| 26 | + accepted++; | ||
| 27 | + stream.on('error', () => {}); | ||
| 28 | + stream.respond(); | ||
| 29 | + stream.write('x'); | ||
| 30 | + }); | ||
| 31 | + | ||
| 32 | + server.listen(0, common.mustCall(() => { | ||
| 33 | + const client = http2.connect(`http://localhost:${server.address().port}`, { | ||
| 34 | + settings: { | ||
| 35 | + initialWindowSize: 0, | ||
| 36 | + }, | ||
| 37 | + }); | ||
| 38 | + client.on('error', () => {}); | ||
| 39 | + | ||
| 40 | + client.on('remoteSettings', common.mustCall(() => { | ||
| 41 | + let destroyed = false; | ||
| 42 | + const countdown = new Countdown(totalRequests, common.mustCall(() => { | ||
| 43 | + assert(rejected > 0); | ||
| 44 | + assert(accepted < totalRequests); | ||
| 45 | + server.close(); | ||
| 46 | + })); | ||
| 47 | + | ||
| 48 | + for (let i = 0; i < totalRequests; i++) { | ||
| 49 | + const headers = [':path', '/']; | ||
| 50 | + for (let j = 0; j < cookieCrumbs; j++) { | ||
| 51 | + headers.push('cookie', 'a=1'); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + const req = client.request(headers); | ||
| 55 | + req.on('error', () => {}); | ||
| 56 | + req.on('close', () => { | ||
| 57 | + if (req.rstCode === NGHTTP2_ENHANCE_YOUR_CALM) { | ||
| 58 | + rejected++; | ||
| 59 | + if (!destroyed) { | ||
| 60 | + destroyed = true; | ||
| 61 | + client.destroy(); | ||
| 62 | + } | ||
| 63 | + } | ||
| 64 | + countdown.dec(); | ||
| 65 | + }); | ||
| 66 | + req.end(); | ||
| 67 | + } | ||
| 68 | + })); | ||
| 69 | + })); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments