Skip to content

Commit f70ca32

Browse files
authored
Merge pull request #17 from membraneframework/nif
Add NIF wrapper alongside existing C node wrapper
2 parents 49989bf + 4ef485d commit f70ca32

File tree

14 files changed

+411
-216
lines changed

14 files changed

+411
-216
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,21 @@ end
2323
## Usage
2424

2525
Basically this library works similarly to [libnice].
26+
27+
`ExLibnice` can work both as CNode and as NIF.
28+
By default `CNode` implementation is used however, user can change it by passing proper option while starting `ExLibnice` (see below) or by `config.exs`:
29+
```elixir
30+
config :ex_libnice, impl: :NIF
31+
```
32+
2633
Example flow can look in the following way (this is not complete i.e. runnable example).
2734

2835
Listed functions must be invoked on both peers.
2936
```elixir
3037
# Init ExLibnice
3138
{:ok, pid} =
3239
ExLibnice.start_link(
40+
impl: NIF,
3341
parent: self(),
3442
stun_servers: [
3543
%{server_addr: {64, 233, 161, 127}, server_port: 19_302},

bundlex.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ defmodule ExLibnice.BundlexProject do
1414
deps: [unifex: :unifex],
1515
pkg_configs: ["nice"],
1616
libs: ["pthread"],
17-
interface: :cnode,
17+
interface: [:nif, :cnode],
1818
preprocessor: Unifex
1919
]
2020
]

c_src/ex_libnice/native.c

Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,13 @@ UNIFEX_TERM init(UnifexEnv *env, char **stun_servers, unsigned int stun_servers_
3333
Refer to: https://gitlab.freedesktop.org/libnice/libnice/-/issues/120
3434
*/
3535
g_object_set (G_OBJECT (state->agent), "ice-trickle", TRUE, NULL);
36-
state->env = env;
36+
state->env = unifex_alloc_env(env);
37+
if (!unifex_self(env, &state->reply_to)) {
38+
return unifex_raise(env, "failed to create native state");
39+
};
3740
state->min_port = min_port;
3841
state->max_port = max_port;
42+
3943
NiceAgent *agent = state->agent;
4044

4145
int parse_res = parse_args(agent, stun_servers, stun_servers_length, controlling_mode);
@@ -69,13 +73,14 @@ UNIFEX_TERM init(UnifexEnv *env, char **stun_servers, unsigned int stun_servers_
6973
return unifex_raise(env, "failed to create main loop thread");
7074
}
7175

72-
return init_result_ok(env, state);
76+
UNIFEX_TERM ret = init_result_ok(env, state);
77+
unifex_release_state(env, state);
78+
return ret;
7379
}
7480

7581
static void *main_loop_thread_func(void *user_data) {
7682
GMainLoop *loop = (GMainLoop *)user_data;
7783
g_main_loop_run(loop);
78-
g_main_loop_unref(loop);
7984
return NULL;
8085
}
8186

@@ -84,7 +89,7 @@ static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id,
8489
UNIFEX_UNUSED(agent);
8590
UNIFEX_UNUSED(stream_id);
8691
State *state = (State *)user_data;
87-
send_candidate_gathering_done(state->env, *state->env->reply_to, 0, stream_id);
92+
send_candidate_gathering_done(state->env, state->reply_to, 0, stream_id);
8893
}
8994

9095
static void cb_component_state_changed(NiceAgent *agent, guint stream_id,
@@ -93,9 +98,9 @@ static void cb_component_state_changed(NiceAgent *agent, guint stream_id,
9398
UNIFEX_UNUSED(agent);
9499
State *state = (State *)user_data;
95100
if(component_state == NICE_COMPONENT_STATE_FAILED) {
96-
send_component_state_failed(state->env, *state->env->reply_to, 0, stream_id, component_id);
101+
send_component_state_failed(state->env, state->reply_to, 0, stream_id, component_id);
97102
} else if(component_state == NICE_COMPONENT_STATE_READY) {
98-
send_component_state_ready(state->env, *state->env->reply_to, 0, stream_id, component_id);
103+
send_component_state_ready(state->env, state->reply_to, 0, stream_id, component_id);
99104
}
100105
}
101106

@@ -104,7 +109,7 @@ static void cb_new_candidate_full(NiceAgent *agent, NiceCandidate *candidate,
104109
State *state = (State *)user_data;
105110
gchar *candidate_sdp_str =
106111
nice_agent_generate_local_candidate_sdp(agent, candidate);
107-
send_new_candidate_full(state->env, *state->env->reply_to, 0, candidate_sdp_str);
112+
send_new_candidate_full(state->env, state->reply_to, 0, candidate_sdp_str);
108113
g_free(candidate_sdp_str);
109114
}
110115

@@ -119,7 +124,7 @@ static void cb_new_remote_candidate_full(NiceAgent *agent, NiceCandidate *candid
119124
*/
120125
gchar *candidate_sdp_str =
121126
nice_agent_generate_local_candidate_sdp(agent, candidate);
122-
send_new_remote_candidate_full(state->env, *state->env->reply_to, 0, candidate_sdp_str);
127+
send_new_remote_candidate_full(state->env, state->reply_to, 0, candidate_sdp_str);
123128
g_free(candidate_sdp_str);
124129
}
125130

@@ -128,7 +133,7 @@ static void cb_new_selected_pair(NiceAgent *agent, guint stream_id,
128133
gchar *rfoundation, gpointer user_data) {
129134
UNIFEX_UNUSED(agent);
130135
State *state = (State *)user_data;
131-
send_new_selected_pair(state->env, *state->env->reply_to, 0, stream_id, component_id,
136+
send_new_selected_pair(state->env, state->reply_to, 0, stream_id, component_id,
132137
lfoundation, rfoundation);
133138
}
134139

@@ -138,27 +143,27 @@ static void cb_recv(NiceAgent *_agent, guint stream_id, guint component_id,
138143
State *state = (State *)user_data;
139144
UnifexPayload *payload = unifex_payload_alloc(state->env, UNIFEX_PAYLOAD_BINARY, len);
140145
memcpy(payload->data, buf, len);
141-
send_ice_payload(state->env, *state->env->reply_to, 0, stream_id, component_id, payload);
146+
send_ice_payload(state->env, state->reply_to, 0, stream_id, component_id, payload);
142147
unifex_payload_release(payload);
143148
}
144149

145150
UNIFEX_TERM add_stream(UnifexEnv *env, UnifexState *state,
146151
unsigned int n_components, char *name) {
147152
guint stream_id = nice_agent_add_stream(state->agent, n_components);
148153
if (stream_id == 0) {
149-
return add_stream_result_error_failed_to_add_stream(env);
154+
return add_stream_result_error_failed_to_add_stream(env, state);
150155
}
151156

152157
if(!attach_recv(state, stream_id, n_components)) {
153-
return add_stream_result_error_failed_to_attach_recv(env);
158+
return add_stream_result_error_failed_to_attach_recv(env, state);
154159
}
155160

156161
// set name if one was specified
157162
if (strcmp(name, "") == 0) {
158-
return add_stream_result_ok(env, stream_id);
163+
return add_stream_result_ok(env, stream_id, state);
159164
} else {
160165
if (!nice_agent_set_stream_name(state->agent, stream_id, name)) {
161-
return add_stream_result_error_invalid_stream_or_duplicate_name(env);
166+
return add_stream_result_error_invalid_stream_or_duplicate_name(env, state);
162167
}
163168
}
164169

@@ -167,7 +172,7 @@ UNIFEX_TERM add_stream(UnifexEnv *env, UnifexState *state,
167172
nice_agent_set_port_range(state->agent, stream_id, i, state->min_port, state->max_port);
168173
}
169174

170-
return add_stream_result_ok(env, stream_id);
175+
return add_stream_result_ok(env, stream_id, state);
171176
}
172177

173178
static gboolean attach_recv(UnifexState *state, guint stream_id, guint n_components) {
@@ -182,7 +187,7 @@ static gboolean attach_recv(UnifexState *state, guint stream_id, guint n_compone
182187

183188
UNIFEX_TERM remove_stream(UnifexEnv *env, UnifexState *state, unsigned int stream_id) {
184189
nice_agent_remove_stream(state->agent, stream_id);
185-
return remove_stream_result_ok(env);
190+
return remove_stream_result_ok(env, state);
186191
}
187192

188193
UNIFEX_TERM set_relay_info(UnifexEnv *env, UnifexState *state, unsigned int stream_id,
@@ -196,57 +201,57 @@ UNIFEX_TERM set_relay_info(UnifexEnv *env, UnifexState *state, unsigned int stre
196201
} else if(strcmp(relay_type, "tls") == 0) {
197202
nice_relay_type = NICE_RELAY_TYPE_TURN_TLS;
198203
} else {
199-
return set_relay_info_result_error_bad_relay_type(env);
204+
return set_relay_info_result_error_bad_relay_type(env, state);
200205
}
201206

202207
if(!nice_agent_set_relay_info(state->agent, stream_id, component_id, server_ip, server_port,
203208
username, password, nice_relay_type)) {
204-
return set_relay_info_result_error_failed_to_set_turn(env);
209+
return set_relay_info_result_error_failed_to_set_turn(env, state);
205210
}
206-
return set_relay_info_result_ok(env);
211+
return set_relay_info_result_ok(env, state);
207212
}
208213

209214
UNIFEX_TERM forget_relays(UnifexEnv *env, UnifexState *state, unsigned int stream_id,
210215
unsigned int component_id) {
211216
if(!nice_agent_forget_relays(state->agent, stream_id, component_id)) {
212-
return forget_relays_result_error_component_not_found(env);
217+
return forget_relays_result_error_component_not_found(env, state);
213218
}
214-
return forget_relays_result_ok(env);
219+
return forget_relays_result_ok(env, state);
215220
}
216221

217222
UNIFEX_TERM generate_local_sdp(UnifexEnv *env, UnifexState *state) {
218223
gchar *local_sdp = nice_agent_generate_local_sdp(state->agent);
219-
return generate_local_sdp_result_ok(env, local_sdp);
224+
return generate_local_sdp_result_ok(env, local_sdp, state);
220225
}
221226

222227
UNIFEX_TERM parse_remote_sdp(UnifexEnv *env, UnifexState *state, char *remote_sdp) {
223228
int cand_added_num = nice_agent_parse_remote_sdp(state->agent, remote_sdp);
224229
if (cand_added_num < 0) {
225-
return parse_remote_sdp_result_error_failed_to_parse_sdp(env);
230+
return parse_remote_sdp_result_error_failed_to_parse_sdp(env, state);
226231
}
227-
return parse_remote_sdp_result_ok(env, cand_added_num);
232+
return parse_remote_sdp_result_ok(env, cand_added_num, state);
228233
}
229234

230235
UNIFEX_TERM gather_candidates(UnifexEnv *env, State *state, unsigned int stream_id) {
231236
g_networking_init();
232237
if(!nice_agent_gather_candidates(state->agent, stream_id)) {
233-
return gather_candidates_result_error_invalid_stream_or_allocation(env);
238+
return gather_candidates_result_error_invalid_stream_or_allocation(env, state);
234239
}
235-
return gather_candidates_result_ok(env);
240+
return gather_candidates_result_ok(env, state);
236241
}
237242

238243
UNIFEX_TERM peer_candidate_gathering_done(UnifexEnv *env, State *state, unsigned int stream_id) {
239244
if(!nice_agent_peer_candidate_gathering_done(state->agent, stream_id)) {
240-
return peer_candidate_gathering_done_result_error_stream_not_found(env);
245+
return peer_candidate_gathering_done_result_error_stream_not_found(env, state);
241246
}
242-
return peer_candidate_gathering_done_result_ok(env);
247+
return peer_candidate_gathering_done_result_ok(env, state);
243248
}
244249

245250
UNIFEX_TERM get_local_credentials(UnifexEnv *env, State *state, unsigned int stream_id) {
246251
gchar *ufrag = NULL;
247252
gchar *pwd = NULL;
248253
if (!nice_agent_get_local_credentials(state->agent, stream_id, &ufrag, &pwd)) {
249-
return get_local_credentials_result_error_failed_to_get_credentials(env);
254+
return get_local_credentials_result_error_failed_to_get_credentials(env, state);
250255
}
251256
const size_t lenufrag = strlen(ufrag);
252257
const size_t lenpwd = strlen(pwd);
@@ -256,7 +261,7 @@ UNIFEX_TERM get_local_credentials(UnifexEnv *env, State *state, unsigned int str
256261
memcpy(credentials + lenufrag + 1, pwd, lenpwd + 1);
257262
g_free(ufrag);
258263
g_free(pwd);
259-
UNIFEX_TERM ret = get_local_credentials_result_ok(env, credentials);
264+
UNIFEX_TERM ret = get_local_credentials_result_ok(env, credentials, state);
260265
unifex_free(credentials);
261266
return ret;
262267
}
@@ -267,51 +272,50 @@ UNIFEX_TERM set_remote_credentials(UnifexEnv *env, State *state,
267272
char *pwd = NULL;
268273
parse_credentials(credentials, &ufrag, &pwd);
269274
if (!nice_agent_set_remote_credentials(state->agent, stream_id, ufrag, pwd)) {
270-
return set_remote_credentials_result_error_failed_to_set_credentials(env);
275+
return set_remote_credentials_result_error_failed_to_set_credentials(env, state);
271276
}
272-
return set_remote_credentials_result_ok(env);
277+
return set_remote_credentials_result_ok(env, state);
273278
}
274279

275280
UNIFEX_TERM set_remote_candidate(UnifexEnv *env, State *state,
276281
char *candidate, unsigned int stream_id, unsigned int component_id) {
277282
NiceCandidate *cand = nice_agent_parse_remote_candidate_sdp(state->agent, stream_id, candidate);
278283
if (cand == NULL) {
279-
return set_remote_candidate_result_error_failed_to_parse_sdp_string(env);
284+
return set_remote_candidate_result_error_failed_to_parse_sdp_string(env, state);
280285
}
281286
GSList *cands = NULL;
282287
cands = g_slist_append(cands, cand);
283288
if (nice_agent_set_remote_candidates(state->agent, stream_id, component_id, cands) < 0) {
284-
return set_remote_candidate_result_error_failed_to_set(env);
289+
return set_remote_candidate_result_error_failed_to_set(env, state);
285290
}
286-
return set_remote_candidate_result_ok(env);
291+
return set_remote_candidate_result_ok(env, state);
287292
}
288293

289294
UNIFEX_TERM restart(UnifexEnv *env, State *state) {
290295
if(nice_agent_restart(state->agent)) {
291-
return restart_result_ok(env);
296+
return restart_result_ok(env, state);
292297
}
293-
return restart_result_error_failed_to_restart(env);
298+
return restart_result_error_failed_to_restart(env, state);
294299
}
295300

296301
UNIFEX_TERM restart_stream(UnifexEnv *env, State *state, unsigned int stream_id) {
297302
if(nice_agent_restart_stream(state->agent, stream_id)) {
298-
return restart_stream_result_ok(env);
303+
return restart_stream_result_ok(env, state);
299304
}
300-
return restart_stream_result_error_failed_to_restart(env);
305+
return restart_stream_result_error_failed_to_restart(env, state);
301306
}
302307

303308
UNIFEX_TERM send_payload(UnifexEnv *env, State *state, unsigned int stream_id,
304309
unsigned int component_id, UnifexPayload *payload) {
305310
if(nice_agent_send(state->agent, stream_id, component_id, payload->size, (char *)payload->data) < 0) {
306-
return send_payload_result_error_failed_to_send(env);
311+
return send_payload_result_error_failed_to_send(env, state);
307312
}
308-
return send_payload_result_ok(env);
313+
return send_payload_result_ok(env, state);
309314
}
310315

311316
void handle_destroy_state(UnifexEnv *env, State *state) {
312317
UNIFEX_UNUSED(env);
313318
g_main_loop_quit(state->gloop);
314-
pthread_kill(state->gloop_tid, SIGKILL);
315319
if (state->gloop) {
316320
g_main_loop_unref(state->gloop);
317321
state->gloop = NULL;
@@ -320,4 +324,7 @@ void handle_destroy_state(UnifexEnv *env, State *state) {
320324
g_object_unref(state->agent);
321325
state->agent = NULL;
322326
}
327+
if (state->env) {
328+
unifex_free_env(state->env);
329+
}
323330
}

c_src/ex_libnice/native.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ struct State {
1313
pthread_t gloop_tid;
1414
unsigned int min_port;
1515
unsigned int max_port;
16+
UnifexPid reply_to;
1617
};
1718

1819
#include "_generated/native.h"

0 commit comments

Comments
 (0)