Skip to content

Commit 85a0e1e

Browse files
authored
Use unique IDs and internal hashtable to map SCTP associations with usrsctp (meetecho#2302)
1 parent 68f7760 commit 85a0e1e

File tree

2 files changed

+56
-9
lines changed

2 files changed

+56
-9
lines changed

sctp.c

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,13 @@ void janus_sctp_handle_remote_error_event(struct sctp_remote_error *sre);
119119
void janus_sctp_handle_send_failed_event(struct sctp_send_failed_event *ssfe);
120120
void janus_sctp_handle_notification(janus_sctp_association *sctp, union sctp_notification *notif, size_t n);
121121

122+
/* We need to keep a map of associations with random IDs, as usrsctp will
123+
* use the pointer to our structures in the actual messages instead */
124+
static janus_mutex sctp_mutex;
125+
static GHashTable *sctp_ids = NULL;
126+
static void janus_sctp_association_unref(janus_sctp_association *sctp);
127+
128+
/* SCTP management code */
122129
static gboolean sctp_running;
123130
int janus_sctp_init(void) {
124131
/* Initialize the SCTP stack */
@@ -131,12 +138,25 @@ int janus_sctp_init(void) {
131138
JANUS_LOG(LOG_ERR, "Error creating folder %s, expect problems...\n", debug_folder);
132139
}
133140
#endif
141+
142+
/* Create a map of local IDs too, to map them to our SCTP associations */
143+
janus_mutex_init(&sctp_mutex);
144+
sctp_ids = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)janus_sctp_association_unref);
145+
134146
return 0;
135147
}
136148

137149
void janus_sctp_deinit(void) {
138150
usrsctp_finish();
139151
sctp_running = FALSE;
152+
janus_mutex_lock(&sctp_mutex);
153+
g_hash_table_unref(sctp_ids);
154+
janus_mutex_unlock(&sctp_mutex);
155+
}
156+
157+
static void janus_sctp_association_unref(janus_sctp_association *sctp) {
158+
if(sctp)
159+
janus_refcount_decrease(&sctp->ref);
140160
}
141161

142162
static void janus_sctp_association_free(const janus_refcount *sctp_ref) {
@@ -205,9 +225,25 @@ janus_sctp_association *janus_sctp_association_create(janus_dtls_srtp *dtls, jan
205225
}
206226
sctp->stream_buffer_counter = 0;
207227

208-
usrsctp_register_address((void *)sctp);
228+
/* Create a unique ID to map locally: this is what we'll pass to
229+
* usrsctp_socket, which means that's what we'll get in callbacks
230+
* too: we can then use the map to retrieve the actual struct */
231+
janus_mutex_lock(&sctp_mutex);
232+
while(sctp->map_id == 0) {
233+
sctp->map_id = janus_random_uint32();
234+
if(g_hash_table_lookup(sctp_ids, GUINT_TO_POINTER(sctp->map_id)) != NULL) {
235+
/* ID already taken, try another one */
236+
sctp->map_id = 0;
237+
}
238+
}
239+
janus_refcount_increase(&sctp->ref);
240+
g_hash_table_insert(sctp_ids, GUINT_TO_POINTER(sctp->map_id), sctp);
241+
janus_mutex_unlock(&sctp_mutex);
242+
243+
usrsctp_register_address(GUINT_TO_POINTER(sctp->map_id));
209244
usrsctp_sysctl_set_sctp_ecn_enable(0);
210-
if((sock = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, janus_sctp_incoming_data, NULL, 0, (void *)sctp)) == NULL) {
245+
if((sock = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, janus_sctp_incoming_data, NULL, 0,
246+
GUINT_TO_POINTER(sctp->map_id))) == NULL) {
211247
JANUS_LOG(LOG_ERR, "[%"SCNu64"] Error creating usrsctp socket... (%d)\n", sctp->handle_id, errno);
212248
janus_sctp_association_destroy(sctp);
213249
return NULL;
@@ -274,7 +310,7 @@ janus_sctp_association *janus_sctp_association_create(janus_dtls_srtp *dtls, jan
274310
memset(&sconn, 0, sizeof(struct sockaddr_conn));
275311
sconn.sconn_family = AF_CONN;
276312
sconn.sconn_port = htons(sctp->local_port);
277-
sconn.sconn_addr = (void *)sctp;
313+
sconn.sconn_addr = GUINT_TO_POINTER(sctp->map_id);
278314
if(usrsctp_bind(sock, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) {
279315
JANUS_LOG(LOG_ERR, "[%"SCNu64"] Error binding client on port %"SCNu16" (%d)\n", sctp->handle_id, sctp->local_port, errno);
280316
janus_sctp_association_destroy(sctp);
@@ -293,7 +329,7 @@ janus_sctp_association *janus_sctp_association_create(janus_dtls_srtp *dtls, jan
293329
memset(&rconn, 0, sizeof(struct sockaddr_conn));
294330
rconn.sconn_family = AF_CONN;
295331
rconn.sconn_port = htons(sctp->remote_port);
296-
rconn.sconn_addr = (void *)sctp;
332+
rconn.sconn_addr = GUINT_TO_POINTER(sctp->map_id);
297333
#ifdef HAVE_SCONN_LEN
298334
rconn.sconn_len = sizeof(struct sockaddr_conn);
299335
#endif
@@ -311,8 +347,13 @@ void janus_sctp_association_destroy(janus_sctp_association *sctp) {
311347
if(sctp == NULL || !g_atomic_int_compare_and_exchange(&sctp->destroyed, 0, 1))
312348
return;
313349

314-
usrsctp_deregister_address(sctp);
315-
if (sctp->sock != NULL) {
350+
if(sctp->map_id != 0) {
351+
usrsctp_deregister_address(GUINT_TO_POINTER(sctp->map_id));
352+
janus_mutex_lock(&sctp_mutex);
353+
g_hash_table_remove(sctp_ids, GUINT_TO_POINTER(sctp->map_id));
354+
janus_mutex_unlock(&sctp_mutex);
355+
}
356+
if(sctp->sock != NULL) {
316357
usrsctp_shutdown(sctp->sock, SHUT_RDWR);
317358
usrsctp_close(sctp->sock);
318359
}
@@ -334,11 +375,13 @@ void janus_sctp_data_from_dtls(janus_sctp_association *sctp, char *buf, int len)
334375
}
335376
}
336377
#endif
337-
usrsctp_conninput((void *)sctp, buf, len, 0);
378+
usrsctp_conninput(GUINT_TO_POINTER(sctp->map_id), buf, len, 0);
338379
}
339380

340381
int janus_sctp_data_to_dtls(void *instance, void *buffer, size_t length, uint8_t tos, uint8_t set_df) {
341-
janus_sctp_association *sctp = (janus_sctp_association *)instance;
382+
janus_mutex_lock(&sctp_mutex);
383+
janus_sctp_association *sctp = (janus_sctp_association *)g_hash_table_lookup(sctp_ids, instance);
384+
janus_mutex_unlock(&sctp_mutex);
342385
if(sctp == NULL || sctp->handle == NULL)
343386
return -1;
344387
JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Data from SCTP to DTLS stack: %zu bytes\n", sctp->handle_id, length);
@@ -358,7 +401,9 @@ int janus_sctp_data_to_dtls(void *instance, void *buffer, size_t length, uint8_t
358401
}
359402

360403
static int janus_sctp_incoming_data(struct socket *sock, union sctp_sockstore addr, void *data, size_t datalen, struct sctp_rcvinfo rcv, int flags, void *ulp_info) {
361-
janus_sctp_association *sctp = (janus_sctp_association *)ulp_info;
404+
janus_mutex_lock(&sctp_mutex);
405+
janus_sctp_association *sctp = (janus_sctp_association *)g_hash_table_lookup(sctp_ids, ulp_info);
406+
janus_mutex_unlock(&sctp_mutex);
362407
if(sctp == NULL || sctp->dtls == NULL) {
363408
free(data);
364409
return 0;

sctp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ typedef struct janus_sctp_channel {
9999
} janus_sctp_channel;
100100

101101
typedef struct janus_sctp_association {
102+
/*! \brief Unique (local) ID of this association (needed for an internal map) */
103+
uint32_t map_id;
102104
/*! \brief Pointer to the DTLS instance related to this SCTP association */
103105
struct janus_dtls_srtp *dtls;
104106
/*! \brief Pointer to the ICE handle related to this SCTP association */

0 commit comments

Comments
 (0)