diff options
Diffstat (limited to 'lib/dgram.js')
-rw-r--r-- | lib/dgram.js | 91 |
1 files changed, 72 insertions, 19 deletions
diff --git a/lib/dgram.js b/lib/dgram.js index 8ddd523237..c541373fe2 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -25,7 +25,8 @@ const errors = require('internal/errors'); const { kStateSymbol, _createSocketHandle, - newHandle + newHandle, + guessHandleType, } = require('internal/dgram'); const { ERR_INVALID_ARG_TYPE, @@ -35,7 +36,8 @@ const { ERR_SOCKET_BAD_PORT, ERR_SOCKET_BUFFER_SIZE, ERR_SOCKET_CANNOT_SEND, - ERR_SOCKET_DGRAM_NOT_RUNNING + ERR_SOCKET_DGRAM_NOT_RUNNING, + ERR_INVALID_FD_TYPE } = errors.codes; const { Buffer } = require('buffer'); const util = require('util'); @@ -45,6 +47,7 @@ const { defaultTriggerAsyncIdScope, symbols: { async_id_symbol, owner_symbol } } = require('internal/async_hooks'); +const { isInt32 } = require('internal/validators'); const { UV_UDP_REUSEADDR } = process.binding('constants').os; const { UDP, SendWrap } = process.binding('udp_wrap'); @@ -151,6 +154,28 @@ function bufferSize(self, size, buffer) { return ret; } +// Query master process to get the server handle and utilize it. +function bindServerHandle(self, options, errCb) { + if (!cluster) + cluster = require('cluster'); + + const state = self[kStateSymbol]; + cluster._getServer(self, options, (err, handle) => { + if (err) { + errCb(err); + return; + } + + if (!state.handle) { + // Handle has been closed in the mean time. + return handle.close(); + } + + replaceHandle(self, handle); + startListening(self); + }); +} + Socket.prototype.bind = function(port_, address_ /* , callback */) { let port = port_; @@ -171,6 +196,44 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) { return this; } + // Open an existing fd instead of creating a new one. + if (port !== null && typeof port === 'object' && + isInt32(port.fd) && port.fd > 0) { + const fd = port.fd; + const exclusive = !!port.exclusive; + const state = this[kStateSymbol]; + + if (!cluster) + cluster = require('cluster'); + + if (cluster.isWorker && !exclusive) { + bindServerHandle(this, { + address: null, + port: null, + addressType: this.type, + fd, + flags: null + }, (err) => { + // Callback to handle error. + const ex = errnoException(err, 'open'); + this.emit('error', ex); + state.bindState = BIND_STATE_UNBOUND; + }); + return this; + } + + const type = guessHandleType(fd); + if (type !== 'UDP') + throw new ERR_INVALID_FD_TYPE(type); + const err = state.handle.open(fd); + + if (err) + throw errnoException(err, 'open'); + + startListening(this); + return this; + } + var address; var exclusive; @@ -207,28 +270,18 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) { flags |= UV_UDP_REUSEADDR; if (cluster.isWorker && !exclusive) { - const onHandle = (err, handle) => { - if (err) { - var ex = exceptionWithHostPort(err, 'bind', ip, port); - this.emit('error', ex); - state.bindState = BIND_STATE_UNBOUND; - return; - } - - if (!state.handle) - // handle has been closed in the mean time. - return handle.close(); - - replaceHandle(this, handle); - startListening(this); - }; - cluster._getServer(this, { + bindServerHandle(this, { address: ip, port: port, addressType: this.type, fd: -1, flags: flags - }, onHandle); + }, (err) => { + // Callback to handle error. + const ex = exceptionWithHostPort(err, 'bind', ip, port); + this.emit('error', ex); + state.bindState = BIND_STATE_UNBOUND; + }); } else { if (!state.handle) return; // handle has been closed in the mean time |