@@ -25,7 +25,8 @@ const errors = require('internal/errors');
2525const {
2626 kStateSymbol,
2727 _createSocketHandle,
28- newHandle
28+ newHandle,
29+ guessHandleType,
2930} = require ( 'internal/dgram' ) ;
3031const {
3132 ERR_INVALID_ARG_TYPE ,
@@ -35,7 +36,8 @@ const {
3536 ERR_SOCKET_BAD_PORT ,
3637 ERR_SOCKET_BUFFER_SIZE ,
3738 ERR_SOCKET_CANNOT_SEND ,
38- ERR_SOCKET_DGRAM_NOT_RUNNING
39+ ERR_SOCKET_DGRAM_NOT_RUNNING ,
40+ ERR_INVALID_FD_TYPE
3941} = errors . codes ;
4042const { Buffer } = require ( 'buffer' ) ;
4143const util = require ( 'util' ) ;
@@ -45,6 +47,7 @@ const {
4547 defaultTriggerAsyncIdScope,
4648 symbols : { async_id_symbol, owner_symbol }
4749} = require ( 'internal/async_hooks' ) ;
50+ const { isInt32 } = require ( 'internal/validators' ) ;
4851const { UV_UDP_REUSEADDR } = process . binding ( 'constants' ) . os ;
4952
5053const { UDP , SendWrap } = process . binding ( 'udp_wrap' ) ;
@@ -151,6 +154,28 @@ function bufferSize(self, size, buffer) {
151154 return ret ;
152155}
153156
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+
154179Socket . prototype . bind = function ( port_ , address_ /* , callback */ ) {
155180 let port = port_ ;
156181
@@ -171,6 +196,44 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) {
171196 return this ;
172197 }
173198
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+
174237 var address ;
175238 var exclusive ;
176239
@@ -207,28 +270,18 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) {
207270 flags |= UV_UDP_REUSEADDR ;
208271
209272 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 , {
226274 address : ip ,
227275 port : port ,
228276 addressType : this . type ,
229277 fd : - 1 ,
230278 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+ } ) ;
232285 } else {
233286 if ( ! state . handle )
234287 return ; // handle has been closed in the mean time
0 commit comments