| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent dada3ae commit f6bf3f8
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1698,6 +1698,11 @@ Adoption transfers ownership of the socket; afterwards `address()` and `close()` | |||
| 1698 | 1698 | throw [`ERR_SOCKET_HANDLE_ADOPTED`][]. A handle that is never adopted must be | |
| 1699 | 1699 | closed to avoid leaking the socket. | |
| 1700 | 1700 | ||
| 1701 | + When an adopted `BoundSocket` connects to a numeric IP literal, `connect(2)` is | ||
| 1702 | + issued synchronously, so [`socket.localAddress`][] is resolved once | ||
| 1703 | + [`socket.connect()`][] returns. Connection failures are still reported via a | ||
| 1704 | + deferred `'error'` event. | ||
| 1705 | + | ||
| 1701 | 1706 | ```mjs | |
| 1702 | 1707 | import net from 'node:net'; | |
| 1703 | 1708 | ||
@@ -2283,6 +2288,7 @@ net.isIPv6('fhqwhgads'); // returns false | |||
| 2283 | 2288 | [`socket.connecting`]: #socketconnecting | |
| 2284 | 2289 | [`socket.destroy()`]: #socketdestroyerror | |
| 2285 | 2290 | [`socket.end()`]: #socketenddata-encoding-callback | |
| 2291 | + [`socket.localAddress`]: #socketlocaladdress | ||
| 2286 | 2292 | [`socket.pause()`]: #socketpause | |
| 2287 | 2293 | [`socket.resume()`]: #socketresume | |
| 2288 | 2294 | [`socket.setEncoding()`]: #socketsetencodingencoding | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1630,6 +1630,17 @@ function lookupAndConnect(self, options) { | |||
| 1630 | 1630 | // If host is an IP, skip performing a lookup | |
| 1631 | 1631 | const addressType = isIP(host); | |
| 1632 | 1632 | if (addressType) { | |
| 1633 | + // An adopted BoundSocket needs no lookup: issue connect(2) in-tick so the | ||
| 1634 | + // kernel-resolved concrete source address is observable synchronously. | ||
| 1635 | + // Connection failures are still reported via a deferred 'error' event. | ||
| 1636 | + if (self[kBoundSource]) { | ||
| 1637 | + defaultTriggerAsyncIdScope( | ||
| 1638 | + self[async_id_symbol], | ||
| 1639 | + internalConnect, | ||
| 1640 | + self, host, port, addressType, localAddress, localPort, | ||
| 1641 | + ); | ||
| 1642 | + return; | ||
| 1643 | + } | ||
| 1633 | 1644 | defaultTriggerAsyncIdScope(self[async_id_symbol], process.nextTick, () => { | |
| 1634 | 1645 | if (self.connecting) | |
| 1635 | 1646 | defaultTriggerAsyncIdScope( | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -178,6 +178,42 @@ if (!common.isWindows && process.getuid() !== 0) { | |||
| 178 | 178 | client.destroy(); | |
| 179 | 179 | } | |
| 180 | 180 | ||
| 181 | + // Adopted BoundSocket: connect(2) is synchronous, so localAddress/localPort | ||
| 182 | + // resolve to the concrete source in-tick, before the 'connect' event. | ||
| 183 | + { | ||
| 184 | + const server = net.createServer(); | ||
| 185 | + server.listen(0, '127.0.0.1', common.mustCall(() => { | ||
| 186 | + const serverPort = server.address().port; | ||
| 187 | + const bound = new net.BoundSocket({ host: '127.0.0.1', port: 0 }); | ||
| 188 | + const localPort = bound.address().port; | ||
| 189 | + const client = new net.Socket({ handle: bound }); | ||
| 190 | + | ||
| 191 | + client.connect({ host: '127.0.0.1', port: serverPort }); | ||
| 192 | + | ||
| 193 | + assert.strictEqual(client.localAddress, '127.0.0.1'); | ||
| 194 | + assert.strictEqual(client.localPort, localPort); | ||
| 195 | + | ||
| 196 | + client.on('connect', common.mustCall(() => { | ||
| 197 | + assert.strictEqual(client.localAddress, '127.0.0.1'); | ||
| 198 | + assert.strictEqual(client.localPort, localPort); | ||
| 199 | + client.destroy(); | ||
| 200 | + server.close(); | ||
| 201 | + })); | ||
| 202 | + })); | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + // A connect failure is reported via a deferred 'error' event, never thrown | ||
| 206 | + // synchronously. An IPv4-bound handle connecting to an IPv6 literal fails on | ||
| 207 | + // address family mismatch. | ||
| 208 | + { | ||
| 209 | + const bound = new net.BoundSocket({ host: '127.0.0.1', port: 0 }); | ||
| 210 | + const client = new net.Socket({ handle: bound }); | ||
| 211 | + client.connect({ host: '::1', port: 1 }); | ||
| 212 | + client.on('error', common.mustCall((err) => { | ||
| 213 | + assert.strictEqual(err.syscall, 'connect'); | ||
| 214 | + })); | ||
| 215 | + } | ||
| 216 | + | ||
| 181 | 217 | // reusePort: SO_REUSEPORT permits multiple listeners on the same port. Support | |
| 182 | 218 | // is platform-dependent, so probe first. | |
| 183 | 219 | { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments