summaryrefslogtreecommitdiff
path: root/lib/dgram.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dgram.js')
-rw-r--r--lib/dgram.js91
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