Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6014d66
crypto: add randomFill and randomFillSync
evanlucas Dec 9, 2016
631b441
doc: improve randomfill and fix broken link
thefourtheye Apr 20, 2017
4afecfc
lib: return this from net.Socket.end()
sam-github Jun 5, 2017
19955c6
net: return this from getConnections()
sam-github Jun 7, 2017
5c18651
repl: improve require() autocompletion
aqrln Jul 21, 2017
79a3e37
console: add console.count() and console.clear()
jasnell Apr 26, 2017
5c20548
dgram: added setMulticastInterface()
lostnet Jul 23, 2016
0912453
test: don't skip when common.mustCall() is pending
cjihrig Sep 14, 2017
d7ac63e
test: crypto createClass instanceof Class
bengl Aug 19, 2016
809858c
crypto: expose ECDH class
bengl Aug 19, 2016
542f13f
test: fix flaky test-crypto-classes.js
bengl Sep 28, 2017
23ad5cb
tools, build: refactor macOS installer
jpwesselink Sep 4, 2017
1558a90
deps: upgrade libuv to 1.16.1
cjihrig Nov 10, 2017
61728e7
src: add process.ppid
cjihrig Oct 30, 2017
dd2102d
src: add --use-bundled-ca --use-openssl-ca check
danbev Mar 28, 2017
c3d5fb3
src: guard bundled_ca/openssl_ca with HAVE_OPENSSL
danbev Apr 10, 2017
8e89616
src: fix incorrect macro comment
danbev Apr 27, 2017
3c4bb3c
crypto: remove BIO_set_shutdown
danbev Dec 7, 2017
ba2af51
src: clean up MaybeStackBuffer
TimothyGu Nov 28, 2017
df835c4
test: add common.hasIntl
jasnell Oct 23, 2016
5a13d1a
url: update IDNA handling
TimothyGu Jun 1, 2017
3639d0c
url: adding WHATWG URL support
jasnell Nov 28, 2017
3e7f0fc
promises: more robust stringification
TimothyGu Jun 19, 2017
f374d60
test: fix truncation of argv
danbev Mar 29, 2017
b8e561e
http: overridable keep-alive behavior of `Agent`
indutny Jan 15, 2018
a511b49
src: add openssl-system-ca-path configure option
danbev Nov 6, 2017
ae9af7a
module: add builtinModules
maclover7 Nov 24, 2017
9f571ef
deps: ICU 59.1 bump
srl295 Apr 13, 2017
a164c9a
deps: ICU 60 bump
srl295 Sep 21, 2017
c0aee51
deps: ICU 60.2 bump
srl295 Dec 14, 2017
f14a715
fixup: potential hack for null_ptr
MylesBorins Feb 2, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
dgram: added setMulticastInterface()
Add wrapper for uv's uv_udp_set_multicast_interface which provides the
sender side mechanism to explicitly select an interface. The
equivalent receiver side mechanism is the optional 2nd argument of
addMembership().

PR-URL: #7855
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
  • Loading branch information
lostnet authored and MylesBorins committed Jan 17, 2018
commit 5c205487c34f2f1538b4265bc125e3486f4eeddc
81 changes: 81 additions & 0 deletions doc/api/dgram.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,84 @@ added: v0.6.9
Sets or clears the `SO_BROADCAST` socket option. When set to `true`, UDP
packets may be sent to a local interface's broadcast address.

### socket.setMulticastInterface(multicastInterface)
<!-- YAML
added: REPLACEME
-->

* `multicastInterface` {String}

*Note: All references to scope in this section are refering to
[IPv6 Zone Indices][], which are defined by [RFC 4007][]. In string form, an IP
with a scope index is written as `'IP%scope'` where scope is an interface name or
interface number.*

Sets the default outgoing multicast interface of the socket to a chosen
interface or back to system interface selection. The `multicastInterface` must
be a valid string representation of an IP from the socket's family.

For IPv4 sockets, this should be the IP configured for the desired physical
interface. All packets sent to multicast on the socket will be sent on the
interface determined by the most recent successful use of this call.

For IPv6 sockets, `multicastInterface` should include a scope to indicate the
interface as in the examples that follow. In IPv6, individual `send` calls can
also use explicit scope in addresses, so only packets sent to a multicast
address without specifying an explicit scope are affected by the most recent
successful use of this call.

#### Examples: IPv6 Outgoing Multicast Interface

On most systems, where scope format uses the interface name:

```js
const socket = dgram.createSocket('udp6');

socket.bind(1234, () => {
socket.setMulticastInterface('::%eth1');
});
```

On Windows, where scope format uses an interface number:

```js
const socket = dgram.createSocket('udp6');

socket.bind(1234, () => {
socket.setMulticastInterface('::%2');
});
```

#### Example: IPv4 Outgoing Multicast Interface
All systems use an IP of the host on the desired physical interface:
```js
const socket = dgram.createSocket('udp4');

socket.bind(1234, () => {
socket.setMulticastInterface('10.0.0.2');
});
```

#### Call Results

A call on a socket that is not ready to send or no longer open may throw a *Not
running* [`Error`][].

If `multicastInterface` can not be parsed into an IP then an *EINVAL*
[`System Error`][] is thrown.

On IPv4, if `multicastInterface` is a valid address but does not match any
interface, or if the address does not match the family then
a [`System Error`][] such as `EADDRNOTAVAIL` or `EPROTONOSUP` is thrown.

On IPv6, most errors with specifying or omiting scope will result in the socket
continuing to use (or returning to) the system's default interface selection.

A socket's address family's ANY address (IPv4 `'0.0.0.0'` or IPv6 `'::'`) can be
used to return control of the sockets default outgoing interface to the system
for future multicast packets.


### socket.setMulticastLoopback(flag)
<!-- YAML
added: v0.3.8
Expand Down Expand Up @@ -490,4 +568,7 @@ and `udp6` sockets). The bound address and port can be retrieved using
[`socket.address().address`]: #dgram_socket_address
[`socket.address().port`]: #dgram_socket_address
[`socket.bind()`]: #dgram_socket_bind_port_address_callback
[`System Error`]: errors.html#errors_class_system_error
[byte length]: buffer.html#buffer_class_method_buffer_bytelength_string_encoding
[IPv6 Zone Indices]: https://en.wikipedia.org/wiki/IPv6_address#Link-local_addresses_and_zone_indices
[RFC 4007]: https://tools.ietf.org/html/rfc4007
13 changes: 13 additions & 0 deletions lib/dgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,19 @@ Socket.prototype.setMulticastLoopback = function(arg) {
};


Socket.prototype.setMulticastInterface = function(interfaceAddress) {
this._healthCheck();

if (typeof interfaceAddress !== 'string') {
throw new TypeError('"interfaceAddress" argument must be a string');
}

const err = this._handle.setMulticastInterface(interfaceAddress);
if (err) {
throw errnoException(err, 'setMulticastInterface');
}
};

Socket.prototype.addMembership = function(multicastAddress,
interfaceAddress) {
this._healthCheck();
Expand Down
17 changes: 17 additions & 0 deletions src/udp_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ void UDPWrap::Initialize(Local<Object> target,
GetSockOrPeerName<UDPWrap, uv_udp_getsockname>);
env->SetProtoMethod(t, "addMembership", AddMembership);
env->SetProtoMethod(t, "dropMembership", DropMembership);
env->SetProtoMethod(t, "setMulticastInterface", SetMulticastInterface);
env->SetProtoMethod(t, "setMulticastTTL", SetMulticastTTL);
env->SetProtoMethod(t, "setMulticastLoopback", SetMulticastLoopback);
env->SetProtoMethod(t, "setBroadcast", SetBroadcast);
Expand Down Expand Up @@ -208,6 +209,22 @@ X(SetMulticastLoopback, uv_udp_set_multicast_loop)

#undef X

void UDPWrap::SetMulticastInterface(const FunctionCallbackInfo<Value>& args) {
UDPWrap* wrap;
ASSIGN_OR_RETURN_UNWRAP(&wrap,
args.Holder(),
args.GetReturnValue().Set(UV_EBADF));

CHECK_EQ(args.Length(), 1);
CHECK(args[0]->IsString());

Utf8Value iface(args.GetIsolate(), args[0]);

const char* iface_cstr = *iface;

int err = uv_udp_set_multicast_interface(&wrap->handle_, iface_cstr);
args.GetReturnValue().Set(err);
}

void UDPWrap::SetMembership(const FunctionCallbackInfo<Value>& args,
uv_membership membership) {
Expand Down
2 changes: 2 additions & 0 deletions src/udp_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class UDPWrap: public HandleWrap {
static void RecvStop(const v8::FunctionCallbackInfo<v8::Value>& args);
static void AddMembership(const v8::FunctionCallbackInfo<v8::Value>& args);
static void DropMembership(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetMulticastInterface(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetMulticastTTL(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetMulticastLoopback(
const v8::FunctionCallbackInfo<v8::Value>& args);
Expand Down
4 changes: 3 additions & 1 deletion test/internet/test-dgram-multicast-multi-process.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const assert = require('assert');
const dgram = require('dgram');
const fork = require('child_process').fork;
const LOCAL_BROADCAST_HOST = '224.0.0.114';
const LOCAL_HOST_IFADDR = '0.0.0.0';
const TIMEOUT = common.platformTimeout(5000);
const messages = [
Buffer.from('First message to send'),
Expand Down Expand Up @@ -136,6 +137,7 @@ if (process.argv[2] !== 'child') {
sendSocket.setBroadcast(true);
sendSocket.setMulticastTTL(1);
sendSocket.setMulticastLoopback(true);
sendSocket.setMulticastInterface(LOCAL_HOST_IFADDR);
});

sendSocket.on('close', function() {
Expand Down Expand Up @@ -175,7 +177,7 @@ if (process.argv[2] === 'child') {
});

listenSocket.on('listening', function() {
listenSocket.addMembership(LOCAL_BROADCAST_HOST);
listenSocket.addMembership(LOCAL_BROADCAST_HOST, LOCAL_HOST_IFADDR);

listenSocket.on('message', function(buf, rinfo) {
console.error('[CHILD] %s received "%s" from %j', process.pid,
Expand Down
Loading