| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 883ed4b commit 5833007
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1037,7 +1037,7 @@ function finishSessionClose(session, error) { | |||
| 1037 | 1037 | if (socket && !socket.destroyed) { | |
| 1038 | 1038 | // Always wait for writable side to finish. | |
| 1039 | 1039 | socket.end((err) => { | |
| 1040 | - debugSessionObj(session, 'finishSessionClose socket end', err); | ||
| 1040 | + debugSessionObj(session, 'finishSessionClose socket end', err, error); | ||
| 1041 | 1041 | // Due to the way the underlying stream is handled in Http2Session we | |
| 1042 | 1042 | // won't get graceful Readable end from the other side even if it was sent | |
| 1043 | 1043 | // as the stream is already considered closed and will neither be read | |
@@ -1055,7 +1055,7 @@ function finishSessionClose(session, error) { | |||
| 1055 | 1055 | } | |
| 1056 | 1056 | ||
| 1057 | 1057 | function closeSession(session, code, error) { | |
| 1058 | - debugSessionObj(session, 'start closing/destroying'); | ||
| 1058 | + debugSessionObj(session, 'start closing/destroying', error); | ||
| 1059 | 1059 | ||
| 1060 | 1060 | const state = session[kState]; | |
| 1061 | 1061 | state.flags |= SESSION_FLAGS_DESTROYED; | |
@@ -3140,6 +3140,17 @@ function connect(authority, options, listener) { | |||
| 3140 | 3140 | ||
| 3141 | 3141 | if (typeof listener === 'function') | |
| 3142 | 3142 | session.once('connect', listener); | |
| 3143 | + | ||
| 3144 | + debug('Http2Session connect', options.createConnection); | ||
| 3145 | + // Socket already has some buffered data - emulate receiving it | ||
| 3146 | + // https://github.com/nodejs/node/issues/35475 | ||
| 3147 | + if (typeof options.createConnection === 'function') { | ||
| 3148 | + let buf; | ||
| 3149 | + while ((buf = socket.read()) !== null) { | ||
| 3150 | + debug(`Http2Session connect: injecting ${buf.length} already in buffer`); | ||
| 3151 | + session[kHandle].receive(buf); | ||
| 3152 | + } | ||
| 3153 | + } | ||
| 3143 | 3154 | return session; | |
| 3144 | 3155 | } | |
| 3145 | 3156 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1829,6 +1829,33 @@ void Http2Session::Consume(Local<Object> stream_obj) { | |||
| 1829 | 1829 | Debug(this, "i/o stream consumed"); | |
| 1830 | 1830 | } | |
| 1831 | 1831 | ||
| 1832 | + // Allow injecting of data from JS | ||
| 1833 | + // This is used when the socket has already some data received | ||
| 1834 | + // before our listener was attached | ||
| 1835 | + // https://github.com/nodejs/node/issues/35475 | ||
| 1836 | + void Http2Session::Receive(const FunctionCallbackInfo<Value>& args) { | ||
| 1837 | + Http2Session* session; | ||
| 1838 | + ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder()); | ||
| 1839 | + CHECK(args[0]->IsObject()); | ||
| 1840 | + | ||
| 1841 | + ArrayBufferViewContents<char> buffer(args[0]); | ||
| 1842 | + const char* data = buffer.data(); | ||
| 1843 | + size_t len = buffer.length(); | ||
| 1844 | + Debug(session, "Receiving %zu bytes injected from JS", len); | ||
| 1845 | + | ||
| 1846 | + // Copy given buffer | ||
| 1847 | + while (len > 0) { | ||
| 1848 | + uv_buf_t buf = session->OnStreamAlloc(len); | ||
| 1849 | + size_t copy = buf.len > len ? len : buf.len; | ||
| 1850 | + memcpy(buf.base, data, copy); | ||
| 1851 | + buf.len = copy; | ||
| 1852 | + session->OnStreamRead(copy, buf); | ||
| 1853 | + | ||
| 1854 | + data += copy; | ||
| 1855 | + len -= copy; | ||
| 1856 | + } | ||
| 1857 | + } | ||
| 1858 | + | ||
| 1832 | 1859 | Http2Stream* Http2Stream::New(Http2Session* session, | |
| 1833 | 1860 | int32_t id, | |
| 1834 | 1861 | nghttp2_headers_category category, | |
@@ -3054,6 +3081,7 @@ void Initialize(Local<Object> target, | |||
| 3054 | 3081 | env->SetProtoMethod(session, "altsvc", Http2Session::AltSvc); | |
| 3055 | 3082 | env->SetProtoMethod(session, "ping", Http2Session::Ping); | |
| 3056 | 3083 | env->SetProtoMethod(session, "consume", Http2Session::Consume); | |
| 3084 | + env->SetProtoMethod(session, "receive", Http2Session::Receive); | ||
| 3057 | 3085 | env->SetProtoMethod(session, "destroy", Http2Session::Destroy); | |
| 3058 | 3086 | env->SetProtoMethod(session, "goaway", Http2Session::Goaway); | |
| 3059 | 3087 | env->SetProtoMethod(session, "settings", Http2Session::Settings); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -694,6 +694,7 @@ class Http2Session : public AsyncWrap, | |||
| 694 | 694 | // The JavaScript API | |
| 695 | 695 | static void New(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 696 | 696 | static void Consume(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 697 | + static void Receive(const v8::FunctionCallbackInfo<v8::Value>& args); | ||
| 697 | 698 | static void Destroy(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 698 | 699 | static void Settings(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 699 | 700 | static void Request(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,64 @@ | |||
| 1 | + // Flags: --expose-internals | ||
| 2 | + 'use strict'; | ||
| 3 | + const common = require('../common'); | ||
| 4 | + if (!common.hasCrypto) | ||
| 5 | + common.skip('missing crypto'); | ||
| 6 | + | ||
| 7 | + if (!common.hasMultiLocalhost()) | ||
| 8 | + common.skip('platform-specific test.'); | ||
| 9 | + | ||
| 10 | + const http2 = require('http2'); | ||
| 11 | + const assert = require('assert'); | ||
| 12 | + const tls = require('tls'); | ||
| 13 | + const fixtures = require('../common/fixtures'); | ||
| 14 | + | ||
| 15 | + const serverOptions = { | ||
| 16 | + key: fixtures.readKey('agent1-key.pem'), | ||
| 17 | + cert: fixtures.readKey('agent1-cert.pem') | ||
| 18 | + }; | ||
| 19 | + const server = http2.createSecureServer(serverOptions, (req, res) => { | ||
| 20 | + console.log(`Connect from: ${req.connection.remoteAddress}`); | ||
| 21 | + assert.strictEqual(req.connection.remoteAddress, '127.0.0.2'); | ||
| 22 | + | ||
| 23 | + req.on('end', common.mustCall(() => { | ||
| 24 | + res.writeHead(200, { 'Content-Type': 'text/plain' }); | ||
| 25 | + res.end(`You are from: ${req.connection.remoteAddress}`); | ||
| 26 | + })); | ||
| 27 | + req.resume(); | ||
| 28 | + }); | ||
| 29 | + | ||
| 30 | + server.listen(0, '127.0.0.1', common.mustCall(() => { | ||
| 31 | + const options = { | ||
| 32 | + ALPNProtocols: ['h2'], | ||
| 33 | + host: '127.0.0.1', | ||
| 34 | + servername: 'localhost', | ||
| 35 | + localAddress: '127.0.0.2', | ||
| 36 | + port: server.address().port, | ||
| 37 | + rejectUnauthorized: false | ||
| 38 | + }; | ||
| 39 | + | ||
| 40 | + console.log('Server ready', server.address().port); | ||
| 41 | + | ||
| 42 | + const socket = tls.connect(options, async () => { | ||
| 43 | + | ||
| 44 | + console.log('TLS Connected!'); | ||
| 45 | + | ||
| 46 | + setTimeout(() => { | ||
| 47 | + | ||
| 48 | + const client = http2.connect( | ||
| 49 | + 'https://localhost:' + server.address().port, | ||
| 50 | + { ...options, createConnection: () => socket } | ||
| 51 | + ); | ||
| 52 | + const req = client.request({ | ||
| 53 | + ':path': '/' | ||
| 54 | + }); | ||
| 55 | + req.on('data', () => req.resume()); | ||
| 56 | + req.on('end', common.mustCall(function() { | ||
| 57 | + client.close(); | ||
| 58 | + req.close(); | ||
| 59 | + server.close(); | ||
| 60 | + })); | ||
| 61 | + req.end(); | ||
| 62 | + }, 1000); | ||
| 63 | + }); | ||
| 64 | + })); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments