Skip to content

Commit 76490a7

Browse files
author
Arto Kinnunen
authored
Add option to join COAP multicast group (ARMmbed#67)
* Add option to join COAP multicast group Option COAP_SERVICE_OPTIONS_MULTICAST_JOIN added to service_api to join COAP multicast group. The group is left when service is deleted.
1 parent 381d910 commit 76490a7

File tree

6 files changed

+107
-58
lines changed

6 files changed

+107
-58
lines changed

coap-service/coap_service_api.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ extern "C" {
4747
#define COAP_SERVICE_OPTIONS_EPHEMERAL_PORT 0x04
4848
/** Coap interface selected as socket interface */
4949
#define COAP_SERVICE_OPTIONS_SELECT_SOCKET_IF 0x08
50+
/** Register to COAP multicast groups */
51+
#define COAP_SERVICE_OPTIONS_MULTICAST_JOIN 0x10
5052
/** Link-layer security bypass option is set*/
5153
#define COAP_SERVICE_OPTIONS_SECURE_BYPASS 0x80
5254

source/coap_connection_handler.c

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,30 @@ static secure_session_t *secure_session_find(internal_socket_t *parent, const ui
225225
return this;
226226
}
227227

228-
static internal_socket_t *int_socket_create(uint16_t listen_port, bool use_ephemeral_port, bool is_secure, bool real_socket, bool bypassSec, int8_t socket_interface_selection)
228+
static void coap_multicast_group_join_or_leave(int8_t socket_id, uint8_t opt_name, int8_t interface_id)
229229
{
230230
ns_ipv6_mreq_t ns_ipv6_mreq;
231+
int8_t ret_val;
232+
233+
// Join or leave COAP multicast groups
234+
ns_ipv6_mreq.ipv6mr_interface = interface_id;
235+
236+
memcpy(ns_ipv6_mreq.ipv6mr_multiaddr, COAP_MULTICAST_ADDR_LINK_LOCAL, 16);
237+
ret_val = socket_setsockopt(socket_id, SOCKET_IPPROTO_IPV6, opt_name, &ns_ipv6_mreq, sizeof(ns_ipv6_mreq));
238+
239+
memcpy(ns_ipv6_mreq.ipv6mr_multiaddr, COAP_MULTICAST_ADDR_ADMIN_LOCAL, 16);
240+
ret_val |= socket_setsockopt(socket_id, SOCKET_IPPROTO_IPV6, opt_name, &ns_ipv6_mreq, sizeof(ns_ipv6_mreq));
241+
242+
memcpy(ns_ipv6_mreq.ipv6mr_multiaddr, COAP_MULTICAST_ADDR_SITE_LOCAL, 16);
243+
ret_val |= socket_setsockopt(socket_id, SOCKET_IPPROTO_IPV6, opt_name, &ns_ipv6_mreq, sizeof(ns_ipv6_mreq));
244+
245+
if (ret_val) {
246+
tr_error("Multicast group access failed, err=%d, name=%d", ret_val, opt_name);
247+
}
248+
}
249+
250+
static internal_socket_t *int_socket_create(uint16_t listen_port, bool use_ephemeral_port, bool is_secure, bool real_socket, bool bypassSec, int8_t socket_interface_selection, bool multicast_registration)
251+
{
231252
internal_socket_t *this = ns_dyn_mem_alloc(sizeof(internal_socket_t));
232253

233254
if (!this) {
@@ -276,17 +297,9 @@ static internal_socket_t *int_socket_create(uint16_t listen_port, bool use_ephem
276297
socket_setsockopt(this->socket, SOCKET_IPPROTO_IPV6, SOCKET_INTERFACE_SELECT, &socket_interface_selection, sizeof(socket_interface_selection));
277298
}
278299

279-
// Join COAP multicast group(s)
280-
ns_ipv6_mreq.ipv6mr_interface = socket_interface_selection; // It is OK to use 0 or real interface id here
281-
282-
memcpy(ns_ipv6_mreq.ipv6mr_multiaddr, COAP_MULTICAST_ADDR_LINK_LOCAL, 16);
283-
socket_setsockopt(this->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_JOIN_GROUP, &ns_ipv6_mreq, sizeof(ns_ipv6_mreq));
284-
285-
memcpy(ns_ipv6_mreq.ipv6mr_multiaddr, COAP_MULTICAST_ADDR_ADMIN_LOCAL, 16);
286-
socket_setsockopt(this->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_JOIN_GROUP, &ns_ipv6_mreq, sizeof(ns_ipv6_mreq));
287-
288-
memcpy(ns_ipv6_mreq.ipv6mr_multiaddr, COAP_MULTICAST_ADDR_SITE_LOCAL, 16);
289-
socket_setsockopt(this->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_JOIN_GROUP, &ns_ipv6_mreq, sizeof(ns_ipv6_mreq));
300+
if (multicast_registration) {
301+
coap_multicast_group_join_or_leave(this->socket, SOCKET_IPV6_JOIN_GROUP, socket_interface_selection);
302+
}
290303
} else {
291304
this->socket = virtual_socket_id_allocate();
292305
}
@@ -793,9 +806,13 @@ coap_conn_handler_t *connection_handler_create(receive_from_socket_cb *recv_from
793806

794807
return handler;
795808
}
796-
void connection_handler_destroy(coap_conn_handler_t *handler)
809+
810+
void connection_handler_destroy(coap_conn_handler_t *handler, bool multicast_group_leave)
797811
{
798812
if(handler){
813+
if (multicast_group_leave) {
814+
coap_multicast_group_join_or_leave(handler->socket->socket, SOCKET_IPV6_LEAVE_GROUP, handler->socket_interface_selection);
815+
}
799816
int_socket_delete(handler->socket);
800817
ns_dyn_mem_free(handler);
801818
}
@@ -815,7 +832,7 @@ void connection_handler_close_secure_connection( coap_conn_handler_t *handler, u
815832
}
816833
}
817834

818-
int coap_connection_handler_open_connection(coap_conn_handler_t *handler, uint16_t listen_port, bool use_ephemeral_port, bool is_secure, bool is_real_socket, bool bypassSec, int8_t socket_interface_selection)
835+
int coap_connection_handler_open_connection(coap_conn_handler_t *handler, uint16_t listen_port, bool use_ephemeral_port, bool is_secure, bool is_real_socket, bool bypassSec)
819836
{
820837
if (!handler) {
821838
return -1;
@@ -830,7 +847,7 @@ int coap_connection_handler_open_connection(coap_conn_handler_t *handler, uint16
830847

831848
internal_socket_t *current = !use_ephemeral_port?int_socket_find(listen_port, is_secure, is_real_socket, bypassSec):NULL;
832849
if (!current) {
833-
handler->socket = int_socket_create(listen_port, use_ephemeral_port, is_secure, is_real_socket, bypassSec, socket_interface_selection);
850+
handler->socket = int_socket_create(listen_port, use_ephemeral_port, is_secure, is_real_socket, bypassSec, handler->socket_interface_selection, handler->registered_to_multicast);
834851
if (!handler->socket) {
835852
return -1;
836853
}

source/coap_service_api.c

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,27 @@ static coap_service_t *service_find_by_uri(uint8_t socket_id, uint8_t *uri_ptr,
9999
return NULL;
100100
}
101101

102+
static bool coap_service_can_leave_multicast_group(coap_conn_handler_t *conn_handler)
103+
{
104+
int mc_count = 0;
105+
bool current_handler_joined_to_mc_group = false;
106+
107+
ns_list_foreach(coap_service_t, cur_ptr, &instance_list) {
108+
if (cur_ptr->conn_handler && cur_ptr->conn_handler->registered_to_multicast) {
109+
if (conn_handler == cur_ptr->conn_handler) {
110+
current_handler_joined_to_mc_group = true;
111+
}
112+
mc_count ++;
113+
}
114+
}
115+
116+
if (mc_count == 1 && current_handler_joined_to_mc_group) {
117+
// current handler is the only one joined to multicast group
118+
return true;
119+
}
120+
121+
return false;
122+
}
102123

103124
/**
104125
* Coap handling functions
@@ -280,8 +301,8 @@ static int get_passwd_cb(int8_t socket_id, uint8_t address[static 16], uint16_t
280301
int8_t coap_service_initialize(int8_t interface_id, uint16_t listen_port, uint8_t service_options,
281302
coap_service_security_start_cb *start_ptr, coap_service_security_done_cb *coap_security_done_cb)
282303
{
283-
int8_t socket_interface_selection = 0; // zero is illegal interface ID
284304
coap_service_t *this = ns_dyn_mem_alloc(sizeof(coap_service_t));
305+
285306
if (!this) {
286307
return -1;
287308
}
@@ -310,16 +331,18 @@ int8_t coap_service_initialize(int8_t interface_id, uint16_t listen_port, uint8_
310331
return -1;
311332
}
312333

334+
this->conn_handler->socket_interface_selection = 0; // zero is illegal interface ID
313335
if (this->service_options & COAP_SERVICE_OPTIONS_SELECT_SOCKET_IF) {
314-
socket_interface_selection = this->interface_id;
336+
this->conn_handler->socket_interface_selection = this->interface_id;
315337
}
316338

339+
this->conn_handler->registered_to_multicast = this->service_options & COAP_SERVICE_OPTIONS_MULTICAST_JOIN;
340+
317341
if (0 > coap_connection_handler_open_connection(this->conn_handler, listen_port,
318342
(this->service_options & COAP_SERVICE_OPTIONS_EPHEMERAL_PORT),
319343
(this->service_options & COAP_SERVICE_OPTIONS_SECURE),
320344
!(this->service_options & COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET),
321-
(this->service_options & COAP_SERVICE_OPTIONS_SECURE_BYPASS),
322-
socket_interface_selection)) {
345+
(this->service_options & COAP_SERVICE_OPTIONS_SECURE_BYPASS))) {
323346
ns_dyn_mem_free(this->conn_handler);
324347
ns_dyn_mem_free(this);
325348
return -1;
@@ -346,7 +369,12 @@ void coap_service_delete(int8_t service_id)
346369
}
347370

348371
if (this->conn_handler){
349-
connection_handler_destroy(this->conn_handler);
372+
bool leave_multicast_group = false;
373+
if (coap_service_can_leave_multicast_group(this->conn_handler)) {
374+
// This is the last handler joined to multicast group
375+
leave_multicast_group = true;
376+
}
377+
connection_handler_destroy(this->conn_handler, leave_multicast_group);
350378
}
351379

352380
//TODO clear all transactions

source/include/coap_connection_handler.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,20 @@ typedef struct coap_conn_handler_s{
4444
send_to_socket_cb *_send_cb;
4545
get_pw_cb *_get_password_cb;
4646
security_done_cb *_security_done_cb;
47+
int8_t socket_interface_selection;
48+
bool registered_to_multicast;
4749
} coap_conn_handler_t;
4850

4951
coap_conn_handler_t *connection_handler_create(receive_from_socket_cb *recv_from_cb,
5052
send_to_socket_cb *send_to_cb,
5153
get_pw_cb *pw_cb,
5254
security_done_cb *done_cb);
5355

54-
void connection_handler_destroy( coap_conn_handler_t *handler );
56+
void connection_handler_destroy( coap_conn_handler_t *handler, bool multicast_group_leave);
5557

5658
void connection_handler_close_secure_connection( coap_conn_handler_t *handler, uint8_t destination_addr_ptr[static 16], uint16_t port );
5759

58-
int coap_connection_handler_open_connection(coap_conn_handler_t *handler, uint16_t listen_port, bool use_ephemeral_port, bool is_secure, bool real_socket, bool bypassSec, int8_t socket_interface_selection);
60+
int coap_connection_handler_open_connection(coap_conn_handler_t *handler, uint16_t listen_port, bool use_ephemeral_port, bool is_secure, bool real_socket, bool bypassSec);
5961

6062
//If returns -2, it means security was started and data was not send
6163
int coap_connection_handler_send_data(coap_conn_handler_t *handler, const ns_address_t *dest_addr, const uint8_t src_address[static 16], uint8_t *data_ptr, uint16_t data_len, bool bypass_link_sec);

0 commit comments

Comments
 (0)