15
15
16
16
#include <assert.h>
17
17
#include <string.h>
18
+ #include <stdio.h>
18
19
19
20
#define INITIAL_REGISTRY_SIZE 16
20
21
@@ -33,30 +34,114 @@ typedef struct conn_mode_entry {
33
34
int (* get_addrs_func )(juice_agent_t * agent , addr_record_t * records , size_t size );
34
35
35
36
mutex_t mutex ;
36
- conn_registry_t * registry ;
37
+ conn_registry_t * * registries ;
38
+ int registries_size ;
39
+ int registries_count ;
37
40
} conn_mode_entry_t ;
38
41
39
42
#define MODE_ENTRIES_SIZE 3
40
43
41
44
static conn_mode_entry_t mode_entries [MODE_ENTRIES_SIZE ] = {
42
45
{conn_poll_registry_init , conn_poll_registry_cleanup , conn_poll_init , conn_poll_cleanup ,
43
46
conn_poll_lock , conn_poll_unlock , conn_poll_interrupt , conn_poll_send , conn_poll_get_addrs ,
44
- MUTEX_INITIALIZER , NULL },
47
+ MUTEX_INITIALIZER , NULL , 0 , 0 },
45
48
{conn_mux_registry_init , conn_mux_registry_cleanup , conn_mux_init , conn_mux_cleanup ,
46
49
conn_mux_lock , conn_mux_unlock , conn_mux_interrupt , conn_mux_send , conn_mux_get_addrs ,
47
- MUTEX_INITIALIZER , NULL },
50
+ MUTEX_INITIALIZER , NULL , 0 , 0 },
48
51
{NULL , NULL , conn_thread_init , conn_thread_cleanup , conn_thread_lock , conn_thread_unlock ,
49
- conn_thread_interrupt , conn_thread_send , conn_thread_get_addrs , MUTEX_INITIALIZER , NULL }};
52
+ conn_thread_interrupt , conn_thread_send , conn_thread_get_addrs , MUTEX_INITIALIZER , NULL , 0 , 0 }};
50
53
51
54
static conn_mode_entry_t * get_mode_entry (juice_agent_t * agent ) {
52
55
juice_concurrency_mode_t mode = agent -> config .concurrency_mode ;
53
56
assert (mode >= 0 && mode < MODE_ENTRIES_SIZE );
54
57
return mode_entries + (int )mode ;
55
58
}
56
59
60
+ // accepts a host name and a port and returns a token that can be used to
61
+ // distinguish one mux request handler from another. E.g.
62
+ //
63
+ // '127.0.0.1', 8080 -> '127.0.0.1:8080'
64
+ // '::', 8080 -> '[::]:8080'
65
+ // NULL, 8080 -> 'any:8080'
66
+ // '', 8080 -> 'any:8080'
67
+ static char * get_address (const char * bind_address , uint16_t port ) {
68
+ if (!bind_address || strcmp (bind_address , "" ) == 0 ) {
69
+ bind_address = "any" ;
70
+ }
71
+
72
+ // search for '.' in bind_address, treat as IPv4 if found
73
+ char * result = strchr (bind_address , '.' );
74
+ int index = (int )(result - bind_address );
75
+ int maxAddrSize = 48 ; // ip6 is 39 chars + [ + ] + : + 5 for the port + \0
76
+ char * address = (char * ) calloc (1 , maxAddrSize * sizeof (char ));
77
+
78
+ // ip6
79
+ char * format = "[%s]:%d" ;
80
+
81
+ if (index > -1 ) {
82
+ // ip4
83
+ format = "%s:%d" ;
84
+ }
85
+
86
+ sprintf (address , format , bind_address , port );
87
+
88
+ return address ;
89
+ }
90
+
91
+ static conn_registry_t * get_port_registry (conn_mode_entry_t * entry , const char * bind_address , uint16_t port ) {
92
+ char * address = get_address (bind_address , port );
93
+
94
+ for (int i = 0 ; i < entry -> registries_size ; i ++ ) {
95
+ if (!entry -> registries [i ]) {
96
+ continue ;
97
+ }
98
+
99
+ if (strcmp (entry -> registries [i ]-> address , address ) == 0 ) {
100
+ return entry -> registries [i ];
101
+ }
102
+ }
103
+
104
+ return NULL ;
105
+ }
106
+
107
+ static int add_registry (conn_mode_entry_t * entry , conn_registry_t * registry ) {
108
+ int i = 0 ;
109
+ while (i < entry -> registries_size && entry -> registries [i ])
110
+ ++ i ;
111
+
112
+ if (i == entry -> registries_size ) {
113
+ int new_size = entry -> registries_size * 2 ;
114
+
115
+ if (new_size == 0 ) {
116
+ new_size = 1 ;
117
+ }
118
+
119
+ JLOG_DEBUG ("Reallocating registries array, new_size=%d" , new_size );
120
+ assert (new_size > 0 );
121
+
122
+ conn_registry_t * * new_registries =
123
+ realloc (entry -> registries , new_size * sizeof (conn_registry_t * ));
124
+ if (!new_registries ) {
125
+ JLOG_FATAL ("Memory reallocation failed for registries array" );
126
+ return -1 ;
127
+ }
128
+
129
+ entry -> registries = new_registries ;
130
+ entry -> registries_size = new_size ;
131
+ memset (entry -> registries + i , 0 , (new_size - i ) * sizeof (conn_registry_t * ));
132
+ }
133
+
134
+ entry -> registries [i ] = registry ;
135
+ registry -> registry_index = i ;
136
+ ++ entry -> registries_count ;
137
+
138
+ return 0 ;
139
+ }
140
+
57
141
static int acquire_registry (conn_mode_entry_t * entry , udp_socket_config_t * config ) {
58
142
// entry must be locked
59
- conn_registry_t * registry = entry -> registry ;
143
+ conn_registry_t * registry = get_port_registry (entry , config -> bind_address , config -> port_begin );
144
+
60
145
if (!registry ) {
61
146
if (!entry -> registry_init_func )
62
147
return 0 ;
@@ -83,16 +168,25 @@ static int acquire_registry(conn_mode_entry_t *entry, udp_socket_config_t *confi
83
168
mutex_init (& registry -> mutex , MUTEX_RECURSIVE );
84
169
mutex_lock (& registry -> mutex );
85
170
171
+ registry -> address = get_address (config -> bind_address , config -> port_begin );
172
+
86
173
if (entry -> registry_init_func (registry , config )) {
87
174
JLOG_FATAL ("Registry initialization failed" );
88
175
mutex_unlock (& registry -> mutex );
89
176
free (registry -> agents );
177
+ free (registry -> address );
90
178
free (registry );
91
179
return -1 ;
92
180
}
93
181
94
- entry -> registry = registry ;
95
-
182
+ if (add_registry (entry , registry )) {
183
+ JLOG_FATAL ("Adding registry to entry failed" );
184
+ mutex_unlock (& registry -> mutex );
185
+ free (registry -> agents );
186
+ free (registry -> address );
187
+ free (registry );
188
+ return -1 ;
189
+ }
96
190
} else {
97
191
mutex_lock (& registry -> mutex );
98
192
}
@@ -101,9 +195,8 @@ static int acquire_registry(conn_mode_entry_t *entry, udp_socket_config_t *confi
101
195
return 0 ;
102
196
}
103
197
104
- static void release_registry (conn_mode_entry_t * entry ) {
198
+ static void release_registry (conn_mode_entry_t * entry , conn_registry_t * registry ) {
105
199
// entry must be locked
106
- conn_registry_t * registry = entry -> registry ;
107
200
if (!registry )
108
201
return ;
109
202
@@ -116,9 +209,19 @@ static void release_registry(conn_mode_entry_t *entry) {
116
209
if (entry -> registry_cleanup_func )
117
210
entry -> registry_cleanup_func (registry );
118
211
212
+ if (registry -> registry_index > -1 ) {
213
+ int i = registry -> registry_index ;
214
+ assert (entry -> registries [i ] == registry );
215
+ entry -> registries [i ] = NULL ;
216
+ registry -> registry_index = -1 ;
217
+ }
218
+
219
+ assert (entry -> registries_count > 0 );
220
+ -- entry -> registries_count ;
221
+
119
222
free (registry -> agents );
223
+ free (registry -> address );
120
224
free (registry );
121
- entry -> registry = NULL ;
122
225
return ;
123
226
}
124
227
@@ -136,7 +239,8 @@ int conn_create(juice_agent_t *agent, udp_socket_config_t *config) {
136
239
return -1 ;
137
240
}
138
241
139
- conn_registry_t * registry = entry -> registry ;
242
+ conn_registry_t * registry = get_port_registry (entry , config -> bind_address , config -> port_begin );
243
+ agent -> registry = registry ;
140
244
141
245
JLOG_DEBUG ("Creating connection" );
142
246
if (registry ) {
@@ -164,7 +268,7 @@ int conn_create(juice_agent_t *agent, udp_socket_config_t *config) {
164
268
}
165
269
166
270
if (get_mode_entry (agent )-> init_func (agent , registry , config )) {
167
- release_registry (entry ); // unlocks the registry
271
+ release_registry (entry , registry ); // unlocks the registry
168
272
mutex_unlock (& entry -> mutex );
169
273
return -1 ;
170
274
}
@@ -194,7 +298,7 @@ void conn_destroy(juice_agent_t *agent) {
194
298
mutex_lock (& entry -> mutex );
195
299
196
300
JLOG_DEBUG ("Destroying connection" );
197
- conn_registry_t * registry = entry -> registry ;
301
+ conn_registry_t * registry = agent -> registry ;
198
302
if (registry ) {
199
303
mutex_lock (& registry -> mutex );
200
304
@@ -205,12 +309,13 @@ void conn_destroy(juice_agent_t *agent) {
205
309
assert (registry -> agents [i ] == agent );
206
310
registry -> agents [i ] = NULL ;
207
311
agent -> conn_index = -1 ;
312
+ agent -> registry = NULL ;
208
313
}
209
314
210
315
assert (registry -> agents_count > 0 );
211
316
-- registry -> agents_count ;
212
317
213
- release_registry (entry ); // unlocks the registry
318
+ release_registry (entry , registry ); // unlocks the registry
214
319
215
320
} else {
216
321
entry -> cleanup_func (agent );
@@ -264,7 +369,7 @@ static int juice_mux_stop_listen(const char *bind_address, int local_port) {
264
369
265
370
mutex_lock (& entry -> mutex );
266
371
267
- conn_registry_t * registry = entry -> registry ;
372
+ conn_registry_t * registry = get_port_registry ( entry , bind_address , local_port ) ;
268
373
if (!registry ) {
269
374
mutex_unlock (& entry -> mutex );
270
375
return -1 ;
@@ -276,7 +381,7 @@ static int juice_mux_stop_listen(const char *bind_address, int local_port) {
276
381
registry -> mux_incoming_user_ptr = NULL ;
277
382
conn_mux_interrupt_registry (registry );
278
383
279
- release_registry (entry );
384
+ release_registry (entry , registry );
280
385
281
386
mutex_unlock (& entry -> mutex );
282
387
@@ -296,9 +401,9 @@ int juice_mux_listen(const char *bind_address, int local_port, juice_cb_mux_inco
296
401
297
402
mutex_lock (& entry -> mutex );
298
403
299
- if (entry -> registry ) {
404
+ if (get_port_registry ( entry , bind_address , local_port ) ) {
300
405
mutex_unlock (& entry -> mutex );
301
- JLOG_DEBUG ("juice_mux_listen needs to be called before establishing any mux connection ." );
406
+ JLOG_DEBUG ("juice_mux_listen there is already a listener for this host/port combination ." );
302
407
return -1 ;
303
408
}
304
409
@@ -307,7 +412,7 @@ int juice_mux_listen(const char *bind_address, int local_port, juice_cb_mux_inco
307
412
return -1 ;
308
413
}
309
414
310
- conn_registry_t * registry = entry -> registry ;
415
+ conn_registry_t * registry = get_port_registry ( entry , bind_address , local_port ) ;
311
416
if (!registry ) {
312
417
mutex_unlock (& entry -> mutex );
313
418
return -1 ;
0 commit comments