Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1aeca6d

Browse filesBrowse files
Lucas Parduen-thumannTrott
authored andcommitted
dgram: add source-specific multicast support
This adds RFC 4607 support for IPv4 and IPv6. Co-Authored-By: Nicolas Thumann <46975855+n-thumann@users.noreply.github.com> Co-Authored-By: Rich Trott <rtrott@gmail.com> PR-URL: #15735 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 497b59b commit 1aeca6d
Copy full SHA for 1aeca6d

File tree

Expand file treeCollapse file tree

6 files changed

+589
-0
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

6 files changed

+589
-0
lines changed
Open diff view settings
Collapse file

‎doc/api/dgram.md‎

Copy file name to clipboardExpand all lines: doc/api/dgram.md
+33Lines changed: 33 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,21 @@ if (cluster.isMaster) {
123123
}
124124
```
125125

126+
### `socket.addSourceSpecificMembership(sourceAddress, groupAddress[, multicastInterface])`
127+
<!-- YAML
128+
added: REPLACEME
129+
-->
130+
* `sourceAddress` {string}
131+
* `groupAddress` {string}
132+
* `multicastInterface` {string}
133+
134+
Tells the kernel to join a source-specific multicast channel at the given
135+
`sourceAddress` and `groupAddress`, using the `multicastInterface` with the
136+
`IP_ADD_SOURCE_MEMBERSHIP` socket option. If the `multicastInterface` argument
137+
is not specified, the operating system will choose one interface and will add
138+
membership to it. To add membership to every available interface, call
139+
`socket.addSourceSpecificMembership()` multiple times, once per interface.
140+
126141
### `socket.address()`
127142
<!-- YAML
128143
added: v0.1.99
@@ -297,6 +312,24 @@ never have reason to call this.
297312
If `multicastInterface` is not specified, the operating system will attempt to
298313
drop membership on all valid interfaces.
299314

315+
### `socket.dropSourceSpecificMembership(sourceAddress, groupAddress[, multicastInterface])`
316+
<!-- YAML
317+
added: REPLACEME
318+
-->
319+
320+
* `sourceAddress` {string}
321+
* `groupAddress` {string}
322+
* `multicastInterface` {string}
323+
324+
Instructs the kernel to leave a source-specific multicast channel at the given
325+
`sourceAddress` and `groupAddress` using the `IP_DROP_SOURCE_MEMBERSHIP`
326+
socket option. This method is automatically called by the kernel when the
327+
socket is closed or the process terminates, so most apps will never have
328+
reason to call this.
329+
330+
If `multicastInterface` is not specified, the operating system will attempt to
331+
drop membership on all valid interfaces.
332+
300333
### `socket.getRecvBufferSize()`
301334
<!-- YAML
302335
added: v8.7.0
Collapse file

‎lib/dgram.js‎

Copy file name to clipboardExpand all lines: lib/dgram.js
+49Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,55 @@ Socket.prototype.dropMembership = function(multicastAddress,
845845
}
846846
};
847847

848+
Socket.prototype.addSourceSpecificMembership = function(sourceAddress,
849+
groupAddress,
850+
interfaceAddress) {
851+
healthCheck(this);
852+
853+
if (typeof sourceAddress !== 'string') {
854+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'sourceAddress',
855+
'string');
856+
}
857+
858+
if (typeof groupAddress !== 'string') {
859+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'groupAddress',
860+
'string');
861+
}
862+
863+
const err =
864+
this[kStateSymbol].handle.addSourceSpecificMembership(sourceAddress,
865+
groupAddress,
866+
interfaceAddress);
867+
if (err) {
868+
throw errnoException(err, 'addSourceSpecificMembership');
869+
}
870+
};
871+
872+
873+
Socket.prototype.dropSourceSpecificMembership = function(sourceAddress,
874+
groupAddress,
875+
interfaceAddress) {
876+
healthCheck(this);
877+
878+
if (typeof sourceAddress !== 'string') {
879+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'sourceAddress',
880+
'string');
881+
}
882+
883+
if (typeof groupAddress !== 'string') {
884+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'groupAddress',
885+
'string');
886+
}
887+
888+
const err =
889+
this[kStateSymbol].handle.dropSourceSpecificMembership(sourceAddress,
890+
groupAddress,
891+
interfaceAddress);
892+
if (err) {
893+
throw errnoException(err, 'dropSourceSpecificMembership');
894+
}
895+
};
896+
848897

849898
function healthCheck(socket) {
850899
if (!socket[kStateSymbol].handle) {
Collapse file

‎src/udp_wrap.cc‎

Copy file name to clipboardExpand all lines: src/udp_wrap.cc
+42Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ void UDPWrap::Initialize(Local<Object> target,
128128
GetSockOrPeerName<UDPWrap, uv_udp_getsockname>);
129129
env->SetProtoMethod(t, "addMembership", AddMembership);
130130
env->SetProtoMethod(t, "dropMembership", DropMembership);
131+
env->SetProtoMethod(t, "addSourceSpecificMembership",
132+
AddSourceSpecificMembership);
133+
env->SetProtoMethod(t, "dropSourceSpecificMembership",
134+
DropSourceSpecificMembership);
131135
env->SetProtoMethod(t, "setMulticastInterface", SetMulticastInterface);
132136
env->SetProtoMethod(t, "setMulticastTTL", SetMulticastTTL);
133137
env->SetProtoMethod(t, "setMulticastLoopback", SetMulticastLoopback);
@@ -397,6 +401,44 @@ void UDPWrap::DropMembership(const FunctionCallbackInfo<Value>& args) {
397401
SetMembership(args, UV_LEAVE_GROUP);
398402
}
399403

404+
void UDPWrap::SetSourceMembership(const FunctionCallbackInfo<Value>& args,
405+
uv_membership membership) {
406+
UDPWrap* wrap;
407+
ASSIGN_OR_RETURN_UNWRAP(&wrap,
408+
args.Holder(),
409+
args.GetReturnValue().Set(UV_EBADF));
410+
411+
CHECK_EQ(args.Length(), 3);
412+
413+
node::Utf8Value source_address(args.GetIsolate(), args[0]);
414+
node::Utf8Value group_address(args.GetIsolate(), args[1]);
415+
node::Utf8Value iface(args.GetIsolate(), args[2]);
416+
417+
if (*iface == nullptr) return;
418+
const char* iface_cstr = *iface;
419+
if (args[2]->IsUndefined() || args[2]->IsNull()) {
420+
iface_cstr = nullptr;
421+
}
422+
423+
int err = uv_udp_set_source_membership(&wrap->handle_,
424+
*group_address,
425+
iface_cstr,
426+
*source_address,
427+
membership);
428+
args.GetReturnValue().Set(err);
429+
}
430+
431+
void UDPWrap::AddSourceSpecificMembership(
432+
const FunctionCallbackInfo<Value>& args) {
433+
SetSourceMembership(args, UV_JOIN_GROUP);
434+
}
435+
436+
437+
void UDPWrap::DropSourceSpecificMembership(
438+
const FunctionCallbackInfo<Value>& args) {
439+
SetSourceMembership(args, UV_LEAVE_GROUP);
440+
}
441+
400442

401443
void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
402444
Environment* env = Environment::GetCurrent(args);
Collapse file

‎src/udp_wrap.h‎

Copy file name to clipboardExpand all lines: src/udp_wrap.h
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ class UDPWrap: public HandleWrap {
5555
static void RecvStop(const v8::FunctionCallbackInfo<v8::Value>& args);
5656
static void AddMembership(const v8::FunctionCallbackInfo<v8::Value>& args);
5757
static void DropMembership(const v8::FunctionCallbackInfo<v8::Value>& args);
58+
static void AddSourceSpecificMembership(
59+
const v8::FunctionCallbackInfo<v8::Value>& args);
60+
static void DropSourceSpecificMembership(
61+
const v8::FunctionCallbackInfo<v8::Value>& args);
5862
static void SetMulticastInterface(
5963
const v8::FunctionCallbackInfo<v8::Value>& args);
6064
static void SetMulticastTTL(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -88,6 +92,9 @@ class UDPWrap: public HandleWrap {
8892
int family);
8993
static void SetMembership(const v8::FunctionCallbackInfo<v8::Value>& args,
9094
uv_membership membership);
95+
static void SetSourceMembership(
96+
const v8::FunctionCallbackInfo<v8::Value>& args,
97+
uv_membership membership);
9198

9299
static void OnAlloc(uv_handle_t* handle,
93100
size_t suggested_size,

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.