| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent ac02a0b commit e6e99eb
14 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -725,8 +725,8 @@ reached. | |||
| 725 | 725 | <a id="ERR_HTTP2_NO_SOCKET_MANIPULATION"></a> | |
| 726 | 726 | ### ERR_HTTP2_NO_SOCKET_MANIPULATION | |
| 727 | 727 | ||
| 728 | - Used when attempting to read, write, pause, and/or resume a socket attached to | ||
| 729 | - an `Http2Session`. | ||
| 728 | + Used when attempting to directly manipulate (e.g read, write, pause, resume, | ||
| 729 | + etc.) a socket attached to an `Http2Session`. | ||
| 730 | 730 | ||
| 731 | 731 | <a id="ERR_HTTP2_OUT_OF_STREAMS"></a> | |
| 732 | 732 | ### ERR_HTTP2_OUT_OF_STREAMS | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -463,12 +463,16 @@ added: v8.4.0 | |||
| 463 | 463 | ||
| 464 | 464 | * Value: {net.Socket|tls.TLSSocket} | |
| 465 | 465 | ||
| 466 | - A reference to the [`net.Socket`][] or [`tls.TLSSocket`][] to which this | ||
| 467 | - `Http2Session` instance is bound. | ||
| 466 | + Returns a Proxy object that acts as a `net.Socket` (or `tls.TLSSocket`) but | ||
| 467 | + limits available methods to ones safe to use with HTTP/2. | ||
| 468 | 468 | ||
| 469 | - *Note*: It is not recommended for user code to interact directly with a | ||
| 470 | - `Socket` bound to an `Http2Session`. See [Http2Session and Sockets][] for | ||
| 471 | - details. | ||
| 469 | + `destroy`, `emit`, `end`, `pause`, `read`, `resume`, and `write` will throw | ||
| 470 | + an error with code `ERR_HTTP2_NO_SOCKET_MANIPULATION`. See | ||
| 471 | + [Http2Session and Sockets][] for more information. | ||
| 472 | + | ||
| 473 | + `setTimeout` method will be called on this `Http2Session`. | ||
| 474 | + | ||
| 475 | + All other interactions will be routed directly to the socket. | ||
| 472 | 476 | ||
| 473 | 477 | #### http2session.state | |
| 474 | 478 | <!-- YAML | |
@@ -2138,10 +2142,10 @@ Returns `request`. | |||
| 2138 | 2142 | added: v8.4.0 | |
| 2139 | 2143 | --> | |
| 2140 | 2144 | ||
| 2141 | - * {net.Socket} | ||
| 2145 | + * {net.Socket|tls.TLSSocket} | ||
| 2142 | 2146 | ||
| 2143 | - Returns a Proxy object that acts as a `net.Socket` but applies getters, | ||
| 2144 | - setters and methods based on HTTP/2 logic. | ||
| 2147 | + Returns a Proxy object that acts as a `net.Socket` (or `tls.TLSSocket`) but | ||
| 2148 | + applies getters, setters and methods based on HTTP/2 logic. | ||
| 2145 | 2149 | ||
| 2146 | 2150 | `destroyed`, `readable`, and `writable` properties will be retrieved from and | |
| 2147 | 2151 | set on `request.stream`. | |
@@ -2293,7 +2297,7 @@ will result in a [`TypeError`][] being thrown. | |||
| 2293 | 2297 | added: v8.4.0 | |
| 2294 | 2298 | --> | |
| 2295 | 2299 | ||
| 2296 | - * {net.Socket} | ||
| 2300 | + * {net.Socket|tls.TLSSocket} | ||
| 2297 | 2301 | ||
| 2298 | 2302 | See [`response.socket`][]. | |
| 2299 | 2303 | ||
@@ -2510,10 +2514,10 @@ Returns `response`. | |||
| 2510 | 2514 | added: v8.4.0 | |
| 2511 | 2515 | --> | |
| 2512 | 2516 | ||
| 2513 | - * {net.Socket} | ||
| 2517 | + * {net.Socket|tls.TLSSocket} | ||
| 2514 | 2518 | ||
| 2515 | - Returns a Proxy object that acts as a `net.Socket` but applies getters, | ||
| 2516 | - setters and methods based on HTTP/2 logic. | ||
| 2519 | + Returns a Proxy object that acts as a `net.Socket` (or `tls.TLSSocket`) but | ||
| 2520 | + applies getters, setters and methods based on HTTP/2 logic. | ||
| 2517 | 2521 | ||
| 2518 | 2522 | `destroyed`, `readable`, and `writable` properties will be retrieved from and | |
| 2519 | 2523 | set on `response.stream`. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -199,8 +199,7 @@ E('ERR_HTTP2_INVALID_STREAM', 'The stream has been destroyed'); | |||
| 199 | 199 | E('ERR_HTTP2_MAX_PENDING_SETTINGS_ACK', | |
| 200 | 200 | (max) => `Maximum number of pending settings acknowledgements (${max})`); | |
| 201 | 201 | E('ERR_HTTP2_NO_SOCKET_MANIPULATION', | |
| 202 | - 'HTTP/2 sockets should not be directly read from, written to, ' + | ||
| 203 | - 'paused and/or resumed.'); | ||
| 202 | + 'HTTP/2 sockets should not be directly manipulated (e.g. read and written)'); | ||
| 204 | 203 | E('ERR_HTTP2_OUT_OF_STREAMS', | |
| 205 | 204 | 'No stream ID is available because maximum stream ID has been reached'); | |
| 206 | 205 | E('ERR_HTTP2_PAYLOAD_FORBIDDEN', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,6 +5,7 @@ const Readable = Stream.Readable; | |||
| 5 | 5 | const binding = process.binding('http2'); | |
| 6 | 6 | const constants = binding.constants; | |
| 7 | 7 | const errors = require('internal/errors'); | |
| 8 | + const { kSocket } = require('internal/http2/util'); | ||
| 8 | 9 | ||
| 9 | 10 | const kFinish = Symbol('finish'); | |
| 10 | 11 | const kBeginSend = Symbol('begin-send'); | |
@@ -176,15 +177,15 @@ const proxySocketHandler = { | |||
| 176 | 177 | throw new errors.Error('ERR_HTTP2_NO_SOCKET_MANIPULATION'); | |
| 177 | 178 | default: | |
| 178 | 179 | const ref = stream.session !== undefined ? | |
| 179 | - stream.session.socket : stream; | ||
| 180 | + stream.session[kSocket] : stream; | ||
| 180 | 181 | const value = ref[prop]; | |
| 181 | 182 | return typeof value === 'function' ? value.bind(ref) : value; | |
| 182 | 183 | } | |
| 183 | 184 | }, | |
| 184 | 185 | getPrototypeOf(stream) { | |
| 185 | 186 | if (stream.session !== undefined) | |
| 186 | - return stream.session.socket.constructor.prototype; | ||
| 187 | - return stream.prototype; | ||
| 187 | + return Reflect.getPrototypeOf(stream.session[kSocket]); | ||
| 188 | + return Reflect.getPrototypeOf(stream); | ||
| 188 | 189 | }, | |
| 189 | 190 | set(stream, prop, value) { | |
| 190 | 191 | switch (prop) { | |
@@ -201,9 +202,9 @@ const proxySocketHandler = { | |||
| 201 | 202 | case 'setTimeout': | |
| 202 | 203 | const session = stream.session; | |
| 203 | 204 | if (session !== undefined) | |
| 204 | - session[prop] = value; | ||
| 205 | + session.setTimeout = value; | ||
| 205 | 206 | else | |
| 206 | - stream[prop] = value; | ||
| 207 | + stream.setTimeout = value; | ||
| 207 | 208 | return true; | |
| 208 | 209 | case 'write': | |
| 209 | 210 | case 'read': | |
@@ -212,7 +213,7 @@ const proxySocketHandler = { | |||
| 212 | 213 | throw new errors.Error('ERR_HTTP2_NO_SOCKET_MANIPULATION'); | |
| 213 | 214 | default: | |
| 214 | 215 | const ref = stream.session !== undefined ? | |
| 215 | - stream.session.socket : stream; | ||
| 216 | + stream.session[kSocket] : stream; | ||
| 216 | 217 | ref[prop] = value; | |
| 217 | 218 | return true; | |
| 218 | 219 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -38,6 +38,7 @@ const { | |||
| 38 | 38 | getSettings, | |
| 39 | 39 | getStreamState, | |
| 40 | 40 | isPayloadMeaningless, | |
| 41 | + kSocket, | ||
| 41 | 42 | mapToHeaders, | |
| 42 | 43 | NghttpError, | |
| 43 | 44 | sessionName, | |
@@ -70,10 +71,10 @@ const kOptions = Symbol('options'); | |||
| 70 | 71 | const kOwner = Symbol('owner'); | |
| 71 | 72 | const kProceed = Symbol('proceed'); | |
| 72 | 73 | const kProtocol = Symbol('protocol'); | |
| 74 | + const kProxySocket = Symbol('proxy-socket'); | ||
| 73 | 75 | const kRemoteSettings = Symbol('remote-settings'); | |
| 74 | 76 | const kServer = Symbol('server'); | |
| 75 | 77 | const kSession = Symbol('session'); | |
| 76 | - const kSocket = Symbol('socket'); | ||
| 77 | 78 | const kState = Symbol('state'); | |
| 78 | 79 | const kType = Symbol('type'); | |
| 79 | 80 | ||
@@ -672,6 +673,48 @@ function finishSessionDestroy(self, socket) { | |||
| 672 | 673 | debug(`[${sessionName(self[kType])}] nghttp2session destroyed`); | |
| 673 | 674 | } | |
| 674 | 675 | ||
| 676 | + const proxySocketHandler = { | ||
| 677 | + get(session, prop) { | ||
| 678 | + switch (prop) { | ||
| 679 | + case 'setTimeout': | ||
| 680 | + return session.setTimeout.bind(session); | ||
| 681 | + case 'destroy': | ||
| 682 | + case 'emit': | ||
| 683 | + case 'end': | ||
| 684 | + case 'pause': | ||
| 685 | + case 'read': | ||
| 686 | + case 'resume': | ||
| 687 | + case 'write': | ||
| 688 | + throw new errors.Error('ERR_HTTP2_NO_SOCKET_MANIPULATION'); | ||
| 689 | + default: | ||
| 690 | + const socket = session[kSocket]; | ||
| 691 | + const value = socket[prop]; | ||
| 692 | + return typeof value === 'function' ? value.bind(socket) : value; | ||
| 693 | + } | ||
| 694 | + }, | ||
| 695 | + getPrototypeOf(session) { | ||
| 696 | + return Reflect.getPrototypeOf(session[kSocket]); | ||
| 697 | + }, | ||
| 698 | + set(session, prop, value) { | ||
| 699 | + switch (prop) { | ||
| 700 | + case 'setTimeout': | ||
| 701 | + session.setTimeout = value; | ||
| 702 | + return true; | ||
| 703 | + case 'destroy': | ||
| 704 | + case 'emit': | ||
| 705 | + case 'end': | ||
| 706 | + case 'pause': | ||
| 707 | + case 'read': | ||
| 708 | + case 'resume': | ||
| 709 | + case 'write': | ||
| 710 | + throw new errors.Error('ERR_HTTP2_NO_SOCKET_MANIPULATION'); | ||
| 711 | + default: | ||
| 712 | + session[kSocket][prop] = value; | ||
| 713 | + return true; | ||
| 714 | + } | ||
| 715 | + } | ||
| 716 | + }; | ||
| 717 | + | ||
| 675 | 718 | // Upon creation, the Http2Session takes ownership of the socket. The session | |
| 676 | 719 | // may not be ready to use immediately if the socket is not yet fully connected. | |
| 677 | 720 | class Http2Session extends EventEmitter { | |
@@ -707,6 +750,7 @@ class Http2Session extends EventEmitter { | |||
| 707 | 750 | }; | |
| 708 | 751 | ||
| 709 | 752 | this[kType] = type; | |
| 753 | + this[kProxySocket] = null; | ||
| 710 | 754 | this[kSocket] = socket; | |
| 711 | 755 | ||
| 712 | 756 | // Do not use nagle's algorithm | |
@@ -756,7 +800,10 @@ class Http2Session extends EventEmitter { | |||
| 756 | 800 | ||
| 757 | 801 | // The socket owned by this session | |
| 758 | 802 | get socket() { | |
| 759 | - return this[kSocket]; | ||
| 803 | + const proxySocket = this[kProxySocket]; | ||
| 804 | + if (proxySocket === null) | ||
| 805 | + return this[kProxySocket] = new Proxy(this, proxySocketHandler); | ||
| 806 | + return proxySocket; | ||
| 760 | 807 | } | |
| 761 | 808 | ||
| 762 | 809 | // The session type | |
@@ -957,6 +1004,7 @@ class Http2Session extends EventEmitter { | |||
| 957 | 1004 | // Disassociate from the socket and server | |
| 958 | 1005 | const socket = this[kSocket]; | |
| 959 | 1006 | // socket.pause(); | |
| 1007 | + delete this[kProxySocket]; | ||
| 960 | 1008 | delete this[kSocket]; | |
| 961 | 1009 | delete this[kServer]; | |
| 962 | 1010 | ||
@@ -2155,30 +2203,6 @@ function socketDestroy(error) { | |||
| 2155 | 2203 | this.destroy(error); | |
| 2156 | 2204 | } | |
| 2157 | 2205 | ||
| 2158 | - function socketOnResume() { | ||
| 2159 | - if (this._paused) | ||
| 2160 | - return this.pause(); | ||
| 2161 | - if (this._handle && !this._handle.reading) { | ||
| 2162 | - this._handle.reading = true; | ||
| 2163 | - this._handle.readStart(); | ||
| 2164 | - } | ||
| 2165 | - } | ||
| 2166 | - | ||
| 2167 | - function socketOnPause() { | ||
| 2168 | - if (this._handle && this._handle.reading) { | ||
| 2169 | - this._handle.reading = false; | ||
| 2170 | - this._handle.readStop(); | ||
| 2171 | - } | ||
| 2172 | - } | ||
| 2173 | - | ||
| 2174 | - function socketOnDrain() { | ||
| 2175 | - const needPause = 0 > this._writableState.highWaterMark; | ||
| 2176 | - if (this._paused && !needPause) { | ||
| 2177 | - this._paused = false; | ||
| 2178 | - this.resume(); | ||
| 2179 | - } | ||
| 2180 | - } | ||
| 2181 | - | ||
| 2182 | 2206 | // When an Http2Session emits an error, first try to forward it to the | |
| 2183 | 2207 | // server as a sessionError; failing that, forward it to the socket as | |
| 2184 | 2208 | // a sessionError; failing that, destroy, remove the error listener, and | |
@@ -2267,9 +2291,6 @@ function connectionListener(socket) { | |||
| 2267 | 2291 | } | |
| 2268 | 2292 | ||
| 2269 | 2293 | socket.on('error', socketOnError); | |
| 2270 | - socket.on('resume', socketOnResume); | ||
| 2271 | - socket.on('pause', socketOnPause); | ||
| 2272 | - socket.on('drain', socketOnDrain); | ||
| 2273 | 2294 | socket.on('close', socketOnClose); | |
| 2274 | 2295 | ||
| 2275 | 2296 | // Set up the Session | |
@@ -2426,9 +2447,6 @@ function connect(authority, options, listener) { | |||
| 2426 | 2447 | } | |
| 2427 | 2448 | ||
| 2428 | 2449 | socket.on('error', socketOnError); | |
| 2429 | - socket.on('resume', socketOnResume); | ||
| 2430 | - socket.on('pause', socketOnPause); | ||
| 2431 | - socket.on('drain', socketOnDrain); | ||
| 2432 | 2450 | socket.on('close', socketOnClose); | |
| 2433 | 2451 | ||
| 2434 | 2452 | const session = new ClientHttp2Session(options, socket); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,6 +3,8 @@ | |||
| 3 | 3 | const binding = process.binding('http2'); | |
| 4 | 4 | const errors = require('internal/errors'); | |
| 5 | 5 | ||
| 6 | + const kSocket = Symbol('socket'); | ||
| 7 | + | ||
| 6 | 8 | const { | |
| 7 | 9 | NGHTTP2_SESSION_CLIENT, | |
| 8 | 10 | NGHTTP2_SESSION_SERVER, | |
@@ -551,6 +553,7 @@ module.exports = { | |||
| 551 | 553 | getSettings, | |
| 552 | 554 | getStreamState, | |
| 553 | 555 | isPayloadMeaningless, | |
| 556 | + kSocket, | ||
| 554 | 557 | mapToHeaders, | |
| 555 | 558 | NghttpError, | |
| 556 | 559 | sessionName, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,10 +1,13 @@ | |||
| 1 | + // Flags: --expose-internals | ||
| 2 | + | ||
| 1 | 3 | 'use strict'; | |
| 2 | 4 | ||
| 3 | 5 | const common = require('../common'); | |
| 4 | 6 | if (!common.hasCrypto) | |
| 5 | 7 | common.skip('missing crypto'); | |
| 6 | 8 | const assert = require('assert'); | |
| 7 | 9 | const h2 = require('http2'); | |
| 10 | + const { kSocket } = require('internal/http2/util'); | ||
| 8 | 11 | ||
| 9 | 12 | { | |
| 10 | 13 | const server = h2.createServer(); | |
@@ -13,7 +16,7 @@ const h2 = require('http2'); | |||
| 13 | 16 | common.mustCall(() => { | |
| 14 | 17 | const destroyCallbacks = [ | |
| 15 | 18 | (client) => client.destroy(), | |
| 16 | - (client) => client.socket.destroy() | ||
| 19 | + (client) => client[kSocket].destroy() | ||
| 17 | 20 | ]; | |
| 18 | 21 | ||
| 19 | 22 | let remaining = destroyCallbacks.length; | |
@@ -23,9 +26,9 @@ const h2 = require('http2'); | |||
| 23 | 26 | client.on( | |
| 24 | 27 | 'connect', | |
| 25 | 28 | common.mustCall(() => { | |
| 26 | - const socket = client.socket; | ||
| 29 | + const socket = client[kSocket]; | ||
| 27 | 30 | ||
| 28 | - assert(client.socket, 'client session has associated socket'); | ||
| 31 | + assert(socket, 'client session has associated socket'); | ||
| 29 | 32 | assert( | |
| 30 | 33 | !client.destroyed, | |
| 31 | 34 | 'client has not been destroyed before destroy is called' | |
@@ -41,7 +44,7 @@ const h2 = require('http2'); | |||
| 41 | 44 | destroyCallback(client); | |
| 42 | 45 | ||
| 43 | 46 | assert( | |
| 44 | - !client.socket, | ||
| 47 | + !client[kSocket], | ||
| 45 | 48 | 'client.socket undefined after destroy is called' | |
| 46 | 49 | ); | |
| 47 | 50 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,9 +1,13 @@ | |||
| 1 | + // Flags: --expose-internals | ||
| 2 | + | ||
| 1 | 3 | 'use strict'; | |
| 2 | 4 | ||
| 3 | 5 | const common = require('../common'); | |
| 4 | 6 | if (!common.hasCrypto) | |
| 5 | 7 | common.skip('missing crypto'); | |
| 6 | 8 | const h2 = require('http2'); | |
| 9 | + const { kSocket } = require('internal/http2/util'); | ||
| 10 | + | ||
| 7 | 11 | const body = | |
| 8 | 12 | '<html><head></head><body><h1>this is some data</h2></body></html>'; | |
| 9 | 13 | ||
@@ -32,7 +36,7 @@ server.on('listening', common.mustCall(function() { | |||
| 32 | 36 | ||
| 33 | 37 | req.on('response', common.mustCall(() => { | |
| 34 | 38 | // send a premature socket close | |
| 35 | - client.socket.destroy(); | ||
| 39 | + client[kSocket].destroy(); | ||
| 36 | 40 | })); | |
| 37 | 41 | req.on('data', common.mustNotCall()); | |
| 38 | 42 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,8 +13,8 @@ const h2 = require('http2'); | |||
| 13 | 13 | const errMsg = { | |
| 14 | 14 | code: 'ERR_HTTP2_NO_SOCKET_MANIPULATION', | |
| 15 | 15 | type: Error, | |
| 16 | - message: 'HTTP/2 sockets should not be directly read from, written to, ' + | ||
| 17 | - 'paused and/or resumed.' | ||
| 16 | + message: 'HTTP/2 sockets should not be directly manipulated ' + | ||
| 17 | + '(e.g. read and written)' | ||
| 18 | 18 | }; | |
| 19 | 19 | ||
| 20 | 20 | const server = h2.createServer(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,8 +15,8 @@ const net = require('net'); | |||
| 15 | 15 | const errMsg = { | |
| 16 | 16 | code: 'ERR_HTTP2_NO_SOCKET_MANIPULATION', | |
| 17 | 17 | type: Error, | |
| 18 | - message: 'HTTP/2 sockets should not be directly read from, written to, ' + | ||
| 19 | - 'paused and/or resumed.' | ||
| 18 | + message: 'HTTP/2 sockets should not be directly manipulated ' + | ||
| 19 | + '(e.g. read and written)' | ||
| 20 | 20 | }; | |
| 21 | 21 | ||
| 22 | 22 | const server = h2.createServer(); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments