@@ -38,6 +38,15 @@ const {
38
38
owner_symbol,
39
39
} ,
40
40
} = require ( 'internal/async_hooks' ) ;
41
+ const dgram = require ( 'dgram' ) ;
42
+ const internalDgram = require ( 'internal/dgram' ) ;
43
+
44
+ const {
45
+ constants : {
46
+ UV_UDP_IPV6ONLY ,
47
+ UV_UDP_REUSEADDR ,
48
+ }
49
+ } = internalBinding ( 'udp_wrap' ) ;
41
50
42
51
const {
43
52
writeGeneric,
@@ -59,7 +68,6 @@ const {
59
68
const {
60
69
codes : {
61
70
ERR_INVALID_ARG_TYPE ,
62
- ERR_INVALID_ARG_VALUE ,
63
71
ERR_INVALID_CALLBACK ,
64
72
ERR_OUT_OF_RANGE ,
65
73
ERR_QUIC_ERROR ,
@@ -90,8 +98,6 @@ const {
90
98
constants : {
91
99
AF_INET ,
92
100
AF_INET6 ,
93
- UV_UDP_IPV6ONLY ,
94
- UV_UDP_REUSEADDR ,
95
101
NGTCP2_ALPN_H3 ,
96
102
NGTCP2_MAX_CIDLEN ,
97
103
NGTCP2_MIN_CIDLEN ,
@@ -221,11 +227,6 @@ function setTransportParams(config) {
221
227
sessionConfig [ IDX_QUIC_SESSION_CONFIG_COUNT ] = flags ;
222
228
}
223
229
224
- // Called when the socket has been bound and is ready for use
225
- function onSocketReady ( fd ) {
226
- this [ owner_symbol ] [ kReady ] ( fd ) ;
227
- }
228
-
229
230
// Called when the socket is closed
230
231
function onSocketClose ( ) {
231
232
this [ owner_symbol ] . destroy ( ) ;
@@ -436,7 +437,6 @@ function onSessionSilentClose(statelessReset, code, family) {
436
437
437
438
// Register the callbacks with the QUIC internal binding.
438
439
setCallbacks ( {
439
- onSocketReady,
440
440
onSocketClose,
441
441
onSocketError,
442
442
onSocketServerBusy,
@@ -620,6 +620,8 @@ class QuicSocket extends EventEmitter {
620
620
#type = undefined ;
621
621
#alpn = undefined ;
622
622
#stats = undefined ;
623
+ #udpSocket = undefined ;
624
+ #udpHandle = undefined ;
623
625
624
626
constructor ( options = { } ) {
625
627
const {
@@ -667,11 +669,17 @@ class QuicSocket extends EventEmitter {
667
669
const socketOptions =
668
670
( validateAddress ? QUICSOCKET_OPTIONS_VALIDATE_ADDRESS : 0 ) |
669
671
( validateAddressLRU ? QUICSOCKET_OPTIONS_VALIDATE_ADDRESS_LRU : 0 ) ;
672
+ this . #udpSocket = dgram . createSocket ( type === AF_INET6 ? 'udp6' : 'udp4' ) ;
673
+ // TODO(addaleax): Ideally, we would not be needing to store the handle
674
+ // separately, and only pass it to the QuicSocketHandle constructor.
675
+ this . #udpHandle = this . #udpSocket[ internalDgram . kStateSymbol ] . handle ;
670
676
const handle =
671
677
new QuicSocketHandle (
678
+ this . #udpHandle,
672
679
socketOptions ,
673
680
retryTokenTimeout ,
674
681
maxConnectionsPerHost ) ;
682
+ this . #udpHandle. quicSocket = handle ;
675
683
handle [ owner_symbol ] = this ;
676
684
this [ async_id_symbol ] = handle . getAsyncId ( ) ;
677
685
this [ kSetHandle ] ( handle ) ;
@@ -728,14 +736,16 @@ class QuicSocket extends EventEmitter {
728
736
const flags =
729
737
( this . #reuseAddr ? UV_UDP_REUSEADDR : 0 ) ||
730
738
( this . #ipv6Only ? UV_UDP_IPV6ONLY : 0 ) ;
731
- const ret = this [ kHandle ] . bind ( this . #type , ip , this . #port || 0 , flags ) ;
739
+ const ret = this . #udpHandle . bind ( ip , this . #port || 0 , flags ) ;
732
740
if ( ret ) {
733
741
this . destroy ( exceptionWithHostPort ( ret , 'bind' , ip , this . #port || 0 ) ) ;
734
742
return ;
735
743
}
736
744
737
745
if ( typeof callback === 'function' )
738
746
callback ( ) ;
747
+
748
+ this [ kReady ] ( this . #udpHandle. fd ) ;
739
749
}
740
750
741
751
// The kReady function is called after the socket has been bound to the
@@ -913,20 +923,23 @@ class QuicSocket extends EventEmitter {
913
923
if ( handle !== undefined ) {
914
924
this [ kSetHandle ] ( ) ;
915
925
handle [ owner_symbol ] = undefined ;
916
- handle . close ( ( err ) => {
917
- // If an error occurs while attempting to close, it will take
918
- // precedence over any original error specified on the args
919
- // TODO(@jasnell): Alternatively we might set the original
920
- // error as a property on the new error.
921
- if ( err ) error = err ;
922
-
923
- // Capture a copy of the stats as they will no longer be
924
- // available once this function returns.
925
- this . #stats = new BigInt64Array ( handle . stats ) ;
926
-
927
- if ( error ) process . nextTick ( emit . bind ( this , 'error' , error ) ) ;
928
- process . nextTick ( emit . bind ( this , 'close' ) ) ;
929
- } ) ;
926
+ handle . ondone = ( ) => {
927
+ this . #udpSocket. close ( ( err ) => {
928
+ // If an error occurs while attempting to close, it will take
929
+ // precedence over any original error specified on the args
930
+ // TODO(@jasnell): Alternatively we might set the original
931
+ // error as a property on the new error.
932
+ if ( err ) error = err ;
933
+
934
+ // Capture a copy of the stats as they will no longer be
935
+ // available once this function returns.
936
+ this . #stats = new BigInt64Array ( handle . stats ) ;
937
+
938
+ if ( error ) process . nextTick ( emit . bind ( this , 'error' , error ) ) ;
939
+ process . nextTick ( emit . bind ( this , 'close' ) ) ;
940
+ } ) ;
941
+ } ;
942
+ handle . waitForPendingCallbacks ( ) ;
930
943
}
931
944
}
932
945
@@ -1064,14 +1077,14 @@ class QuicSocket extends EventEmitter {
1064
1077
ref ( ) {
1065
1078
if ( this . #state === kSocketDestroyed )
1066
1079
throw new ERR_QUICSOCKET_DESTROYED ( 'ref' ) ;
1067
- this [ kHandle ] . ref ( ) ;
1080
+ this . #udpSocket . ref ( ) ;
1068
1081
return this ;
1069
1082
}
1070
1083
1071
1084
unref ( ) {
1072
1085
if ( this . #state === kSocketDestroyed )
1073
1086
throw new ERR_QUICSOCKET_DESTROYED ( 'unref' ) ;
1074
- this [ kHandle ] . unref ( ) ;
1087
+ this . #udpSocket . unref ( ) ;
1075
1088
return this ;
1076
1089
}
1077
1090
@@ -1082,11 +1095,16 @@ class QuicSocket extends EventEmitter {
1082
1095
get address ( ) {
1083
1096
const out = { } ;
1084
1097
if ( this . #state !== kSocketDestroyed ) {
1085
- const err = this [ kHandle ] . getsockname ( out ) ;
1086
- // If err is returned, socket is not bound.
1087
- // Return empty object
1088
- if ( err )
1089
- return { } ;
1098
+ try {
1099
+ return this . #udpSocket. address ( ) ;
1100
+ } catch ( err ) {
1101
+ if ( err . code === 'EBADF' ) {
1102
+ // If there is an EBADF error, the socket is not bound.
1103
+ // Return empty object
1104
+ return { } ;
1105
+ }
1106
+ throw err ;
1107
+ }
1090
1108
}
1091
1109
return out ;
1092
1110
}
@@ -1114,85 +1132,49 @@ class QuicSocket extends EventEmitter {
1114
1132
setTTL ( ttl ) {
1115
1133
if ( this . #state === kSocketDestroyed )
1116
1134
throw new ERR_QUICSOCKET_DESTROYED ( 'setTTL' ) ;
1117
- if ( typeof ttl !== 'number' )
1118
- throw new ERR_INVALID_ARG_TYPE ( 'ttl' , 'number' , ttl ) ;
1119
- if ( ttl < 1 || ttl > 255 )
1120
- throw new ERR_INVALID_ARG_VALUE ( 'ttl' , ttl ) ;
1121
- const err = this [ kHandle ] . setTTL ( ttl ) ;
1122
- if ( err )
1123
- throw errnoException ( err , 'dropMembership' ) ;
1135
+ this . #udpSocket. setTTL ( ttl ) ;
1124
1136
return this ;
1125
1137
}
1126
1138
1127
1139
setMulticastTTL ( ttl ) {
1128
1140
if ( this . #state === kSocketDestroyed )
1129
1141
throw new ERR_QUICSOCKET_DESTROYED ( 'setMulticastTTL' ) ;
1130
- if ( typeof ttl !== 'number' )
1131
- throw new ERR_INVALID_ARG_TYPE ( 'ttl' , 'number' , ttl ) ;
1132
- if ( ttl < 1 || ttl > 255 )
1133
- throw new ERR_INVALID_ARG_VALUE ( 'ttl' , ttl ) ;
1134
- const err = this [ kHandle ] . setMulticastTTL ( ttl ) ;
1135
- if ( err )
1136
- throw errnoException ( err , 'dropMembership' ) ;
1142
+ this . #udpSocket. setMulticastTTL ( ttl ) ;
1137
1143
return this ;
1138
1144
}
1139
1145
1140
1146
setBroadcast ( on = true ) {
1141
1147
if ( this . #state === kSocketDestroyed )
1142
1148
throw new ERR_QUICSOCKET_DESTROYED ( 'setBroadcast' ) ;
1143
- if ( typeof on !== 'boolean' )
1144
- throw new ERR_INVALID_ARG_TYPE ( 'on' , 'boolean' , on ) ;
1145
- const err = this [ kHandle ] . setBroadcast ( on ) ;
1146
- if ( err )
1147
- throw errnoException ( err , 'dropMembership' ) ;
1149
+ this . #udpSocket. setBroadcast ( on ) ;
1148
1150
return this ;
1149
1151
}
1150
1152
1151
1153
setMulticastLoopback ( on = true ) {
1152
1154
if ( this . #state === kSocketDestroyed )
1153
1155
throw new ERR_QUICSOCKET_DESTROYED ( 'setMulticastLoopback' ) ;
1154
- if ( typeof on !== 'boolean' )
1155
- throw new ERR_INVALID_ARG_TYPE ( 'on' , 'boolean' , on ) ;
1156
- const err = this [ kHandle ] . setMulticastLoopback ( on ) ;
1157
- if ( err )
1158
- throw errnoException ( err , 'dropMembership' ) ;
1156
+ this . #udpSocket. setMulticastLoopback ( on ) ;
1159
1157
return this ;
1160
1158
}
1161
1159
1162
1160
setMulticastInterface ( iface ) {
1163
1161
if ( this . #state === kSocketDestroyed )
1164
1162
throw new ERR_QUICSOCKET_DESTROYED ( 'setMulticastInterface' ) ;
1165
- if ( typeof iface !== 'string' )
1166
- throw new ERR_INVALID_ARG_TYPE ( 'iface' , 'string' , iface ) ;
1167
- const err = this [ kHandle ] . setMulticastInterface ( iface ) ;
1168
- if ( err )
1169
- throw errnoException ( err , 'dropMembership' ) ;
1163
+ this . #udpSocket. setMulticastInterface ( iface ) ;
1170
1164
return this ;
1171
1165
}
1172
1166
1173
1167
addMembership ( address , iface ) {
1174
1168
if ( this . #state === kSocketDestroyed )
1175
1169
throw new ERR_QUICSOCKET_DESTROYED ( 'addMembership' ) ;
1176
- if ( typeof address !== 'string' )
1177
- throw new ERR_INVALID_ARG_TYPE ( 'address' , 'string' , address ) ;
1178
- if ( typeof iface !== 'string' )
1179
- throw new ERR_INVALID_ARG_TYPE ( 'iface' , 'string' , iface ) ;
1180
- const err = this [ kHandle ] . addMembership ( address , iface ) ;
1181
- if ( err )
1182
- throw errnoException ( err , 'addMembership' ) ;
1170
+ this . #udpSocket. addMembership ( address , iface ) ;
1183
1171
return this ;
1184
1172
}
1185
1173
1186
1174
dropMembership ( address , iface ) {
1187
1175
if ( this . #state === kSocketDestroyed )
1188
1176
throw new ERR_QUICSOCKET_DESTROYED ( 'dropMembership' ) ;
1189
- if ( typeof address !== 'string' )
1190
- throw new ERR_INVALID_ARG_TYPE ( 'address' , 'string' , address ) ;
1191
- if ( typeof iface !== 'string' )
1192
- throw new ERR_INVALID_ARG_TYPE ( 'iface' , 'string' , iface ) ;
1193
- const err = this [ kHandle ] . dropMembership ( address , iface ) ;
1194
- if ( err )
1195
- throw errnoException ( err , 'dropMembership' ) ;
1177
+ this . #udpSocket. dropMembership ( address , iface ) ;
1196
1178
return this ;
1197
1179
}
1198
1180
0 commit comments