Skip to content

Commit

Permalink
Multicast bindings (#57)
Browse files Browse the repository at this point in the history
Co-authored-by: jthomas <jthomas-dev@protonmail.com>
  • Loading branch information
jthomas43 and jthomas authored Dec 18, 2024
1 parent 3d770ee commit d24f9d2
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ Creates a new socket instance.
Available `options`:
```js
{
ipv6Only: false
ipv6Only: false,
reuseAddress: false
}
```

Expand Down
41 changes: 41 additions & 0 deletions binding.c
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,39 @@ udx_napi_socket_set_ttl (napi_env env, napi_callback_info info) {
return NULL;
}

napi_value
udx_napi_socket_set_membership (napi_env env, napi_callback_info info) {
napi_value argv[4];
size_t argc = 4;

napi_get_cb_info(env, info, &argc, argv, NULL, NULL);

udx_socket_t *socket;
size_t socket_len;
napi_get_buffer_info(env, argv[0], (void **) &socket, &socket_len);

char mcast_addr[INET6_ADDRSTRLEN];
size_t mcast_addr_len;
napi_get_value_string_utf8(env, argv[1], mcast_addr, INET6_ADDRSTRLEN, &mcast_addr_len);

char iface_addr[INET6_ADDRSTRLEN];
size_t iface_addr_len;
napi_get_value_string_utf8(env, argv[2], iface_addr, INET6_ADDRSTRLEN, &iface_addr_len);

char *iface_param = iface_addr_len > 0 ? iface_addr : NULL;

bool join; // true for join, false for leave
napi_get_value_bool(env, argv[3], &join);

int err = udx_socket_set_membership(socket, mcast_addr, iface_param, join ? UV_JOIN_GROUP : UV_LEAVE_GROUP);
if (err < 0) {
napi_throw_error(env, uv_err_name(err), uv_strerror(err));
return NULL;
}

return NULL;
}

napi_value
udx_napi_socket_get_recv_buffer_size (napi_env env, napi_callback_info info) {
napi_value argv[1];
Expand Down Expand Up @@ -1776,6 +1809,10 @@ napi_macros_init (napi_env env, napi_value exports) {
napi_create_uint32(env, UV_UDP_IPV6ONLY, &UV_UDP_IPV6ONLY_uint32);
napi_set_named_property(env, exports, "UV_UDP_IPV6ONLY", UV_UDP_IPV6ONLY_uint32);

napi_value UV_UDP_REUSEADDR_uint32;
napi_create_uint32(env, UV_UDP_REUSEADDR, &UV_UDP_REUSEADDR_uint32);
napi_set_named_property(env, exports, "UV_UDP_REUSEADDR", UV_UDP_REUSEADDR_uint32);

napi_value inflight_offsetof;
napi_create_uint32(env, offsetof(udx_stream_t, inflight), &inflight_offsetof);
napi_set_named_property(env, exports, "offsetof_udx_stream_t_inflight", inflight_offsetof);
Expand Down Expand Up @@ -1920,6 +1957,10 @@ napi_macros_init (napi_env env, napi_value exports) {
napi_create_function(env, NULL, 0, udx_napi_socket_set_send_buffer_size, NULL, &udx_napi_socket_set_send_buffer_size_fn);
napi_set_named_property(env, exports, "udx_napi_socket_set_send_buffer_size", udx_napi_socket_set_send_buffer_size_fn);

napi_value udx_napi_socket_set_membership_fn;
napi_create_function(env, NULL, 0, udx_napi_socket_set_membership, NULL, &udx_napi_socket_set_membership_fn);
napi_set_named_property(env, exports, "udx_napi_socket_set_membership", udx_napi_socket_set_membership_fn);

napi_value udx_napi_socket_send_ttl_fn;
napi_create_function(env, NULL, 0, udx_napi_socket_send_ttl, NULL, &udx_napi_socket_send_ttl_fn);
napi_set_named_property(env, exports, "udx_napi_socket_send_ttl", udx_napi_socket_send_ttl_fn);
Expand Down
13 changes: 13 additions & 0 deletions lib/socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module.exports = class UDXSocket extends events.EventEmitter {
this._host = null
this._family = 0
this._ipv6Only = opts.ipv6Only === true
this._reuseAddress = opts.reuseAddress === true
this._port = 0
this._reqs = []
this._free = []
Expand Down Expand Up @@ -75,6 +76,7 @@ module.exports = class UDXSocket extends events.EventEmitter {
streams: this.streams.size,
address: this.address(),
ipv6Only: this._ipv6Only,
reuseAddress: this._reuseAddress,
idle: this.idle,
busy: this.busy
}
Expand Down Expand Up @@ -161,6 +163,7 @@ module.exports = class UDXSocket extends events.EventEmitter {

let flags = 0
if (this._ipv6Only) flags |= binding.UV_UDP_IPV6ONLY
if (this._reuseAddress) flags |= binding.UV_UDP_REUSEADDR

let family

Expand Down Expand Up @@ -240,6 +243,16 @@ module.exports = class UDXSocket extends events.EventEmitter {
return binding.udx_napi_socket_set_send_buffer_size(this._handle, size)
}

addMembership (group, ifaceAddress = '') {
if (!this._inited) throw new Error('Socket not active')
return binding.udx_napi_socket_set_membership(this._handle, group, ifaceAddress, true)
}

dropMembership (group, ifaceAddress = '') {
if (!this._inited) throw new Error('Socket not active')
return binding.udx_napi_socket_set_membership(this._handle, group, ifaceAddress, false)
}

async send (buffer, port, host, ttl) {
if (this.closing) return false

Expand Down
38 changes: 38 additions & 0 deletions test/socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,44 @@ test('simple message ipv6', async function (t) {
await a.send(b4a.from('hello'), a.address().port, '::1')
})

test('simple multicast message ipv4', async function (t) {
t.plan(3)
const u = new UDX()
const a = createSocket(t, u, { reuseAddress: true })

a.on('message', function (message, { host, family, port }) {
t.alike(message, b4a.from('hello'))
t.is(family, 4)
t.is(port, a.address().port)
a.dropMembership('239.1.1.1')
a.close()
})

a.bind(0, '0.0.0.0')
a.addMembership('239.1.1.1')

await (a.send(b4a.from('hello'), a.address().port, '239.1.1.1'))
})

test.skip('simple multicast message ipv6', async function (t) {
t.plan(3)
const u = new UDX()
const a = createSocket(t, u, { reuseAddress: true })

a.on('message', function (message, { host, family, port }) {
t.alike(message, b4a.from('hello'))
t.is(family, 6)
t.is(port, a.address().port)
a.dropMembership('ff12::f')
a.close()
})

a.bind(0, '::')
a.addMembership('ff12::f')

await (a.send(b4a.from('hello'), a.address().port, 'ff12::f'))
})

test('empty message', async function (t) {
t.plan(1)

Expand Down

0 comments on commit d24f9d2

Please sign in to comment.