| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 9a4bac2 commit c915bc5
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -656,6 +656,16 @@ inline Http2Stream* Http2Session::FindStream(int32_t id) { | |||
| 656 | 656 | return s != streams_.end() ? s->second : nullptr; | |
| 657 | 657 | } | |
| 658 | 658 | ||
| 659 | + inline bool Http2Session::CanAddStream() { | ||
| 660 | + uint32_t maxConcurrentStreams = | ||
| 661 | + nghttp2_session_get_local_settings( | ||
| 662 | + session_, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS); | ||
| 663 | + size_t maxSize = | ||
| 664 | + std::min(streams_.max_size(), static_cast<size_t>(maxConcurrentStreams)); | ||
| 665 | + // We can add a new stream so long as we are less than the current | ||
| 666 | + // maximum on concurrent streams | ||
| 667 | + return streams_.size() < maxSize; | ||
| 668 | + } | ||
| 659 | 669 | ||
| 660 | 670 | inline void Http2Session::AddStream(Http2Stream* stream) { | |
| 661 | 671 | CHECK_GE(++statistics_.stream_count, 0); | |
@@ -766,7 +776,14 @@ inline int Http2Session::OnBeginHeadersCallback(nghttp2_session* handle, | |||
| 766 | 776 | ||
| 767 | 777 | Http2Stream* stream = session->FindStream(id); | |
| 768 | 778 | if (stream == nullptr) { | |
| 769 | - new Http2Stream(session, id, frame->headers.cat); | ||
| 779 | + if (session->CanAddStream()) { | ||
| 780 | + new Http2Stream(session, id, frame->headers.cat); | ||
| 781 | + } else { | ||
| 782 | + // Too many concurrent streams being opened | ||
| 783 | + nghttp2_submit_rst_stream(**session, NGHTTP2_FLAG_NONE, id, | ||
| 784 | + NGHTTP2_ENHANCE_YOUR_CALM); | ||
| 785 | + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; | ||
| 786 | + } | ||
| 770 | 787 | } else { | |
| 771 | 788 | // If the stream has already been destroyed, ignore. | |
| 772 | 789 | if (stream->IsDestroyed()) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -835,6 +835,8 @@ class Http2Session : public AsyncWrap { | |||
| 835 | 835 | // Returns pointer to the stream, or nullptr if stream does not exist | |
| 836 | 836 | inline Http2Stream* FindStream(int32_t id); | |
| 837 | 837 | ||
| 838 | + inline bool CanAddStream(); | ||
| 839 | + | ||
| 838 | 840 | // Adds a stream instance to this session | |
| 839 | 841 | inline void AddStream(Http2Stream* stream); | |
| 840 | 842 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,60 @@ | |||
| 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 http2 = require('http2'); | ||
| 9 | + const assert = require('assert'); | ||
| 10 | + | ||
| 11 | + // Test that the maxConcurrentStreams setting is strictly enforced | ||
| 12 | + | ||
| 13 | + const server = http2.createServer({ settings: { maxConcurrentStreams: 1 } }); | ||
| 14 | + | ||
| 15 | + let c = 0; | ||
| 16 | + | ||
| 17 | + server.on('stream', common.mustCall((stream) => { | ||
| 18 | + // Because we only allow one open stream at a time, | ||
| 19 | + // c should never be greater than 1. | ||
| 20 | + assert.strictEqual(++c, 1); | ||
| 21 | + stream.respond(); | ||
| 22 | + // Force some asynchronos stuff. | ||
| 23 | + setImmediate(() => { | ||
| 24 | + stream.end('ok'); | ||
| 25 | + assert.strictEqual(--c, 0); | ||
| 26 | + }); | ||
| 27 | + }, 3)); | ||
| 28 | + | ||
| 29 | + server.listen(0, common.mustCall(() => { | ||
| 30 | + const client = http2.connect(`http://localhost:${server.address().port}`); | ||
| 31 | + | ||
| 32 | + const countdown = new Countdown(3, common.mustCall(() => { | ||
| 33 | + server.close(); | ||
| 34 | + client.destroy(); | ||
| 35 | + })); | ||
| 36 | + | ||
| 37 | + client.on('remoteSettings', common.mustCall(() => { | ||
| 38 | + assert.strictEqual(client.remoteSettings.maxConcurrentStreams, 1); | ||
| 39 | + | ||
| 40 | + { | ||
| 41 | + const req = client.request(); | ||
| 42 | + req.resume(); | ||
| 43 | + req.on('close', () => { | ||
| 44 | + countdown.dec(); | ||
| 45 | + | ||
| 46 | + setImmediate(() => { | ||
| 47 | + const req = client.request(); | ||
| 48 | + req.resume(); | ||
| 49 | + req.on('close', () => countdown.dec()); | ||
| 50 | + }); | ||
| 51 | + }); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + { | ||
| 55 | + const req = client.request(); | ||
| 56 | + req.resume(); | ||
| 57 | + req.on('close', () => countdown.dec()); | ||
| 58 | + } | ||
| 59 | + })); | ||
| 60 | + })); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments