@@ -25,7 +25,8 @@ const errors = require('internal/errors');
25
25
const {
26
26
kStateSymbol,
27
27
_createSocketHandle,
28
- newHandle
28
+ newHandle,
29
+ guessHandleType,
29
30
} = require ( 'internal/dgram' ) ;
30
31
const {
31
32
ERR_INVALID_ARG_TYPE ,
@@ -35,7 +36,8 @@ const {
35
36
ERR_SOCKET_BAD_PORT ,
36
37
ERR_SOCKET_BUFFER_SIZE ,
37
38
ERR_SOCKET_CANNOT_SEND ,
38
- ERR_SOCKET_DGRAM_NOT_RUNNING
39
+ ERR_SOCKET_DGRAM_NOT_RUNNING ,
40
+ ERR_INVALID_FD_TYPE
39
41
} = errors . codes ;
40
42
const { Buffer } = require ( 'buffer' ) ;
41
43
const util = require ( 'util' ) ;
@@ -45,6 +47,7 @@ const {
45
47
defaultTriggerAsyncIdScope,
46
48
symbols : { async_id_symbol, owner_symbol }
47
49
} = require ( 'internal/async_hooks' ) ;
50
+ const { isInt32 } = require ( 'internal/validators' ) ;
48
51
const { UV_UDP_REUSEADDR } = process . binding ( 'constants' ) . os ;
49
52
50
53
const { UDP , SendWrap } = process . binding ( 'udp_wrap' ) ;
@@ -151,6 +154,28 @@ function bufferSize(self, size, buffer) {
151
154
return ret ;
152
155
}
153
156
157
+ // Query master process to get the server handle and utilize it.
158
+ function bindServerHandle ( self , options , errCb ) {
159
+ if ( ! cluster )
160
+ cluster = require ( 'cluster' ) ;
161
+
162
+ const state = self [ kStateSymbol ] ;
163
+ cluster . _getServer ( self , options , ( err , handle ) => {
164
+ if ( err ) {
165
+ errCb ( err ) ;
166
+ return ;
167
+ }
168
+
169
+ if ( ! state . handle ) {
170
+ // Handle has been closed in the mean time.
171
+ return handle . close ( ) ;
172
+ }
173
+
174
+ replaceHandle ( self , handle ) ;
175
+ startListening ( self ) ;
176
+ } ) ;
177
+ }
178
+
154
179
Socket . prototype . bind = function ( port_ , address_ /* , callback */ ) {
155
180
let port = port_ ;
156
181
@@ -171,6 +196,44 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) {
171
196
return this ;
172
197
}
173
198
199
+ // Open an existing fd instead of creating a new one.
200
+ if ( port !== null && typeof port === 'object' &&
201
+ isInt32 ( port . fd ) && port . fd > 0 ) {
202
+ const fd = port . fd ;
203
+ const exclusive = ! ! port . exclusive ;
204
+ const state = this [ kStateSymbol ] ;
205
+
206
+ if ( ! cluster )
207
+ cluster = require ( 'cluster' ) ;
208
+
209
+ if ( cluster . isWorker && ! exclusive ) {
210
+ bindServerHandle ( this , {
211
+ address : null ,
212
+ port : null ,
213
+ addressType : this . type ,
214
+ fd,
215
+ flags : null
216
+ } , ( err ) => {
217
+ // Callback to handle error.
218
+ const ex = errnoException ( err , 'open' ) ;
219
+ this . emit ( 'error' , ex ) ;
220
+ state . bindState = BIND_STATE_UNBOUND ;
221
+ } ) ;
222
+ return this ;
223
+ }
224
+
225
+ const type = guessHandleType ( fd ) ;
226
+ if ( type !== 'UDP' )
227
+ throw new ERR_INVALID_FD_TYPE ( type ) ;
228
+ const err = state . handle . open ( fd ) ;
229
+
230
+ if ( err )
231
+ throw errnoException ( err , 'open' ) ;
232
+
233
+ startListening ( this ) ;
234
+ return this ;
235
+ }
236
+
174
237
var address ;
175
238
var exclusive ;
176
239
@@ -207,28 +270,18 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) {
207
270
flags |= UV_UDP_REUSEADDR ;
208
271
209
272
if ( cluster . isWorker && ! exclusive ) {
210
- const onHandle = ( err , handle ) => {
211
- if ( err ) {
212
- var ex = exceptionWithHostPort ( err , 'bind' , ip , port ) ;
213
- this . emit ( 'error' , ex ) ;
214
- state . bindState = BIND_STATE_UNBOUND ;
215
- return ;
216
- }
217
-
218
- if ( ! state . handle )
219
- // handle has been closed in the mean time.
220
- return handle . close ( ) ;
221
-
222
- replaceHandle ( this , handle ) ;
223
- startListening ( this ) ;
224
- } ;
225
- cluster . _getServer ( this , {
273
+ bindServerHandle ( this , {
226
274
address : ip ,
227
275
port : port ,
228
276
addressType : this . type ,
229
277
fd : - 1 ,
230
278
flags : flags
231
- } , onHandle ) ;
279
+ } , ( err ) => {
280
+ // Callback to handle error.
281
+ const ex = exceptionWithHostPort ( err , 'bind' , ip , port ) ;
282
+ this . emit ( 'error' , ex ) ;
283
+ state . bindState = BIND_STATE_UNBOUND ;
284
+ } ) ;
232
285
} else {
233
286
if ( ! state . handle )
234
287
return ; // handle has been closed in the mean time
0 commit comments