Statistics
| Branch: | Revision:

janus-gateway / plugins / janus_sip.c @ 4239218c

History | View | Annotate | Download (79.5 KB)

1
/*! \file   janus_sip.c
2
 * \author Lorenzo Miniero <lorenzo@meetecho.com>
3
 * \copyright GNU General Public License v3
4
 * \brief  Janus SIP plugin
5
 * \details  This is a simple SIP plugin for Janus, allowing WebRTC peers
6
 * to register at a SIP server (e.g., Asterisk) and call SIP user agents
7
 * through the gateway. Specifically, when attaching to the plugin peers
8
 * are requested to provide their SIP server credentials, i.e., the address
9
 * of the SIP server and their username/secret. This results in the plugin
10
 * registering at the SIP server and acting as a SIP client on behalf of
11
 * the web peer. Most of the SIP states and lifetime are masked by the plugin,
12
 * and only the relevant events (e.g., INVITEs and BYEs) and functionality
13
 * (call, hangup) are made available to the web peer: peers can call
14
 * extensions at the SIP server or wait for incoming INVITEs, and during
15
 * a call they can send DTMF tones.
16
 * 
17
 * The concept behind this plugin is to allow different web pages associated
18
 * to the same peer, and hence the same SIP user, to attach to the plugin
19
 * at the same time and yet just do a SIP REGISTER once. The same should
20
 * apply for calls: while an incoming call would be notified to all the
21
 * web UIs associated to the peer, only one would be able to pick up and
22
 * answer, in pretty much the same way as SIP forking works but without the
23
 * need to fork in the same place. This specific functionality, though, has
24
 * not been implemented as of yet.
25
 * 
26
 * \todo Only Asterisk and Kamailio have been tested as a SIP server, and
27
 * specifically only with basic audio calls: this plugin needs some work
28
 * to make it more stable and reliable.
29
 * 
30
 * \section sipapi SIP Plugin API
31
 * 
32
 * All requests you can send in the SIP Plugin API are asynchronous,
33
 * which means all responses (successes and errors) will be delivered
34
 * as events with the same transaction. 
35
 * 
36
 * The supported requests are \c register , \c call , \c accept and
37
 * \c hangup . \c register can be used, as the name suggests, to register
38
 * a username at a SIP registrar to call and be called; \c call is used
39
 * to send an INVITE to a different SIP URI through the plugin, while
40
 * \c accept is used to accept the call in case one is invited instead
41
 * of inviting; finally, \c hangup can be used to terminate the
42
 * communication at any time, either to hangup (BYE) an ongoing call or
43
 * to cancel/decline (CANCEL/BYE) a call that hasn't started yet.
44
 * 
45
 * Actual API docs: TBD.
46
 * 
47
 * \ingroup plugins
48
 * \ref plugins
49
 */
50

    
51
#include "plugin.h"
52

    
53
#include <arpa/inet.h>
54
#include <net/if.h>
55

    
56
#include <jansson.h>
57

    
58
#include <sofia-sip/msg_header.h>
59
#include <sofia-sip/nua.h>
60
#include <sofia-sip/sdp.h>
61
#include <sofia-sip/sip_status.h>
62
#include <sofia-sip/url.h>
63
#include <sofia-sip/tport_tag.h>
64

    
65
#include "../debug.h"
66
#include "../apierror.h"
67
#include "../config.h"
68
#include "../mutex.h"
69
#include "../rtp.h"
70
#include "../rtcp.h"
71
#include "../utils.h"
72

    
73

    
74
/* Plugin information */
75
#define JANUS_SIP_VERSION                        5
76
#define JANUS_SIP_VERSION_STRING        "0.0.5"
77
#define JANUS_SIP_DESCRIPTION                "This is a simple SIP plugin for Janus, allowing WebRTC peers to register at a SIP server and call SIP user agents through the gateway."
78
#define JANUS_SIP_NAME                                "JANUS SIP plugin"
79
#define JANUS_SIP_AUTHOR                        "Meetecho s.r.l."
80
#define JANUS_SIP_PACKAGE                        "janus.plugin.sip"
81

    
82
/* Plugin methods */
83
janus_plugin *create(void);
84
int janus_sip_init(janus_callbacks *callback, const char *config_path);
85
void janus_sip_destroy(void);
86
int janus_sip_get_api_compatibility(void);
87
int janus_sip_get_version(void);
88
const char *janus_sip_get_version_string(void);
89
const char *janus_sip_get_description(void);
90
const char *janus_sip_get_name(void);
91
const char *janus_sip_get_author(void);
92
const char *janus_sip_get_package(void);
93
void janus_sip_create_session(janus_plugin_session *handle, int *error);
94
struct janus_plugin_result *janus_sip_handle_message(janus_plugin_session *handle, char *transaction, char *message, char *sdp_type, char *sdp);
95
void janus_sip_setup_media(janus_plugin_session *handle);
96
void janus_sip_incoming_rtp(janus_plugin_session *handle, int video, char *buf, int len);
97
void janus_sip_incoming_rtcp(janus_plugin_session *handle, int video, char *buf, int len);
98
void janus_sip_hangup_media(janus_plugin_session *handle);
99
void janus_sip_destroy_session(janus_plugin_session *handle, int *error);
100
char *janus_sip_query_session(janus_plugin_session *handle);
101

    
102
/* Plugin setup */
103
static janus_plugin janus_sip_plugin =
104
        JANUS_PLUGIN_INIT (
105
                .init = janus_sip_init,
106
                .destroy = janus_sip_destroy,
107

    
108
                .get_api_compatibility = janus_sip_get_api_compatibility,
109
                .get_version = janus_sip_get_version,
110
                .get_version_string = janus_sip_get_version_string,
111
                .get_description = janus_sip_get_description,
112
                .get_name = janus_sip_get_name,
113
                .get_author = janus_sip_get_author,
114
                .get_package = janus_sip_get_package,
115
                
116
                .create_session = janus_sip_create_session,
117
                .handle_message = janus_sip_handle_message,
118
                .setup_media = janus_sip_setup_media,
119
                .incoming_rtp = janus_sip_incoming_rtp,
120
                .incoming_rtcp = janus_sip_incoming_rtcp,
121
                .hangup_media = janus_sip_hangup_media,
122
                .destroy_session = janus_sip_destroy_session,
123
                .query_session = janus_sip_query_session,
124
        );
125

    
126
/* Plugin creator */
127
janus_plugin *create(void) {
128
        JANUS_LOG(LOG_VERB, "%s created!\n", JANUS_SIP_NAME);
129
        return &janus_sip_plugin;
130
}
131

    
132

    
133
/* Useful stuff */
134
static volatile gint initialized = 0, stopping = 0;
135
static janus_callbacks *gateway = NULL;
136

    
137
static char local_ip[INET6_ADDRSTRLEN];
138
static int keepalive_interval = 120;
139
static gboolean behind_nat = FALSE;
140
static char *user_agent;
141
#define JANUS_DEFAULT_REGISTER_TTL        3600
142
static int register_ttl = JANUS_DEFAULT_REGISTER_TTL;
143

    
144
static GThread *handler_thread;
145
static GThread *watchdog;
146
static void *janus_sip_handler(void *data);
147

    
148
typedef struct janus_sip_message {
149
        janus_plugin_session *handle;
150
        char *transaction;
151
        char *message;
152
        char *sdp_type;
153
        char *sdp;
154
} janus_sip_message;
155
static GAsyncQueue *messages = NULL;
156

    
157
void janus_sip_message_free(janus_sip_message *msg);
158
void janus_sip_message_free(janus_sip_message *msg) {
159
        if(!msg)
160
                return;
161

    
162
        msg->handle = NULL;
163

    
164
        g_free(msg->transaction);
165
        msg->transaction = NULL;
166
        g_free(msg->message);
167
        msg->message = NULL;
168
        g_free(msg->sdp_type);
169
        msg->sdp_type = NULL;
170
        g_free(msg->sdp);
171
        msg->sdp = NULL;
172

    
173
        g_free(msg);
174
}
175

    
176

    
177
typedef enum {
178
        janus_sip_registration_status_disabled = -2,
179
        janus_sip_registration_status_failed = -1,
180
        janus_sip_registration_status_unregistered = 0,
181
        janus_sip_registration_status_registering,
182
        janus_sip_registration_status_registered,
183
        janus_sip_registration_status_unregistering,
184
} janus_sip_registration_status;
185

    
186
static const char *janus_sip_registration_status_string(janus_sip_registration_status status) {
187
        switch(status) {
188
                case janus_sip_registration_status_disabled:
189
                        return "disabled";
190
                case janus_sip_registration_status_failed:
191
                        return "failed";
192
                case janus_sip_registration_status_unregistered:
193
                        return "unregistered";
194
                case janus_sip_registration_status_registering:
195
                        return "registering";
196
                case janus_sip_registration_status_registered:
197
                        return "registered";
198
                case janus_sip_registration_status_unregistering:
199
                        return "unregistering";
200
                default:
201
                        return "unknown";
202
        }
203
}
204

    
205

    
206
typedef enum {
207
        janus_sip_call_status_idle = 0,
208
        janus_sip_call_status_inviting,
209
        janus_sip_call_status_invited,
210
        janus_sip_call_status_incall,
211
        janus_sip_call_status_closing,
212
} janus_sip_call_status;
213

    
214
static const char *janus_sip_call_status_string(janus_sip_call_status status) {
215
        switch(status) {
216
                case janus_sip_call_status_idle:
217
                        return "idle";
218
                case janus_sip_call_status_inviting:
219
                        return "inviting";
220
                case janus_sip_call_status_invited:
221
                        return "invited";
222
                case janus_sip_call_status_incall:
223
                        return "incall";
224
                case janus_sip_call_status_closing:
225
                        return "closing";
226
                default:
227
                        return "unknown";
228
        }
229
}
230

    
231

    
232
/* Sofia stuff */
233
typedef struct ssip_s ssip_t;
234
typedef struct ssip_oper_s ssip_oper_t;
235

    
236
typedef enum {
237
        janus_sip_secret_type_plaintext = 1,
238
        janus_sip_secret_type_hashed = 2,
239
        janus_sip_secret_type_unknown
240
} janus_sip_secret_type;
241

    
242
typedef struct janus_sip_account {
243
        char *identity;
244
        char *username;
245
        char *secret;
246
        janus_sip_secret_type secret_type;
247
        int sip_port;
248
        char *proxy;
249
        janus_sip_registration_status registration_status;
250
} janus_sip_account;
251

    
252
typedef struct janus_sip_media {
253
        char *remote_ip;
254
        int ready:1;
255
        int has_audio:1;
256
        int audio_rtp_fd, audio_rtcp_fd;
257
        int local_audio_rtp_port, remote_audio_rtp_port;
258
        int local_audio_rtcp_port, remote_audio_rtcp_port;
259
        guint32 audio_ssrc, audio_ssrc_peer;
260
        int has_video:1;
261
        int video_rtp_fd, video_rtcp_fd;
262
        int local_video_rtp_port, remote_video_rtp_port;
263
        int local_video_rtcp_port, remote_video_rtcp_port;
264
        guint32 video_ssrc, video_ssrc_peer;
265
} janus_sip_media;
266

    
267
typedef struct janus_sip_session {
268
        janus_plugin_session *handle;
269
        ssip_t *stack;
270
        janus_sip_account account;
271
        janus_sip_call_status status;
272
        janus_sip_media media;
273
        char *transaction;
274
        char *callee;
275
        volatile gint hangingup;
276
        gint64 destroyed;        /* Time at which this session was marked as destroyed */
277
        janus_mutex mutex;
278
} janus_sip_session;
279
static GHashTable *sessions;
280
static GList *old_sessions;
281
static janus_mutex sessions_mutex;
282

    
283

    
284
#undef SU_ROOT_MAGIC_T
285
#define SU_ROOT_MAGIC_T        ssip_t
286
#undef NUA_MAGIC_T
287
#define NUA_MAGIC_T                ssip_t
288
#undef NUA_HMAGIC_T
289
#define NUA_HMAGIC_T        ssip_oper_t
290

    
291
struct ssip_s {
292
        su_home_t s_home[1];
293
        su_root_t *s_root;
294
        nua_t *s_nua;
295
        nua_handle_t *s_nh_r, *s_nh_i;
296
        janus_sip_session *session;
297
};
298

    
299

    
300
/* Sofia Event thread */
301
gpointer janus_sip_sofia_thread(gpointer user_data);
302
/* Sofia callbacks */
303
void janus_sip_sofia_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
304
/* SDP parsing */
305
void janus_sip_sdp_process(janus_sip_session *session, sdp_session_t *sdp);
306
/* Media */
307
static int janus_sip_allocate_local_ports(janus_sip_session *session);
308
static void *janus_sip_relay_thread(void *data);
309

    
310

    
311
/* URI parsing utilies */
312

    
313
#define JANUS_SIP_URI_MAXLEN        1024
314
typedef struct {
315
        char data[JANUS_SIP_URI_MAXLEN];
316
        url_t url[1];
317
} janus_sip_uri_t;
318

    
319
/* Parses a SIP URI (SIPS is not supported), returns 0 on success, -1 otherwise */
320
static int janus_sip_parse_uri(janus_sip_uri_t *sip_uri, const char *data) {
321
        g_strlcpy(sip_uri->data, data, JANUS_SIP_URI_MAXLEN);
322
        if (url_d(sip_uri->url, sip_uri->data) < 0 || sip_uri->url->url_type != url_sip)
323
                return -1;
324
        return 0;
325
}
326

    
327
/* Similar to th above function, but it also accepts SIPS URIs */
328
static int janus_sip_parse_proxy_uri(janus_sip_uri_t *sip_uri, const char *data) {
329
        g_strlcpy(sip_uri->data, data, JANUS_SIP_URI_MAXLEN);
330
        if (url_d(sip_uri->url, sip_uri->data) < 0 || (sip_uri->url->url_type != url_sip && sip_uri->url->url_type != url_sips))
331
                return -1;
332
        return 0;
333
}
334

    
335
/* Error codes */
336
#define JANUS_SIP_ERROR_UNKNOWN_ERROR                499
337
#define JANUS_SIP_ERROR_NO_MESSAGE                        440
338
#define JANUS_SIP_ERROR_INVALID_JSON                441
339
#define JANUS_SIP_ERROR_INVALID_REQUEST                442
340
#define JANUS_SIP_ERROR_MISSING_ELEMENT                443
341
#define JANUS_SIP_ERROR_INVALID_ELEMENT                444
342
#define JANUS_SIP_ERROR_ALREADY_REGISTERED        445
343
#define JANUS_SIP_ERROR_INVALID_ADDRESS                446
344
#define JANUS_SIP_ERROR_WRONG_STATE                        447
345
#define JANUS_SIP_ERROR_MISSING_SDP                        448
346
#define JANUS_SIP_ERROR_LIBSOFIA_ERROR                449
347
#define JANUS_SIP_ERROR_IO_ERROR                        450
348

    
349

    
350
/* SIP watchdog/garbage collector (sort of) */
351
void *janus_sip_watchdog(void *data);
352
void *janus_sip_watchdog(void *data) {
353
        JANUS_LOG(LOG_INFO, "SIP watchdog started\n");
354
        gint64 now = 0;
355
        while(g_atomic_int_get(&initialized) && !g_atomic_int_get(&stopping)) {
356
                janus_mutex_lock(&sessions_mutex);
357
                /* Iterate on all the sessions */
358
                now = janus_get_monotonic_time();
359
                if(old_sessions != NULL) {
360
                        GList *sl = old_sessions;
361
                        JANUS_LOG(LOG_HUGE, "Checking %d old SIP sessions...\n", g_list_length(old_sessions));
362
                        while(sl) {
363
                                janus_sip_session *session = (janus_sip_session *)sl->data;
364
                                if(!session) {
365
                                        sl = sl->next;
366
                                        continue;
367
                                }
368
                                if(now-session->destroyed >= 5*G_USEC_PER_SEC) {
369
                                        /* We're lazy and actually get rid of the stuff only after a few seconds */
370
                                        JANUS_LOG(LOG_VERB, "Freeing old SIP session\n");
371
                                        GList *rm = sl->next;
372
                                        old_sessions = g_list_delete_link(old_sessions, sl);
373
                                        sl = rm;
374
                                        session->handle = NULL;
375
                                        g_free(session);
376
                                        session = NULL;
377
                                        continue;
378
                                }
379
                                sl = sl->next;
380
                        }
381
                }
382
                janus_mutex_unlock(&sessions_mutex);
383
                g_usleep(500000);
384
        }
385
        JANUS_LOG(LOG_INFO, "SIP watchdog stopped\n");
386
        return NULL;
387
}
388

    
389

    
390
static void janus_sip_detect_local_ip(char *buf, size_t buflen) {
391
        JANUS_LOG(LOG_VERB, "Autodetecting local IP...\n");
392

    
393
        struct sockaddr_in addr;
394
        socklen_t len;
395
        int fd = socket(AF_INET, SOCK_DGRAM, 0);
396
        if (fd == -1)
397
                goto error;
398
        addr.sin_family = AF_INET;
399
        addr.sin_port = htons(1);
400
        inet_pton(AF_INET, "1.2.3.4", &addr.sin_addr.s_addr);
401
        if (connect(fd, (const struct sockaddr*) &addr, sizeof(addr)) < 0)
402
                goto error;
403
        len = sizeof(addr);
404
        if (getsockname(fd, (struct sockaddr*) &addr, &len) < 0)
405
                goto error;
406
        if (getnameinfo((const struct sockaddr*) &addr, sizeof(addr),
407
                        buf, buflen,
408
                        NULL, 0, NI_NUMERICHOST) != 0)
409
                goto error;
410
        close(fd);
411
        return;
412

    
413
error:
414
        if (fd != -1)
415
                close(fd);
416
        JANUS_LOG(LOG_VERB, "Couldn't find any address! using 127.0.0.1 as the local IP... (which is NOT going to work out of your machine)\n");
417
        g_strlcpy(buf, "127.0.0.1", buflen);
418
}
419

    
420

    
421
/* Plugin implementation */
422
int janus_sip_init(janus_callbacks *callback, const char *config_path) {
423
        if(g_atomic_int_get(&stopping)) {
424
                /* Still stopping from before */
425
                return -1;
426
        }
427
        if(callback == NULL || config_path == NULL) {
428
                /* Invalid arguments */
429
                return -1;
430
        }
431

    
432
        /* Read configuration */
433
        char filename[255];
434
        g_snprintf(filename, 255, "%s/%s.cfg", config_path, JANUS_SIP_PACKAGE);
435
        JANUS_LOG(LOG_VERB, "Configuration file: %s\n", filename);
436
        janus_config *config = janus_config_parse(filename);
437
        if(config != NULL)
438
                janus_config_print(config);
439

    
440
        gboolean local_ip_set = FALSE;
441
        janus_config_item *item = janus_config_get_item_drilldown(config, "general", "local_ip");
442
        if(item && item->value) {
443
                int family;
444
                if (!janus_is_ip_valid(item->value, &family)) {
445
                        JANUS_LOG(LOG_WARN, "Invalid local IP specified: %s, guessing the default...\n", item->value);
446
                } else {
447
                        /* Verify that we can actually bind to that address */
448
                        int fd = socket(family, SOCK_DGRAM, 0);
449
                        if (fd == -1) {
450
                                JANUS_LOG(LOG_WARN, "Error creating test socket, falling back to detecting IP address...\n");
451
                        } else {
452
                                int r;
453
                                struct sockaddr_storage ss;
454
                                socklen_t addrlen;
455
                                memset(&ss, 0, sizeof(ss));
456
                                if (family == AF_INET) {
457
                                        struct sockaddr_in *addr4 = (struct sockaddr_in*)&ss;
458
                                        addr4->sin_family = AF_INET;
459
                                        addr4->sin_port = 0;
460
                                        inet_pton(AF_INET, item->value, &(addr4->sin_addr.s_addr));
461
                                        addrlen = sizeof(struct sockaddr_in);
462
                                } else {
463
                                        struct sockaddr_in6 *addr6 = (struct sockaddr_in6*)&ss;
464
                                        addr6->sin6_family = AF_INET6;
465
                                        addr6->sin6_port = 0;
466
                                        inet_pton(AF_INET6, item->value, &(addr6->sin6_addr.s6_addr));
467
                                        addrlen = sizeof(struct sockaddr_in6);
468
                                }
469
                                r = bind(fd, (const struct sockaddr*)&ss, addrlen);
470
                                close(fd);
471
                                if (r < 0) {
472
                                        JANUS_LOG(LOG_WARN, "Error setting local IP address to %s, falling back to detecting IP address...\n", item->value);
473
                                } else {
474
                                        g_strlcpy(local_ip, item->value, sizeof(local_ip));
475
                                        local_ip_set = TRUE;
476
                                }
477
                        }
478
                }
479
        }
480
        if (!local_ip_set)
481
                janus_sip_detect_local_ip(local_ip, sizeof(local_ip));
482
        JANUS_LOG(LOG_VERB, "Local IP set to %s\n", local_ip);
483

    
484
        item = janus_config_get_item_drilldown(config, "general", "keepalive_interval");
485
        if(item && item->value)
486
                keepalive_interval = atoi(item->value);
487
        JANUS_LOG(LOG_VERB, "SIP keep-alive interval set to %d seconds\n", keepalive_interval);
488

    
489
        item = janus_config_get_item_drilldown(config, "general", "register_ttl");
490
        if(item && item->value)
491
                register_ttl = atoi(item->value);
492
        JANUS_LOG(LOG_VERB, "SIP registration TTL set to %d seconds\n", register_ttl);
493

    
494
        item = janus_config_get_item_drilldown(config, "general", "behind_nat");
495
        if(item && item->value)
496
                behind_nat = janus_is_true(item->value);
497

    
498
        item = janus_config_get_item_drilldown(config, "general", "user_agent");
499
        if(item && item->value)
500
                user_agent = g_strdup(item->value);
501
        else
502
                user_agent = g_strdup("Janus WebRTC Gateway SIP Plugin "JANUS_SIP_VERSION_STRING);
503
        JANUS_LOG(LOG_VERB, "SIP User-Agent set to %s\n", user_agent);
504

    
505
        /* This plugin actually has nothing to configure... */
506
        janus_config_destroy(config);
507
        config = NULL;
508

    
509
        /* Setup sofia */
510
        su_init();
511

    
512
        sessions = g_hash_table_new(NULL, NULL);
513
        janus_mutex_init(&sessions_mutex);
514
        messages = g_async_queue_new_full((GDestroyNotify) janus_sip_message_free);
515
        /* This is the callback we'll need to invoke to contact the gateway */
516
        gateway = callback;
517

    
518
        g_atomic_int_set(&initialized, 1);
519

    
520
        GError *error = NULL;
521
        /* Start the sessions watchdog */
522
        watchdog = g_thread_try_new("etest watchdog", &janus_sip_watchdog, NULL, &error);
523
        if(error != NULL) {
524
                g_atomic_int_set(&initialized, 0);
525
                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the SIP watchdog thread...\n", error->code, error->message ? error->message : "??");
526
                return -1;
527
        }
528
        /* Launch the thread that will handle incoming messages */
529
        handler_thread = g_thread_try_new("janus sip handler", janus_sip_handler, NULL, &error);
530
        if(error != NULL) {
531
                g_atomic_int_set(&initialized, 0);
532
                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the SIP handler thread...\n", error->code, error->message ? error->message : "??");
533
                return -1;
534
        }
535
        JANUS_LOG(LOG_INFO, "%s initialized!\n", JANUS_SIP_NAME);
536
        return 0;
537
}
538

    
539
void janus_sip_destroy(void) {
540
        if(!g_atomic_int_get(&initialized))
541
                return;
542
        g_atomic_int_set(&stopping, 1);
543
        if(handler_thread != NULL) {
544
                g_thread_join(handler_thread);
545
                handler_thread = NULL;
546
        }
547
        if(watchdog != NULL) {
548
                g_thread_join(watchdog);
549
                watchdog = NULL;
550
        }
551
        /* FIXME We should destroy the sessions cleanly */
552
        janus_mutex_lock(&sessions_mutex);
553
        g_hash_table_destroy(sessions);
554
        janus_mutex_unlock(&sessions_mutex);
555
        g_async_queue_unref(messages);
556
        messages = NULL;
557
        sessions = NULL;
558
        g_atomic_int_set(&initialized, 0);
559
        g_atomic_int_set(&stopping, 0);
560
        JANUS_LOG(LOG_INFO, "%s destroyed!\n", JANUS_SIP_NAME);
561
}
562

    
563
int janus_sip_get_api_compatibility(void) {
564
        /* Important! This is what your plugin MUST always return: don't lie here or bad things will happen */
565
        return JANUS_PLUGIN_API_VERSION;
566
}
567

    
568
int janus_sip_get_version(void) {
569
        return JANUS_SIP_VERSION;
570
}
571

    
572
const char *janus_sip_get_version_string(void) {
573
        return JANUS_SIP_VERSION_STRING;
574
}
575

    
576
const char *janus_sip_get_description(void) {
577
        return JANUS_SIP_DESCRIPTION;
578
}
579

    
580
const char *janus_sip_get_name(void) {
581
        return JANUS_SIP_NAME;
582
}
583

    
584
const char *janus_sip_get_author(void) {
585
        return JANUS_SIP_AUTHOR;
586
}
587

    
588
const char *janus_sip_get_package(void) {
589
        return JANUS_SIP_PACKAGE;
590
}
591

    
592
void janus_sip_create_session(janus_plugin_session *handle, int *error) {
593
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
594
                *error = -1;
595
                return;
596
        }        
597
        janus_sip_session *session = g_malloc0(sizeof(janus_sip_session));
598
        session->handle = handle;
599
        session->account.identity = NULL;
600
        session->account.username = NULL;
601
        session->account.secret = NULL;
602
        session->account.secret_type = janus_sip_secret_type_unknown;
603
        session->account.sip_port = 0;
604
        session->account.proxy = NULL;
605
        session->account.registration_status = janus_sip_registration_status_unregistered;
606
        session->status = janus_sip_call_status_idle;
607
        session->stack = g_malloc0(sizeof(ssip_t));
608
        session->stack->session = session;
609
        session->stack->s_nua = NULL;
610
        session->stack->s_nh_r = NULL;
611
        session->stack->s_nh_i = NULL;
612
        session->stack->s_root = NULL;
613
        session->transaction = NULL;
614
        session->callee = NULL;
615
        session->media.remote_ip = NULL;
616
        session->media.ready = 0;
617
        session->media.has_audio = 0;
618
        session->media.audio_rtp_fd = 0;
619
        session->media.audio_rtcp_fd= 0;
620
        session->media.local_audio_rtp_port = 0;
621
        session->media.remote_audio_rtp_port = 0;
622
        session->media.local_audio_rtcp_port = 0;
623
        session->media.remote_audio_rtcp_port = 0;
624
        session->media.audio_ssrc = 0;
625
        session->media.audio_ssrc_peer = 0;
626
        session->media.has_video = 0;
627
        session->media.video_rtp_fd = 0;
628
        session->media.video_rtcp_fd= 0;
629
        session->media.local_video_rtp_port = 0;
630
        session->media.remote_video_rtp_port = 0;
631
        session->media.local_video_rtcp_port = 0;
632
        session->media.remote_video_rtcp_port = 0;
633
        session->media.video_ssrc = 0;
634
        session->media.video_ssrc_peer = 0;
635
        session->destroyed = 0;
636
        su_home_init(session->stack->s_home);
637
        janus_mutex_init(&session->mutex);
638
        handle->plugin_handle = session;
639

    
640
        janus_mutex_lock(&sessions_mutex);
641
        g_hash_table_insert(sessions, handle, session);
642
        janus_mutex_unlock(&sessions_mutex);
643

    
644
        return;
645
}
646

    
647
void janus_sip_destroy_session(janus_plugin_session *handle, int *error) {
648
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
649
                *error = -1;
650
                return;
651
        }        
652
        janus_sip_session *session = (janus_sip_session *)handle->plugin_handle; 
653
        if(!session) {
654
                JANUS_LOG(LOG_ERR, "No SIP session associated with this handle...\n");
655
                *error = -2;
656
                return;
657
        }
658
        janus_mutex_lock(&sessions_mutex);
659
        if(!session->destroyed) {
660
                g_hash_table_remove(sessions, handle);
661
                janus_sip_hangup_media(handle);
662
                session->destroyed = janus_get_monotonic_time();
663
                JANUS_LOG(LOG_VERB, "Destroying SIP session (%s)...\n", session->account.username ? session->account.username : "unregistered user");
664
                /* Shutdown the NUA */
665
                nua_shutdown(session->stack->s_nua);
666
                /* Cleaning up and removing the session is done in a lazy way */
667
                old_sessions = g_list_append(old_sessions, session);
668
        }
669
        janus_mutex_unlock(&sessions_mutex);
670
        return;
671
}
672

    
673
char *janus_sip_query_session(janus_plugin_session *handle) {
674
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
675
                return NULL;
676
        }
677
        janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;
678
        if(!session) {
679
                JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
680
                return NULL;
681
        }
682
        /* Provide some generic info, e.g., if we're in a call and with whom */
683
        json_t *info = json_object();
684
        json_object_set_new(info, "username", session->account.username ? json_string(session->account.username) : NULL);
685
        json_object_set_new(info, "identity", session->account.identity ? json_string(session->account.identity) : NULL);
686
        json_object_set_new(info, "registration_status", json_string(janus_sip_registration_status_string(session->account.registration_status)));
687
        json_object_set_new(info, "call_status", json_string(janus_sip_call_status_string(session->status)));
688
        if(session->callee)
689
                json_object_set_new(info, "callee", json_string(session->callee ? session->callee : "??"));
690
        json_object_set_new(info, "destroyed", json_integer(session->destroyed));
691
        char *info_text = json_dumps(info, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
692
        json_decref(info);
693
        return info_text;
694
}
695

    
696
struct janus_plugin_result *janus_sip_handle_message(janus_plugin_session *handle, char *transaction, char *message, char *sdp_type, char *sdp) {
697
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
698
                return janus_plugin_result_new(JANUS_PLUGIN_ERROR, g_atomic_int_get(&stopping) ? "Shutting down" : "Plugin not initialized");
699
        JANUS_LOG(LOG_VERB, "%s\n", message);
700
        janus_sip_message *msg = g_malloc0(sizeof(janus_sip_message));
701
        msg->handle = handle;
702
        msg->transaction = transaction;
703
        msg->message = message;
704
        msg->sdp_type = sdp_type;
705
        msg->sdp = sdp;
706
        g_async_queue_push(messages, msg);
707

    
708
        /* All the requests to this plugin are handled asynchronously */
709
        return janus_plugin_result_new(JANUS_PLUGIN_OK_WAIT, NULL);
710
}
711

    
712
void janus_sip_setup_media(janus_plugin_session *handle) {
713
        JANUS_LOG(LOG_INFO, "WebRTC media is now available\n");
714
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
715
                return;
716
        janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;        
717
        if(!session) {
718
                JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
719
                return;
720
        }
721
        if(session->destroyed)
722
                return;
723
        /* TODO Only relay RTP/RTCP when we get this event */
724
}
725

    
726
void janus_sip_incoming_rtp(janus_plugin_session *handle, int video, char *buf, int len) {
727
        if(handle == NULL || handle->stopped || g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
728
                return;
729
        if(gateway) {
730
                /* Honour the audio/video active flags */
731
                janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;        
732
                if(!session || session->destroyed) {
733
                        JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
734
                        return;
735
                }
736
                if(session->status != janus_sip_call_status_incall)
737
                        return;
738
                /* Forward to our SIP peer */
739
                if(video) {
740
                        if(session->media.video_ssrc == 0) {
741
                                rtp_header *header = (rtp_header *)buf;
742
                                session->media.video_ssrc = ntohl(header->ssrc);
743
                                JANUS_LOG(LOG_VERB, "Got SIP video SSRC: %"SCNu32"\n", session->media.video_ssrc);
744
                        }
745
                        if(session->media.has_video && session->media.video_rtp_fd) {
746
                                send(session->media.video_rtp_fd, buf, len, 0);
747
                        }
748
                } else {
749
                        if(session->media.audio_ssrc == 0) {
750
                                rtp_header *header = (rtp_header *)buf;
751
                                session->media.audio_ssrc = ntohl(header->ssrc);
752
                                JANUS_LOG(LOG_VERB, "Got SIP audio SSRC: %"SCNu32"\n", session->media.audio_ssrc);
753
                        }
754
                        if(session->media.has_audio && session->media.audio_rtp_fd) {
755
                                send(session->media.audio_rtp_fd, buf, len, 0);
756
                        }
757
                }
758
        }
759
}
760

    
761
void janus_sip_incoming_rtcp(janus_plugin_session *handle, int video, char *buf, int len) {
762
        if(handle == NULL || handle->stopped || g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
763
                return;
764
        if(gateway) {
765
                janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;        
766
                if(!session || session->destroyed) {
767
                        JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
768
                        return;
769
                }
770
                if(session->status != janus_sip_call_status_incall)
771
                        return;
772
                /* Fix SSRCs as the gateway does */
773
                JANUS_LOG(LOG_HUGE, "[SIP] Fixing SSRCs (local %u, peer %u)\n",
774
                        video ? session->media.video_ssrc : session->media.audio_ssrc,
775
                        video ? session->media.video_ssrc_peer : session->media.audio_ssrc_peer);
776
                janus_rtcp_fix_ssrc((char *)buf, len, 1,
777
                        video ? session->media.video_ssrc : session->media.audio_ssrc,
778
                        video ? session->media.video_ssrc_peer : session->media.audio_ssrc_peer);
779
                /* Forward to our SIP peer */
780
                if(video) {
781
                        if(session->media.has_video && session->media.video_rtcp_fd) {
782
                                send(session->media.video_rtcp_fd, buf, len, 0);
783
                        }
784
                } else {
785
                        if(session->media.has_audio && session->media.audio_rtcp_fd) {
786
                                send(session->media.audio_rtcp_fd, buf, len, 0);
787
                        }
788
                }
789
        }
790
}
791

    
792
void janus_sip_hangup_media(janus_plugin_session *handle) {
793
        JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
794
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
795
                return;
796
        janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;        
797
        if(!session) {
798
                JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
799
                return;
800
        }
801
        if(session->destroyed || g_atomic_int_get(&session->hangingup))
802
                return;
803
        g_atomic_int_set(&session->hangingup, 1);
804
        if(!(session->status == janus_sip_call_status_inviting ||
805
                 session->status == janus_sip_call_status_invited ||
806
                 session->status == janus_sip_call_status_incall))
807
                return;
808
        /* FIXME Simulate a "hangup" coming from the browser */
809
        janus_sip_message *msg = g_malloc0(sizeof(janus_sip_message));
810
        msg->handle = handle;
811
        msg->message = g_strdup("{\"request\":\"hangup\"}");
812
        msg->transaction = NULL;
813
        msg->sdp_type = NULL;
814
        msg->sdp = NULL;
815
        g_async_queue_push(messages, msg);
816
        /* Done */
817
        g_atomic_int_set(&session->hangingup, 0);
818
}
819

    
820
/* Thread to handle incoming messages */
821
static void *janus_sip_handler(void *data) {
822
        JANUS_LOG(LOG_VERB, "Joining SIP handler thread\n");
823
        janus_sip_message *msg = NULL;
824
        int error_code = 0;
825
        char *error_cause = g_malloc0(512);
826
        json_t *root = NULL;
827
        while(g_atomic_int_get(&initialized) && !g_atomic_int_get(&stopping)) {
828
                if(!messages || (msg = g_async_queue_try_pop(messages)) == NULL) {
829
                        usleep(50000);
830
                        continue;
831
                }
832
                janus_sip_session *session = (janus_sip_session *)msg->handle->plugin_handle;
833
                if(!session) {
834
                        JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
835
                        janus_sip_message_free(msg);
836
                        continue;
837
                }
838
                if(session->destroyed) {
839
                        janus_sip_message_free(msg);
840
                        continue;
841
                }
842
                /* Handle request */
843
                error_code = 0;
844
                root = NULL;
845
                JANUS_LOG(LOG_VERB, "Handling message: %s\n", msg->message);
846
                if(msg->message == NULL) {
847
                        JANUS_LOG(LOG_ERR, "No message??\n");
848
                        error_code = JANUS_SIP_ERROR_NO_MESSAGE;
849
                        g_snprintf(error_cause, 512, "%s", "No message??");
850
                        goto error;
851
                }
852
                json_error_t error;
853
                root = json_loads(msg->message, 0, &error);
854
                if(!root) {
855
                        JANUS_LOG(LOG_ERR, "JSON error: on line %d: %s\n", error.line, error.text);
856
                        error_code = JANUS_SIP_ERROR_INVALID_JSON;
857
                        g_snprintf(error_cause, 512, "JSON error: on line %d: %s", error.line, error.text);
858
                        goto error;
859
                }
860
                if(!json_is_object(root)) {
861
                        JANUS_LOG(LOG_ERR, "JSON error: not an object\n");
862
                        error_code = JANUS_SIP_ERROR_INVALID_JSON;
863
                        g_snprintf(error_cause, 512, "JSON error: not an object");
864
                        goto error;
865
                }
866
                json_t *request = json_object_get(root, "request");
867
                if(!request) {
868
                        JANUS_LOG(LOG_ERR, "Missing element (request)\n");
869
                        error_code = JANUS_SIP_ERROR_MISSING_ELEMENT;
870
                        g_snprintf(error_cause, 512, "Missing element (request)");
871
                        goto error;
872
                }
873
                if(!json_is_string(request)) {
874
                        JANUS_LOG(LOG_ERR, "Invalid element (request should be a string)\n");
875
                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
876
                        g_snprintf(error_cause, 512, "Invalid element (request should be a string)");
877
                        goto error;
878
                }
879
                const char *request_text = json_string_value(request);
880
                json_t *result = NULL;
881
                char *sdp_type = NULL, *sdp = NULL;
882
                if(!strcasecmp(request_text, "register")) {
883
                        /* Send a REGISTER */
884
                        if(session->account.registration_status > janus_sip_registration_status_unregistered) {
885
                                JANUS_LOG(LOG_ERR, "Already registered (%s)\n", session->account.username);
886
                                error_code = JANUS_SIP_ERROR_ALREADY_REGISTERED;
887
                                g_snprintf(error_cause, 512, "Already registered (%s)", session->account.username);
888
                                goto error;
889
                        }
890

    
891
                        /* Cleanup old values */
892
                        if(session->account.identity != NULL)
893
                                g_free(session->account.identity);
894
                        session->account.identity = NULL;
895
                        if(session->account.username != NULL)
896
                                g_free(session->account.username);
897
                        session->account.username = NULL;
898
                        if(session->account.secret != NULL)
899
                                g_free(session->account.secret);
900
                        session->account.secret = NULL;
901
                        session->account.secret_type = janus_sip_secret_type_unknown;
902
                        if(session->account.proxy != NULL)
903
                                g_free(session->account.proxy);
904
                        session->account.proxy = NULL;
905
                        session->account.registration_status = janus_sip_registration_status_unregistered;
906

    
907
                        gboolean guest = FALSE;
908
                        json_t *type = json_object_get(root, "type");
909
                        if(type != NULL) {
910
                                if(!json_is_string(type)) {
911
                                        JANUS_LOG(LOG_ERR, "Invalid element (type should be a string)\n");
912
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
913
                                        g_snprintf(error_cause, 512, "Invalid element (type should be a string)");
914
                                        goto error;
915
                                }
916
                                const char *type_text = json_string_value(type);
917
                                if(!strcmp(type_text, "guest")) {
918
                                        JANUS_LOG(LOG_INFO, "Registering as a guest\n");
919
                                        guest = TRUE;
920
                                } else {
921
                                        JANUS_LOG(LOG_WARN, "Unknown type '%s', ignoring...\n", type_text);
922
                                }
923
                        }
924

    
925
                        gboolean send_register = TRUE;
926
                        json_t *do_register = json_object_get(root, "send_register");
927
                        if(do_register != NULL) {
928
                                if(!json_is_boolean(do_register)) {
929
                                        JANUS_LOG(LOG_ERR, "Invalid element (type should be boolean)\n");
930
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
931
                                        g_snprintf(error_cause, 512, "Invalid element (type should be boolean)");
932
                                        goto error;
933
                                }
934
                                if(guest) {
935
                                        JANUS_LOG(LOG_ERR, "Conflicting elements: send_register cannot be true if guest is true\n");
936
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
937
                                        g_snprintf(error_cause, 512, "Conflicting elements: send_register cannot be true if guest is true");
938
                                        goto error;
939
                                }
940
                                send_register = json_is_true(do_register);
941
                        }
942

    
943
                        /* Parse address */
944
                        json_t *proxy = json_object_get(root, "proxy");
945
                        const char *proxy_text = NULL;
946

    
947
                        if (proxy && !json_is_null(proxy)) {
948
                                if(!json_is_string(proxy)) {
949
                                        JANUS_LOG(LOG_ERR, "Invalid element (proxy should be a string)\n");
950
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
951
                                        g_snprintf(error_cause, 512, "Invalid element (proxy should be a string)");
952
                                        goto error;
953
                                }
954
                                proxy_text = json_string_value(proxy);
955
                                janus_sip_uri_t proxy_uri;
956
                                if (janus_sip_parse_proxy_uri(&proxy_uri, proxy_text) < 0) {
957
                                        JANUS_LOG(LOG_ERR, "Invalid proxy address %s\n", proxy_text);
958
                                        error_code = JANUS_SIP_ERROR_INVALID_ADDRESS;
959
                                        g_snprintf(error_cause, 512, "Invalid proxy address %s\n", proxy_text);
960
                                        goto error;
961
                                }
962
                        }
963

    
964
                        /* Parse register TTL */
965
                        int ttl = register_ttl;
966
                        json_t *reg_ttl = json_object_get(root, "register_ttl");
967
                        if (reg_ttl && json_is_integer(reg_ttl))
968
                                ttl = json_integer_value(reg_ttl);
969
                        if (ttl <= 0)
970
                                ttl = JANUS_DEFAULT_REGISTER_TTL;
971

    
972
                        /* Now the user part, if needed */
973
                        json_t *username = json_object_get(root, "username");
974
                        if(!guest && !username) {
975
                                /* The username is mandatory if we're not registering as guests */
976
                                JANUS_LOG(LOG_ERR, "Missing element (username)\n");
977
                                error_code = JANUS_SIP_ERROR_MISSING_ELEMENT;
978
                                g_snprintf(error_cause, 512, "Missing element (username)");
979
                                goto error;
980
                        }
981
                        const char *username_text = NULL;
982
                        janus_sip_uri_t username_uri;
983
                        char user_id[256];
984
                        if(username) {
985
                                if(!json_is_string(username)) {
986
                                        JANUS_LOG(LOG_ERR, "Invalid element (username should be a string)\n");
987
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
988
                                        g_snprintf(error_cause, 512, "Invalid element (username should be a string)");
989
                                        goto error;
990
                                }
991
                                /* Parse address */
992
                                username_text = json_string_value(username);
993
                                if (janus_sip_parse_uri(&username_uri, username_text) < 0) {
994
                                        JANUS_LOG(LOG_ERR, "Invalid user address %s\n", username_text);
995
                                        error_code = JANUS_SIP_ERROR_INVALID_ADDRESS;
996
                                        g_snprintf(error_cause, 512, "Invalid user address %s\n", username_text);
997
                                        goto error;
998
                                }
999
                                g_strlcpy(user_id, username_uri.url->url_user, sizeof(user_id));
1000
                        }
1001
                        if(guest) {
1002
                                /* Not needed, we can stop here: just pick a random username if it wasn't provided and say we're registered */
1003
                                if(!username)
1004
                                        g_snprintf(user_id, 255, "janus-sip-%"SCNu32"", g_random_int());
1005
                                JANUS_LOG(LOG_INFO, "Guest will have username %s\n", user_id);
1006
                                send_register = FALSE;
1007
                        } else {
1008
                                json_t *secret = json_object_get(root, "secret");
1009
                                json_t *ha1_secret = json_object_get(root, "ha1_secret");
1010
                                if(!secret && !ha1_secret) {
1011
                                        JANUS_LOG(LOG_ERR, "Missing element (secret or ha1_secret)\n");
1012
                                        error_code = JANUS_SIP_ERROR_MISSING_ELEMENT;
1013
                                        g_snprintf(error_cause, 512, "Missing element (secret or ha1_secret)");
1014
                                        goto error;
1015
                                }
1016
                                if(secret && ha1_secret) {
1017
                                        JANUS_LOG(LOG_ERR, "Conflicting elements specified (secret and ha1_secret)\n");
1018
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
1019
                                        g_snprintf(error_cause, 512, "Conflicting elements specified (secret and ha1_secret)");
1020
                                        goto error;
1021
                                }
1022
                                const char *secret_text;
1023
                                if(secret) {
1024
                                        if(!json_is_string(secret)) {
1025
                                                JANUS_LOG(LOG_ERR, "Invalid element (secret should be a string)\n");
1026
                                                error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
1027
                                                g_snprintf(error_cause, 512, "Invalid element (secret should be a string)");
1028
                                                goto error;
1029
                                        }
1030
                                        secret_text = json_string_value(secret);
1031
                                        session->account.secret = g_strdup(secret_text);
1032
                                        session->account.secret_type = janus_sip_secret_type_plaintext;
1033
                                } else {
1034
                                        if(!json_is_string(ha1_secret)) {
1035
                                                JANUS_LOG(LOG_ERR, "Invalid element (ha1_secret should be a string)\n");
1036
                                                error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
1037
                                                g_snprintf(error_cause, 512, "Invalid element (ha1_secret should be a string)");
1038
                                                goto error;
1039
                                        }
1040
                                        secret_text = json_string_value(ha1_secret);
1041
                                        session->account.secret = g_strdup(secret_text);
1042
                                        session->account.secret_type = janus_sip_secret_type_hashed;
1043
                                }
1044
                                /* Got the values, try registering now */
1045
                                JANUS_LOG(LOG_VERB, "Registering user %s (secret %s) @ %s through %s\n",
1046
                                        username_text, secret_text, username_uri.url->url_host, proxy_text != NULL ? proxy_text : "(null)");
1047
                        }
1048

    
1049
                        session->account.identity = g_strdup(username_text);
1050
                        session->account.username = g_strdup(user_id);
1051
                        if (proxy_text) {
1052
                                session->account.proxy = g_strdup(proxy_text);
1053
                        }
1054

    
1055
                        session->account.registration_status = janus_sip_registration_status_registering;
1056
                        if(session->stack->s_nua == NULL) {
1057
                                /* Start the thread first */
1058
                                GError *error = NULL;
1059
                                g_thread_try_new("worker", janus_sip_sofia_thread, session, &error);
1060
                                if(error != NULL) {
1061
                                        JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the SIP Sofia thread...\n", error->code, error->message ? error->message : "??");
1062
                                        error_code = JANUS_SIP_ERROR_UNKNOWN_ERROR;
1063
                                        g_snprintf(error_cause, 512, "Got error %d (%s) trying to launch the SIP Sofia thread", error->code, error->message ? error->message : "??");
1064
                                        goto error;
1065
                                }
1066
                                long int timeout = 0;
1067
                                while(session->stack->s_nua == NULL) {
1068
                                        g_usleep(100000);
1069
                                        timeout += 100000;
1070
                                        if(timeout >= 2000000) {
1071
                                                break;
1072
                                        }
1073
                                }
1074
                                if(timeout >= 2000000) {
1075
                                        JANUS_LOG(LOG_ERR, "Two seconds passed and still no NUA, problems with the thread?\n");
1076
                                        error_code = JANUS_SIP_ERROR_UNKNOWN_ERROR;
1077
                                        g_snprintf(error_cause, 512, "Two seconds passed and still no NUA, problems with the thread?");
1078
                                        goto error;
1079
                                }
1080
                        }
1081
                        if(session->stack->s_nh_r != NULL) {
1082
                                nua_handle_destroy(session->stack->s_nh_r);
1083
                                session->stack->s_nh_r = NULL;
1084
                        }
1085

    
1086
                        if (send_register) {
1087
                                session->stack->s_nh_r = nua_handle(session->stack->s_nua, session, TAG_END());
1088
                                if(session->stack->s_nh_r == NULL) {
1089
                                        JANUS_LOG(LOG_ERR, "NUA Handle for REGISTER still null??\n");
1090
                                        error_code = JANUS_SIP_ERROR_LIBSOFIA_ERROR;
1091
                                        g_snprintf(error_cause, 512, "Invalid NUA Handle");
1092
                                        goto error;
1093
                                }
1094
                                char ttl_text[20];
1095
                                g_snprintf(ttl_text, sizeof(ttl_text), "%d", ttl);
1096
                                nua_register(session->stack->s_nh_r,
1097
                                        NUTAG_M_USERNAME(session->account.username),
1098
                                        SIPTAG_FROM_STR(username_text),
1099
                                        SIPTAG_TO_STR(username_text),
1100
                                        SIPTAG_EXPIRES_STR(ttl_text),
1101
                                        NUTAG_PROXY(proxy_text),
1102
                                        TAG_END());
1103
                                result = json_object();
1104
                                json_object_set_new(result, "event", json_string("registering"));
1105
                        } else {
1106
                                JANUS_LOG(LOG_VERB, "Not sending a SIP REGISTER: either send_register was set to false or guest mode was enabled\n");
1107
                                session->account.registration_status = janus_sip_registration_status_disabled;
1108
                                result = json_object();
1109
                                json_object_set_new(result, "event", json_string("registered"));
1110
                                json_object_set_new(result, "username", json_string(session->account.username));
1111
                                json_object_set_new(result, "register_sent", json_string("false"));
1112
                        }
1113
                } else if(!strcasecmp(request_text, "call")) {
1114
                        /* Call another peer */
1115
                        if(session->status >= janus_sip_call_status_inviting) {
1116
                                JANUS_LOG(LOG_ERR, "Wrong state (already in a call? status=%s)\n", janus_sip_call_status_string(session->status));
1117
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1118
                                g_snprintf(error_cause, 512, "Wrong state (already in a call? status=%s)", janus_sip_call_status_string(session->status));
1119
                                goto error;
1120
                        }
1121
                        json_t *uri = json_object_get(root, "uri");
1122
                        if(!uri) {
1123
                                JANUS_LOG(LOG_ERR, "Missing element (uri)\n");
1124
                                error_code = JANUS_SIP_ERROR_MISSING_ELEMENT;
1125
                                g_snprintf(error_cause, 512, "Missing element (uri)");
1126
                                goto error;
1127
                        }
1128
                        if(!json_is_string(uri)) {
1129
                                JANUS_LOG(LOG_ERR, "Invalid element (uri should be a string)\n");
1130
                                error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
1131
                                g_snprintf(error_cause, 512, "Invalid element (uri should be a string)");
1132
                                goto error;
1133
                        }
1134
                        /* Parse address */
1135
                        const char *uri_text = json_string_value(uri);
1136
                        janus_sip_uri_t target_uri;
1137
                        if (janus_sip_parse_uri(&target_uri, uri_text) < 0) {
1138
                                JANUS_LOG(LOG_ERR, "Invalid user address %s\n", uri_text);
1139
                                error_code = JANUS_SIP_ERROR_INVALID_ADDRESS;
1140
                                g_snprintf(error_cause, 512, "Invalid user address %s\n", uri_text);
1141
                                goto error;
1142
                        }
1143
                        /* Any SDP to handle? if not, something's wrong */
1144
                        if(!msg->sdp) {
1145
                                JANUS_LOG(LOG_ERR, "Missing SDP\n");
1146
                                error_code = JANUS_SIP_ERROR_MISSING_SDP;
1147
                                g_snprintf(error_cause, 512, "Missing SDP");
1148
                                goto error;
1149
                        }
1150
                        JANUS_LOG(LOG_VERB, "%s is calling %s\n", session->account.username, uri_text);
1151
                        JANUS_LOG(LOG_VERB, "This is involving a negotiation (%s) as well:\n%s\n", msg->sdp_type, msg->sdp);
1152
                        /* Allocate RTP ports and merge them with the anonymized SDP */
1153
                        if(strstr(msg->sdp, "m=audio")) {
1154
                                JANUS_LOG(LOG_VERB, "Going to negotiate audio...\n");
1155
                                session->media.has_audio = 1;        /* FIXME Maybe we need a better way to signal this */
1156
                        }
1157
                        if(strstr(msg->sdp, "m=video")) {
1158
                                JANUS_LOG(LOG_VERB, "Going to negotiate video...\n");
1159
                                session->media.has_video = 1;        /* FIXME Maybe we need a better way to signal this */
1160
                        }
1161
                        if(janus_sip_allocate_local_ports(session) < 0) {
1162
                                JANUS_LOG(LOG_ERR, "Could not allocate RTP/RTCP ports\n");
1163
                                error_code = JANUS_SIP_ERROR_IO_ERROR;
1164
                                g_snprintf(error_cause, 512, "Could not allocate RTP/RTCP ports");
1165
                                goto error;
1166
                        }
1167
                        char *sdp = g_strdup(msg->sdp);
1168
                        sdp = janus_string_replace(sdp, "RTP/SAVPF", "RTP/AVP");
1169
                        sdp = janus_string_replace(sdp, "1.1.1.1", local_ip);
1170
                        if(session->media.has_audio) {
1171
                                JANUS_LOG(LOG_VERB, "Setting local audio port: %d\n", session->media.local_audio_rtp_port);
1172
                                char mline[20];
1173
                                g_snprintf(mline, 20, "m=audio %d", session->media.local_audio_rtp_port);
1174
                                sdp = janus_string_replace(sdp, "m=audio 1", mline);
1175
                        }
1176
                        if(session->media.has_video) {
1177
                                JANUS_LOG(LOG_VERB, "Setting local video port: %d\n", session->media.local_video_rtp_port);
1178
                                char mline[20];
1179
                                g_snprintf(mline, 20, "m=video %d", session->media.local_video_rtp_port);
1180
                                sdp = janus_string_replace(sdp, "m=video 1", mline);
1181
                        }
1182
                        /* Send INVITE */
1183
                        if(session->stack->s_nh_i != NULL)
1184
                                nua_handle_destroy(session->stack->s_nh_i);
1185
                        session->stack->s_nh_i = nua_handle(session->stack->s_nua, session, TAG_END());
1186
                        if(session->stack->s_nh_i == NULL) {
1187
                                JANUS_LOG(LOG_WARN, "NUA Handle for INVITE still null??\n");
1188
                                error_code = JANUS_SIP_ERROR_LIBSOFIA_ERROR;
1189
                                g_snprintf(error_cause, 512, "Invalid NUA Handle");
1190
                                goto error;
1191
                        }
1192
                        session->status = janus_sip_call_status_inviting;
1193
                        nua_invite(session->stack->s_nh_i,
1194
                                SIPTAG_FROM_STR(session->account.identity),
1195
                                SIPTAG_TO_STR(uri_text),
1196
                                SOATAG_USER_SDP_STR(sdp),
1197
                                NUTAG_PROXY(session->account.proxy),
1198
                                TAG_END());
1199
                        g_free(sdp);
1200
                        session->callee = g_strdup(uri_text);
1201
                        if(session->transaction)
1202
                                g_free(session->transaction);
1203
                        session->transaction = msg->transaction ? g_strdup(msg->transaction) : NULL;
1204
                        /* Send an ack back */
1205
                        result = json_object();
1206
                        json_object_set_new(result, "event", json_string("calling"));
1207
                } else if(!strcasecmp(request_text, "accept")) {
1208
                        if(session->status != janus_sip_call_status_invited) {
1209
                                JANUS_LOG(LOG_ERR, "Wrong state (not invited? status=%s)\n", janus_sip_call_status_string(session->status));
1210
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1211
                                g_snprintf(error_cause, 512, "Wrong state (not invited? status=%s)", janus_sip_call_status_string(session->status));
1212
                                goto error;
1213
                        }
1214
                        if(session->callee == NULL) {
1215
                                JANUS_LOG(LOG_ERR, "Wrong state (no caller?)\n");
1216
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1217
                                g_snprintf(error_cause, 512, "Wrong state (no caller?)");
1218
                                goto error;
1219
                        }
1220
                        /* Any SDP to handle? if not, something's wrong */
1221
                        if(!msg->sdp) {
1222
                                JANUS_LOG(LOG_ERR, "Missing SDP\n");
1223
                                error_code = JANUS_SIP_ERROR_MISSING_SDP;
1224
                                g_snprintf(error_cause, 512, "Missing SDP");
1225
                                goto error;
1226
                        }
1227
                        /* Accept a call from another peer */
1228
                        JANUS_LOG(LOG_VERB, "We're accepting the call from %s\n", session->callee);
1229
                        JANUS_LOG(LOG_VERB, "This is involving a negotiation (%s) as well:\n%s\n", msg->sdp_type, msg->sdp);
1230
                        /* Allocate RTP ports and merge them with the anonymized SDP */
1231
                        if(strstr(msg->sdp, "m=audio")) {
1232
                                JANUS_LOG(LOG_VERB, "Going to negotiate audio...\n");
1233
                                session->media.has_audio = 1;        /* FIXME Maybe we need a better way to signal this */
1234
                        }
1235
                        if(strstr(msg->sdp, "m=video")) {
1236
                                JANUS_LOG(LOG_VERB, "Going to negotiate video...\n");
1237
                                session->media.has_video = 1;        /* FIXME Maybe we need a better way to signal this */
1238
                        }
1239
                        if(janus_sip_allocate_local_ports(session) < 0) {
1240
                                JANUS_LOG(LOG_ERR, "Could not allocate RTP/RTCP ports\n");
1241
                                error_code = JANUS_SIP_ERROR_IO_ERROR;
1242
                                g_snprintf(error_cause, 512, "Could not allocate RTP/RTCP ports");
1243
                                goto error;
1244
                        }
1245
                        char *sdp = g_strdup(msg->sdp);
1246
                        sdp = janus_string_replace(sdp, "RTP/SAVPF", "RTP/AVP");
1247
                        sdp = janus_string_replace(sdp, "1.1.1.1", local_ip);
1248
                        if(session->media.has_audio) {
1249
                                JANUS_LOG(LOG_VERB, "Setting local audio port: %d\n", session->media.local_audio_rtp_port);
1250
                                char mline[20];
1251
                                g_snprintf(mline, 20, "m=audio %d", session->media.local_audio_rtp_port);
1252
                                sdp = janus_string_replace(sdp, "m=audio 1", mline);
1253
                        }
1254
                        if(session->media.has_video) {
1255
                                JANUS_LOG(LOG_VERB, "Setting local video port: %d\n", session->media.local_video_rtp_port);
1256
                                char mline[20];
1257
                                g_snprintf(mline, 20, "m=video %d", session->media.local_video_rtp_port);
1258
                                sdp = janus_string_replace(sdp, "m=video 1", mline);
1259
                        }
1260
                        /* Send 200 OK */
1261
                        session->status = janus_sip_call_status_incall;
1262
                        if(session->stack->s_nh_i == NULL) {
1263
                                JANUS_LOG(LOG_WARN, "NUA Handle for 200 OK still null??\n");
1264
                        }
1265
                        nua_respond(session->stack->s_nh_i,
1266
                                200, sip_status_phrase(200),
1267
                                SOATAG_USER_SDP_STR(sdp),
1268
                                TAG_END());
1269
                        g_free(sdp);
1270
                        /* Send an ack back */
1271
                        result = json_object();
1272
                        json_object_set_new(result, "event", json_string("accepted"));
1273
                        /* Start the media */
1274
                        session->media.ready = 1;        /* FIXME Maybe we need a better way to signal this */
1275
                        GError *error = NULL;
1276
                        g_thread_try_new("janus rtp handler", janus_sip_relay_thread, session, &error);
1277
                        if(error != NULL) {
1278
                                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the RTP/RTCP thread...\n", error->code, error->message ? error->message : "??");
1279
                        }
1280
                } else if(!strcasecmp(request_text, "decline")) {
1281
                        /* Reject an incoming call */
1282
                        if(session->status != janus_sip_call_status_invited) {
1283
                                JANUS_LOG(LOG_ERR, "Wrong state (not invited? status=%s)\n", janus_sip_call_status_string(session->status));
1284
                                /* Ignore */
1285
                                json_decref(root);
1286
                                continue;
1287
                                //~ g_snprintf(error_cause, 512, "Wrong state (not in a call?)");
1288
                                //~ goto error;
1289
                        }
1290
                        if(session->callee == NULL) {
1291
                                JANUS_LOG(LOG_ERR, "Wrong state (no callee?)\n");
1292
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1293
                                g_snprintf(error_cause, 512, "Wrong state (no callee?)");
1294
                                goto error;
1295
                        }
1296
                        session->status = janus_sip_call_status_closing;
1297
                        if(session->stack->s_nh_i == NULL) {
1298
                                JANUS_LOG(LOG_WARN, "NUA Handle for 200 OK still null??\n");
1299
                        }
1300
                        int response_code = 486;
1301
                        json_t *code_json = json_object_get(root, "code");
1302
                        if (code_json && json_is_integer(code_json))
1303
                                response_code = json_integer_value(code_json);
1304
                        if (response_code <= 399) {
1305
                                JANUS_LOG(LOG_WARN, "Invalid SIP response code specified, using 486 to decline call\n");
1306
                                response_code = 486;
1307
                        }
1308
                        nua_respond(session->stack->s_nh_i, response_code, sip_status_phrase(response_code), TAG_END());
1309
                        g_free(session->callee);
1310
                        session->callee = NULL;
1311
                        /* Notify the operation */
1312
                        result = json_object();
1313
                        json_object_set_new(result, "event", json_string("declining"));
1314
                        json_object_set_new(result, "code", json_integer(response_code));
1315
                } else if(!strcasecmp(request_text, "hangup")) {
1316
                        /* Hangup an ongoing call */
1317
                        if(!(session->status == janus_sip_call_status_inviting || session->status == janus_sip_call_status_incall)) {
1318
                                JANUS_LOG(LOG_ERR, "Wrong state (not in a call? status=%s)\n", janus_sip_call_status_string(session->status));
1319
                                /* Ignore */
1320
                                json_decref(root);
1321
                                continue;
1322
                                //~ g_snprintf(error_cause, 512, "Wrong state (not in a call?)");
1323
                                //~ goto error;
1324
                        }
1325
                        if(session->callee == NULL) {
1326
                                JANUS_LOG(LOG_ERR, "Wrong state (no callee?)\n");
1327
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1328
                                g_snprintf(error_cause, 512, "Wrong state (no callee?)");
1329
                                goto error;
1330
                        }
1331
                        session->status = janus_sip_call_status_closing;
1332
                        nua_bye(session->stack->s_nh_i, TAG_END());
1333
                        g_free(session->callee);
1334
                        session->callee = NULL;
1335
                        /* Notify the operation */
1336
                        result = json_object();
1337
                        json_object_set_new(result, "event", json_string("hangingup"));
1338
                } else {
1339
                        JANUS_LOG(LOG_ERR, "Unknown request (%s)\n", request_text);
1340
                        error_code = JANUS_SIP_ERROR_INVALID_REQUEST;
1341
                        g_snprintf(error_cause, 512, "Unknown request (%s)", request_text);
1342
                        goto error;
1343
                }
1344

    
1345
                json_decref(root);
1346
                /* Prepare JSON event */
1347
                json_t *event = json_object();
1348
                json_object_set_new(event, "sip", json_string("event"));
1349
                if(result != NULL)
1350
                        json_object_set_new(event, "result", result);
1351
                char *event_text = json_dumps(event, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1352
                json_decref(event);
1353
                JANUS_LOG(LOG_VERB, "Pushing event: %s\n", event_text);
1354
                int ret = gateway->push_event(msg->handle, &janus_sip_plugin, msg->transaction, event_text, sdp_type, sdp);
1355
                JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1356
                g_free(event_text);
1357
                if(sdp)
1358
                        g_free(sdp);
1359
                janus_sip_message_free(msg);
1360
                continue;
1361
                
1362
error:
1363
                {
1364
                        if(root != NULL)
1365
                                json_decref(root);
1366
                        /* Prepare JSON error event */
1367
                        json_t *event = json_object();
1368
                        json_object_set_new(event, "sip", json_string("event"));
1369
                        json_object_set_new(event, "error_code", json_integer(error_code));
1370
                        json_object_set_new(event, "error", json_string(error_cause));
1371
                        char *event_text = json_dumps(event, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1372
                        json_decref(event);
1373
                        JANUS_LOG(LOG_VERB, "Pushing event: %s\n", event_text);
1374
                        int ret = gateway->push_event(msg->handle, &janus_sip_plugin, msg->transaction, event_text, NULL, NULL);
1375
                        JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1376
                        g_free(event_text);
1377
                        janus_sip_message_free(msg);
1378
                }
1379
        }
1380
        g_free(error_cause);
1381
        JANUS_LOG(LOG_VERB, "Leaving SIP handler thread\n");
1382
        return NULL;
1383
}
1384

    
1385

    
1386
/* Sofia callbacks */
1387
void janus_sip_sofia_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[])
1388
{
1389
        janus_sip_session *session = (janus_sip_session *)magic;
1390
        ssip_t *ssip = session->stack;
1391
        switch (event) {
1392
        /* Status or Error Indications */
1393
                case nua_i_active:
1394
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1395
                        break;
1396
                case nua_i_error:
1397
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1398
                        break;
1399
                case nua_i_fork:
1400
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1401
                        break;
1402
                case nua_i_media_error:
1403
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1404
                        break;
1405
                case nua_i_subscription:
1406
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1407
                        break;
1408
                case nua_i_state:
1409
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1410
                        tagi_t const *ti = tl_find(tags, nutag_callstate);
1411
                        enum nua_callstate callstate = ti ? ti->t_value : -1;
1412
                        /* There are several call states, but we only care about the terminated state
1413
                         * in order to send the 'hangup' event.
1414
                         * http://sofia-sip.sourceforge.net/refdocs/nua/nua__tag_8h.html#a516dc237722dc8ca4f4aa3524b2b444b
1415
                         */
1416
                        if (callstate == nua_callstate_terminated) {
1417
                                session->status = janus_sip_call_status_idle;
1418
                                json_t *call = json_object();
1419
                                json_object_set_new(call, "sip", json_string("event"));
1420
                                json_t *calling = json_object();
1421
                                json_object_set_new(calling, "event", json_string("hangup"));
1422
                                json_object_set_new(calling, "code", json_integer(status));
1423
                                json_object_set_new(calling, "reason", json_string(phrase ? phrase : "???"));
1424
                                json_object_set_new(call, "result", calling);
1425
                                char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1426
                                json_decref(call);
1427
                                JANUS_LOG(LOG_VERB, "Pushing event: %s\n", call_text);
1428
                                int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call_text, NULL, NULL);
1429
                                JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1430
                                g_free(call_text);
1431
                                /* Get rid of any PeerConnection that may have been set up */
1432
                                if(session->transaction)
1433
                                        g_free(session->transaction);
1434
                                session->transaction = NULL;
1435
                                gateway->close_pc(session->handle);
1436
                        }
1437
                        break;
1438
                case nua_i_terminated:
1439
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1440
                        break;
1441
        /* SIP requests */
1442
                case nua_i_ack:
1443
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1444
                        break;
1445
                case nua_i_outbound:
1446
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1447
                        break;
1448
                case nua_i_bye: {
1449
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1450
                        break;
1451
                }
1452
                case nua_i_cancel: {
1453
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1454
                        break;
1455
                }
1456
                case nua_i_invite: {
1457
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1458
                        sdp_parser_t *parser = sdp_parse(ssip->s_home, sip->sip_payload->pl_data, sip->sip_payload->pl_len, 0);
1459
                        if(!sdp_session(parser)) {
1460
                                JANUS_LOG(LOG_ERR, "\tError parsing SDP!\n");
1461
                                nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
1462
                                break;
1463
                        }
1464
                        if(session->status >= janus_sip_call_status_inviting) {
1465
                                /* Busy */
1466
                                JANUS_LOG(LOG_VERB, "\tAlready in a call (busy, status=%s)\n", janus_sip_call_status_string(session->status));
1467
                                nua_respond(nh, 486, sip_status_phrase(486), TAG_END());
1468
                                break;
1469
                        }
1470
                        session->callee = g_strdup(url_as_string(session->stack->s_home, sip->sip_from->a_url));
1471
                        session->status = janus_sip_call_status_invited;
1472
                        /* Parse SDP */
1473
                        char *fixed_sdp = g_strdup(sip->sip_payload->pl_data);
1474
                        JANUS_LOG(LOG_VERB, "Someone is inviting us in a call:\n%s", sip->sip_payload->pl_data);
1475
                        sdp_session_t *sdp = sdp_session(parser);
1476
                        janus_sip_sdp_process(session, sdp);
1477
                        /* Send SDP to the browser */
1478
                        json_t *call = json_object();
1479
                        json_object_set_new(call, "sip", json_string("event"));
1480
                        json_t *calling = json_object();
1481
                        json_object_set_new(calling, "event", json_string("incomingcall"));
1482
                        json_object_set_new(calling, "username", json_string(session->callee));
1483
                        json_object_set_new(call, "result", calling);
1484
                        char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1485
                        json_decref(call);
1486
                        JANUS_LOG(LOG_VERB, "Pushing event to peer: %s\n", call_text);
1487
                        int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call_text, "offer", fixed_sdp);
1488
                        JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1489
                        g_free(call_text);
1490
                        /* Send a Ringing back */
1491
                        nua_respond(nh, 180, sip_status_phrase(180), TAG_END());
1492
                        session->stack->s_nh_i = nh;
1493
                        break;
1494
                }
1495
                case nua_i_options:
1496
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1497
                        /* FIXME Should we handle this message? for now we reply with a 405 Method Not Implemented */
1498
                        nua_respond(nh, 405, sip_status_phrase(405), TAG_END());
1499
                        break;
1500
        /* Responses */
1501
                case nua_r_get_params:
1502
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1503
                        break;
1504
                case nua_r_set_params:
1505
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1506
                        break;
1507
                case nua_r_notifier:
1508
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1509
                        break;
1510
                case nua_r_shutdown:
1511
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1512
                        if(status < 200 && !g_atomic_int_get(&stopping)) {
1513
                                /* shutdown in progress -> return */
1514
                                break;
1515
                        }
1516
                        /* end the event loop. su_root_run() will return */
1517
                        su_root_break(ssip->s_root);
1518
                        break;
1519
                case nua_r_terminate:
1520
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1521
                        break;
1522
        /* SIP responses */
1523
                case nua_r_bye:
1524
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1525
                        break;
1526
                case nua_r_cancel:
1527
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1528
                        break;
1529
                case nua_r_invite: {
1530
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1531
                        if(status < 200) {
1532
                                /* Not ready yet (FIXME May this be pranswer?? we don't handle it yet...) */
1533
                                break;
1534
                        } else if(status == 401 || status == 407) {
1535
                                char auth[256];
1536
                                const char* scheme;
1537
                                const char* realm;
1538
                                if(status == 401) {
1539
                                         /* Get scheme/realm from 401 error */
1540
                                        sip_www_authenticate_t const* www_auth = sip->sip_www_authenticate;
1541
                                        scheme = www_auth->au_scheme;
1542
                                        realm = msg_params_find(www_auth->au_params, "realm=");
1543
                                } else {
1544
                                         /* Get scheme/realm from 407 error, proxy-auth */
1545
                                        sip_proxy_authenticate_t const* proxy_auth = sip->sip_proxy_authenticate;
1546
                                        scheme = proxy_auth->au_scheme;
1547
                                        realm = msg_params_find(proxy_auth->au_params, "realm=");
1548
                                }
1549
                                memset(auth, 0, sizeof(auth));
1550
                                g_snprintf(auth, sizeof(auth), "%s%s:%s:%s:%s%s",
1551
                                        session->account.secret_type == janus_sip_secret_type_hashed ? "HA1+" : "",
1552
                                        scheme,
1553
                                        realm,
1554
                                        session->account.username ? session->account.username : "null",
1555
                                        session->account.secret_type == janus_sip_secret_type_hashed ? "HA1+" : "",
1556
                                        session->account.secret ? session->account.secret : "null");
1557
                                JANUS_LOG(LOG_VERB, "\t%s\n", auth);
1558
                                /* Authenticate */
1559
                                nua_authenticate(nh,
1560
                                        NUTAG_AUTH(auth),
1561
                                        TAG_END());
1562
                                break;
1563
                        } else if(status >= 400) {
1564
                                break;
1565
                        }
1566
                        ssip_t *ssip = session->stack;
1567
                        sdp_parser_t *parser = sdp_parse(ssip->s_home, sip->sip_payload->pl_data, sip->sip_payload->pl_len, 0);
1568
                        if(!sdp_session(parser)) {
1569
                                JANUS_LOG(LOG_ERR, "\tError parsing SDP!\n");
1570
                                nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
1571
                                break;
1572
                        }
1573
                        JANUS_LOG(LOG_VERB, "Peer accepted our call:\n%s", sip->sip_payload->pl_data);
1574
                        session->status = janus_sip_call_status_incall;
1575
                        char *fixed_sdp = g_strdup(sip->sip_payload->pl_data);
1576
                        sdp_session_t *sdp = sdp_session(parser);
1577
                        janus_sip_sdp_process(session, sdp);
1578
                        session->media.ready = 1;        /* FIXME Maybe we need a better way to signal this */
1579
                        GError *error = NULL;
1580
                        g_thread_try_new("janus rtp handler", janus_sip_relay_thread, session, &error);
1581
                        if(error != NULL) {
1582
                                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the RTP/RTCP thread...\n", error->code, error->message ? error->message : "??");
1583
                        }
1584
                        /* Send SDP to the browser */
1585
                        json_t *call = json_object();
1586
                        json_object_set_new(call, "sip", json_string("event"));
1587
                        json_t *calling = json_object();
1588
                        json_object_set_new(calling, "event", json_string("accepted"));
1589
                        json_object_set_new(calling, "username", json_string(session->callee));
1590
                        json_object_set_new(call, "result", calling);
1591
                        char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1592
                        json_decref(call);
1593
                        JANUS_LOG(LOG_VERB, "Pushing event to peer: %s\n", call_text);
1594
                        int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call_text, "answer", fixed_sdp);
1595
                        JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1596
                        g_free(call_text);
1597
                        break;
1598
                }
1599
                case nua_r_register: {
1600
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1601
                        if(status == 200) {
1602
                                if(session->account.registration_status < janus_sip_registration_status_registered)
1603
                                        session->account.registration_status = janus_sip_registration_status_registered;
1604
                                JANUS_LOG(LOG_VERB, "Successfully registered\n");
1605
                                /* Notify the browser */
1606
                                json_t *call = json_object();
1607
                                json_object_set_new(call, "sip", json_string("event"));
1608
                                json_t *calling = json_object();
1609
                                json_object_set_new(calling, "event", json_string("registered"));
1610
                                json_object_set_new(calling, "username", json_string(session->account.username));
1611
                                json_object_set_new(calling, "register_sent", json_string("true"));
1612
                                json_object_set_new(call, "result", calling);
1613
                                char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1614
                                json_decref(call);
1615
                                JANUS_LOG(LOG_VERB, "Pushing event: %s\n", call_text);
1616
                                int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call_text, NULL, NULL);
1617
                                JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1618
                                g_free(call_text);
1619
                        } else if(status == 401) {
1620
                                /* Get scheme/realm from 401 error */
1621
                                sip_www_authenticate_t const* www_auth = sip->sip_www_authenticate;
1622
                                char const* scheme = www_auth->au_scheme;
1623
                                const char* realm = msg_params_find(www_auth->au_params, "realm=");
1624
                                char auth[256];
1625
                                memset(auth, 0, sizeof(auth));
1626
                                g_snprintf(auth, sizeof(auth), "%s%s:%s:%s:%s%s",
1627
                                        session->account.secret_type == janus_sip_secret_type_hashed ? "HA1+" : "",
1628
                                        scheme,
1629
                                        realm,
1630
                                        session->account.username,
1631
                                        session->account.secret_type == janus_sip_secret_type_hashed ? "HA1+" : "",
1632
                                        session->account.secret);
1633
                                JANUS_LOG(LOG_VERB, "\t%s\n", auth);
1634
                                /* Authenticate */
1635
                                nua_authenticate(nh,
1636
                                        NUTAG_AUTH(auth),
1637
                                        TAG_END());
1638
                        } else if(status >= 400) {
1639
                                /* Authentication failed? */
1640
                                session->account.registration_status = janus_sip_registration_status_failed;
1641
                                /* Tell the browser... */
1642
                                json_t *event = json_object();
1643
                                json_object_set_new(event, "sip", json_string("event"));
1644
                                json_t *result = json_object();
1645
                                json_object_set_new(result, "event", json_string("registration_failed"));
1646
                                json_object_set_new(result, "code", json_integer(status));
1647
                                json_object_set_new(result, "reason", json_string(phrase ? phrase : ""));
1648
                                json_object_set_new(event, "result", result);
1649
                                char *event_text = json_dumps(event, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1650
                                json_decref(event);
1651
                                JANUS_LOG(LOG_VERB, "Pushing event: %s\n", event_text);
1652
                                int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, event_text, NULL, NULL);
1653
                                JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1654
                                g_free(event_text);
1655
                        }
1656
                        break;
1657
                }
1658
                default:
1659
                        /* unknown event -> print out error message */
1660
                        JANUS_LOG(LOG_ERR, "Unknown event %d (%s)\n", event, nua_event_name(event));
1661
                        break;
1662
        }
1663
}
1664

    
1665
void janus_sip_sdp_process(janus_sip_session *session, sdp_session_t *sdp) {
1666
        if(!session || !sdp)
1667
                return;
1668
        /* c= */
1669
        if(sdp->sdp_connection && sdp->sdp_connection->c_address) {
1670
                if(session->media.remote_ip != NULL)
1671
                        g_free(session->media.remote_ip);
1672
                session->media.remote_ip = g_strdup(sdp->sdp_connection->c_address);
1673
                JANUS_LOG(LOG_VERB, "  >> Media connection:\n");
1674
                JANUS_LOG(LOG_VERB, "       %s\n", session->media.remote_ip);
1675
        }
1676
        JANUS_LOG(LOG_VERB, "  >> Media lines:\n");
1677
        sdp_media_t *m = sdp->sdp_media;
1678
        while(m) {
1679
                if(m->m_type == sdp_media_audio) {
1680
                        JANUS_LOG(LOG_VERB, "       Audio: %lu\n", m->m_port);
1681
                        if(m->m_port) {
1682
                                session->media.has_audio = 1;
1683
                                session->media.remote_audio_rtp_port = m->m_port;
1684
                                session->media.remote_audio_rtcp_port = m->m_port+1;        /* FIXME We're assuming RTCP is on the next port */
1685
                        }
1686
                } else if(m->m_type == sdp_media_video) {
1687
                        JANUS_LOG(LOG_VERB, "       Video: %lu\n", m->m_port);
1688
                        if(m->m_port) {
1689
                                session->media.has_video = 1;
1690
                                session->media.remote_video_rtp_port = m->m_port;
1691
                                session->media.remote_video_rtcp_port = m->m_port+1;        /* FIXME We're assuming RTCP is on the next port */
1692
                        }
1693
                } else {
1694
                        JANUS_LOG(LOG_WARN, "       Unsupported media line (not audio/video)\n");
1695
                        m = m->m_next;
1696
                        continue;
1697
                }
1698
                JANUS_LOG(LOG_VERB, "       Media connections:\n");
1699
                if(m->m_connections) {
1700
                        sdp_connection_t *c = m->m_connections;
1701
                        while(c) {
1702
                                if(c->c_address) {
1703
                                        if(session->media.remote_ip != NULL)
1704
                                                g_free(session->media.remote_ip);
1705
                                        session->media.remote_ip = g_strdup(c->c_address);
1706
                                        JANUS_LOG(LOG_VERB, "         [%s]\n", session->media.remote_ip);
1707
                                }
1708
                                c = c->c_next;
1709
                        }
1710
                }
1711
                JANUS_LOG(LOG_VERB, "       Media RTP maps:\n");
1712
                sdp_rtpmap_t *r = m->m_rtpmaps;
1713
                while(r) {
1714
                        JANUS_LOG(LOG_VERB, "         [%u] %s\n", r->rm_pt, r->rm_encoding);
1715
                        r = r->rm_next;
1716
                }
1717
                JANUS_LOG(LOG_VERB, "       Media attributes:\n");
1718
                sdp_attribute_t *a = m->m_attributes;
1719
                while(a) {
1720
                        if(a->a_name) {
1721
                                if(!strcasecmp(a->a_name, "rtpmap")) {
1722
                                        JANUS_LOG(LOG_VERB, "         RTP Map:     %s\n", a->a_value);
1723
                                }
1724
                        }
1725
                        a = a->a_next;
1726
                }
1727
                m = m->m_next;
1728
        }
1729
}
1730

    
1731
/* Bind local RTP/RTCP sockets */
1732
static int janus_sip_allocate_local_ports(janus_sip_session *session) {
1733
        if(session == NULL) {
1734
                JANUS_LOG(LOG_ERR, "Invalid session\n");
1735
                return -1;
1736
        }
1737
        //~ /* Reset status */
1738
        //~ session->media.ready = 0;
1739
        //~ session->media.has_audio = 0;
1740
        //~ session->media.audio_rtp_fd = 0;
1741
        //~ session->media.audio_rtcp_fd= 0;
1742
        //~ session->media.local_audio_rtp_port = 0;
1743
        //~ session->media.remote_audio_rtp_port = 0;
1744
        //~ session->media.local_audio_rtcp_port = 0;
1745
        //~ session->media.remote_audio_rtcp_port = 0;
1746
        //~ session->media.has_video = 0;
1747
        //~ session->media.video_rtp_fd = 0;
1748
        //~ session->media.video_rtcp_fd= 0;
1749
        //~ session->media.local_video_rtp_port = 0;
1750
        //~ session->media.remote_video_rtp_port = 0;
1751
        //~ session->media.local_video_rtcp_port = 0;
1752
        //~ session->media.remote_video_rtcp_port = 0;
1753
        /* Start */
1754
        int attempts = 100;        /* FIXME Don't retry forever */
1755
        if(session->media.has_audio) {
1756
                JANUS_LOG(LOG_VERB, "Allocating audio ports:\n");
1757
                struct sockaddr_in audio_rtp_address, audio_rtcp_address;
1758
                int yes = 1;        /* For setsockopt() SO_REUSEADDR */
1759
                while(session->media.local_audio_rtp_port == 0 || session->media.local_audio_rtcp_port == 0) {
1760
                        if(attempts == 0)        /* Too many failures */
1761
                                return -1;
1762
                        if(session->media.audio_rtp_fd == 0) {
1763
                                yes = 1;
1764
                                session->media.audio_rtp_fd = socket(AF_INET, SOCK_DGRAM, 0);
1765
                                setsockopt(session->media.audio_rtp_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
1766
                        }
1767
                        if(session->media.audio_rtcp_fd == 0) {
1768
                                yes = 1;
1769
                                session->media.audio_rtcp_fd = socket(AF_INET, SOCK_DGRAM, 0);
1770
                                setsockopt(session->media.audio_rtcp_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
1771
                        }
1772
                        int rtp_port = g_random_int_range(10000, 60000);        /* FIXME Should this be configurable? */
1773
                        if(rtp_port % 2)
1774
                                rtp_port++;        /* Pick an even port for RTP */
1775
                        audio_rtp_address.sin_family = AF_INET;
1776
                        audio_rtp_address.sin_port = htons(rtp_port);
1777
                        inet_pton(AF_INET, local_ip, &audio_rtp_address.sin_addr.s_addr);
1778
                        if(bind(session->media.audio_rtp_fd, (struct sockaddr *)(&audio_rtp_address), sizeof(struct sockaddr)) < 0) {
1779
                                JANUS_LOG(LOG_ERR, "Bind failed for audio RTP (port %d), trying a different one...\n", rtp_port);
1780
                                attempts--;
1781
                                continue;
1782
                        }
1783
                        JANUS_LOG(LOG_VERB, "Audio RTP listener bound to port %d\n", rtp_port);
1784
                        int rtcp_port = rtp_port+1;
1785
                        audio_rtcp_address.sin_family = AF_INET;
1786
                        audio_rtcp_address.sin_port = htons(rtcp_port);
1787
                        inet_pton(AF_INET, local_ip, &audio_rtcp_address.sin_addr.s_addr);
1788
                        if(bind(session->media.audio_rtcp_fd, (struct sockaddr *)(&audio_rtcp_address), sizeof(struct sockaddr)) < 0) {
1789
                                JANUS_LOG(LOG_ERR, "Bind failed for audio RTCP (port %d), trying a different one...\n", rtcp_port);
1790
                                /* RTP socket is not valid anymore, reset it */
1791
                                close(session->media.audio_rtp_fd);
1792
                                session->media.audio_rtp_fd = 0;
1793
                                attempts--;
1794
                                continue;
1795
                        }
1796
                        JANUS_LOG(LOG_VERB, "Audio RTCP listener bound to port %d\n", rtcp_port);
1797
                        session->media.local_audio_rtp_port = rtp_port;
1798
                        session->media.local_audio_rtcp_port = rtcp_port;
1799
                }
1800
        }
1801
        if(session->media.has_video) {
1802
                JANUS_LOG(LOG_VERB, "Allocating video ports:\n");
1803
                struct sockaddr_in video_rtp_address, video_rtcp_address;
1804
                int yes = 1;        /* For setsockopt() SO_REUSEADDR */
1805
                while(session->media.local_video_rtp_port == 0 || session->media.local_video_rtcp_port == 0) {
1806
                        if(attempts == 0)        /* Too many failures */
1807
                                return -1;
1808
                        if(session->media.video_rtp_fd == 0) {
1809
                                yes = 1;
1810
                                session->media.video_rtp_fd = socket(AF_INET, SOCK_DGRAM, 0);
1811
                                setsockopt(session->media.video_rtp_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
1812
                        }
1813
                        if(session->media.video_rtcp_fd == 0) {
1814
                                yes = 1;
1815
                                session->media.video_rtcp_fd = socket(AF_INET, SOCK_DGRAM, 0);
1816
                                setsockopt(session->media.video_rtcp_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
1817
                        }
1818
                        int rtp_port = g_random_int_range(10000, 60000);        /* FIXME Should this be configurable? */
1819
                        if(rtp_port % 2)
1820
                                rtp_port++;        /* Pick an even port for RTP */
1821
                        video_rtp_address.sin_family = AF_INET;
1822
                        video_rtp_address.sin_port = htons(rtp_port);
1823
                        inet_pton(AF_INET, local_ip, &video_rtp_address.sin_addr.s_addr);
1824
                        if(bind(session->media.video_rtp_fd, (struct sockaddr *)(&video_rtp_address), sizeof(struct sockaddr)) < 0) {
1825
                                JANUS_LOG(LOG_ERR, "Bind failed for video RTP (port %d), trying a different one...\n", rtp_port);
1826
                                attempts--;
1827
                                continue;
1828
                        }
1829
                        JANUS_LOG(LOG_VERB, "Video RTP listener bound to port %d\n", rtp_port);
1830
                        int rtcp_port = rtp_port+1;
1831
                        video_rtcp_address.sin_family = AF_INET;
1832
                        video_rtcp_address.sin_port = htons(rtcp_port);
1833
                        inet_pton(AF_INET, local_ip, &video_rtcp_address.sin_addr.s_addr);
1834
                        if(bind(session->media.video_rtcp_fd, (struct sockaddr *)(&video_rtcp_address), sizeof(struct sockaddr)) < 0) {
1835
                                JANUS_LOG(LOG_ERR, "Bind failed for video RTCP (port %d), trying a different one...\n", rtcp_port);
1836
                                /* RTP socket is not valid anymore, reset it */
1837
                                close(session->media.video_rtp_fd);
1838
                                session->media.video_rtp_fd = 0;
1839
                                attempts--;
1840
                                continue;
1841
                        }
1842
                        JANUS_LOG(LOG_VERB, "Video RTCP listener bound to port %d\n", rtcp_port);
1843
                        session->media.local_video_rtp_port = rtp_port;
1844
                        session->media.local_video_rtcp_port = rtcp_port;
1845
                }
1846
        }
1847
        return 0;
1848
}
1849

    
1850
/* Thread to relay RTP/RTCP frames coming from the SIP peer */
1851
static void *janus_sip_relay_thread(void *data) {
1852
        janus_sip_session *session = (janus_sip_session *)data;
1853
        if(!session || !session->account.username || !session->callee) {
1854
                g_thread_unref(g_thread_self());
1855
                return NULL;
1856
        }
1857
        JANUS_LOG(LOG_VERB, "Starting relay thread (%s <--> %s)\n", session->account.username, session->callee);
1858

    
1859
        gboolean have_server_ip = TRUE;
1860
        struct sockaddr_in server_addr;
1861
        memset(&server_addr, 0, sizeof(server_addr));
1862
        server_addr.sin_family = AF_INET;
1863
        if((inet_aton(session->media.remote_ip, &server_addr.sin_addr)) <= 0) {        /* Not a numeric IP... */
1864
                struct hostent *host = gethostbyname(session->media.remote_ip);        /* ...resolve name */
1865
                if(!host) {
1866
                        JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't get host (%s)\n", session->account.username, session->media.remote_ip);
1867
                        have_server_ip = FALSE;
1868
                } else {
1869
                        server_addr.sin_addr = *(struct in_addr *)host->h_addr_list;
1870
                }
1871
        }
1872

    
1873
        /* Connect peers (FIXME This pretty much sucks right now) */
1874
        if(have_server_ip && session->media.remote_audio_rtp_port) {
1875
                server_addr.sin_port = htons(session->media.remote_audio_rtp_port);
1876
                if(connect(session->media.audio_rtp_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
1877
                        JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't connect audio RTP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_audio_rtp_port);
1878
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
1879
                }
1880
        }
1881
        if(have_server_ip && session->media.remote_audio_rtcp_port) {
1882
                server_addr.sin_port = htons(session->media.remote_audio_rtcp_port);
1883
                if(connect(session->media.audio_rtcp_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
1884
                        JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't connect audio RTCP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_audio_rtcp_port);
1885
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
1886
                }
1887
        }
1888
        if(have_server_ip && session->media.remote_video_rtp_port) {
1889
                server_addr.sin_port = htons(session->media.remote_video_rtp_port);
1890
                if(connect(session->media.video_rtp_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
1891
                        JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't connect video RTP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_video_rtp_port);
1892
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
1893
                }
1894
        }
1895
        if(have_server_ip && session->media.remote_video_rtcp_port) {
1896
                server_addr.sin_port = htons(session->media.remote_video_rtcp_port);
1897
                if(connect(session->media.video_rtcp_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
1898
                        JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't connect video RTCP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_video_rtcp_port);
1899
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
1900
                }
1901
        }
1902

    
1903
        if(!session->callee) {
1904
                JANUS_LOG(LOG_VERB, "[SIP-%s] Leaving thread, no callee...\n", session->account.username);
1905
                g_thread_unref(g_thread_self());
1906
                return NULL; 
1907
        }
1908
        /* Loop */
1909
        socklen_t addrlen;
1910
        struct sockaddr_in remote;
1911
        int resfd = 0, bytes = 0;
1912
        struct pollfd fds[4];
1913
        char buffer[1500];
1914
        memset(buffer, 0, 1500);
1915
        while(session != NULL && !session->destroyed &&
1916
                        session->status > janus_sip_call_status_idle &&
1917
                        session->status < janus_sip_call_status_closing) {        /* FIXME We need a per-call watchdog as well */
1918
                /* Wait for some data */
1919
                fds[0].fd = 0;
1920
                fds[0].events = 0;
1921
                fds[0].revents = 0;
1922
                if(session->media.audio_rtp_fd > 0) {
1923
                        fds[0].fd = session->media.audio_rtp_fd;
1924
                        fds[0].events = POLLIN;
1925
                }
1926
                fds[1].fd = 0;
1927
                fds[1].events = 0;
1928
                fds[1].revents = 0;
1929
                if(session->media.audio_rtcp_fd > 0) {
1930
                        fds[1].fd = session->media.audio_rtcp_fd;
1931
                        fds[1].events = POLLIN;
1932
                }
1933
                fds[2].fd = 0;
1934
                fds[2].events = 0;
1935
                fds[2].revents = 0;
1936
                if(session->media.video_rtp_fd > 0) {
1937
                        fds[2].fd = session->media.video_rtp_fd;
1938
                        fds[2].events = POLLIN;
1939
                }
1940
                fds[3].fd = 0;
1941
                fds[3].events = 0;
1942
                fds[3].revents = 0;
1943
                if(session->media.video_rtcp_fd > 0) {
1944
                        fds[3].fd = session->media.video_rtcp_fd;
1945
                        fds[3].events = POLLIN;
1946
                }
1947
                resfd = poll(fds, 4, 1000);
1948
                if(resfd < 0) {
1949
                        JANUS_LOG(LOG_ERR, "[SIP-%s] Error polling...\n", session->account.username);
1950
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
1951
                        break;
1952
                } else if(resfd == 0) {
1953
                        /* No data, keep going */
1954
                        continue;
1955
                }
1956
                if(session == NULL || session->destroyed ||
1957
                                session->status <= janus_sip_call_status_idle ||
1958
                                session->status >= janus_sip_call_status_closing)
1959
                        break;
1960
                if(session->media.audio_rtp_fd && (fds[0].revents & POLLIN)) {
1961
                        /* Got something audio (RTP) */
1962
                        fds[0].revents = 0;
1963
                        addrlen = sizeof(remote);
1964
                        bytes = recvfrom(session->media.audio_rtp_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
1965
                        //~ JANUS_LOG(LOG_VERB, "************************\nGot %d bytes on the audio RTP channel...\n", bytes);
1966
                        //~ rtp_header_t *rtp = (rtp_header_t *)buffer;
1967
                        //~ JANUS_LOG(LOG_VERB, " ... parsed RTP packet (ssrc=%u, pt=%u, seq=%u, ts=%u)...\n",
1968
                                //~ ntohl(rtp->ssrc), rtp->type, ntohs(rtp->seq_number), ntohl(rtp->timestamp));
1969
                        if(session->media.audio_ssrc_peer == 0) {
1970
                                rtp_header *header = (rtp_header *)buffer;
1971
                                session->media.audio_ssrc_peer = ntohl(header->ssrc);
1972
                                JANUS_LOG(LOG_VERB, "Got SIP peer audio SSRC: %"SCNu32"\n", session->media.audio_ssrc_peer);
1973
                        }
1974
                        /* Relay to browser */
1975
                        gateway->relay_rtp(session->handle, 0, buffer, bytes);
1976
                        continue;
1977
                }
1978
                if(session->media.audio_rtcp_fd && (fds[1].revents & POLLIN)) {
1979
                        /* Got something audio (RTCP) */
1980
                        fds[1].revents = 0;
1981
                        addrlen = sizeof(remote);
1982
                        bytes = recvfrom(session->media.audio_rtcp_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
1983
                        //~ JANUS_LOG(LOG_VERB, "************************\nGot %d bytes on the audio RTCP channel...\n", bytes);
1984
                        //~ rtp_header_t *rtp = (rtp_header_t *)buffer;
1985
                        //~ JANUS_LOG(LOG_VERB, " ... parsed RTP packet (ssrc=%u, pt=%u, seq=%u, ts=%u)...\n",
1986
                                //~ ntohl(rtp->ssrc), rtp->type, ntohs(rtp->seq_number), ntohl(rtp->timestamp));
1987
                        /* Relay to browser */
1988
                        gateway->relay_rtcp(session->handle, 0, buffer, bytes);
1989
                        continue;
1990
                }
1991
                if(session->media.video_rtp_fd && (fds[2].revents & POLLIN)) {
1992
                        /* Got something video (RTP) */
1993
                        fds[2].revents = 0;
1994
                        addrlen = sizeof(remote);
1995
                        bytes = recvfrom(session->media.video_rtp_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
1996
                        //~ JANUS_LOG(LOG_VERB, "************************\nGot %d bytes on the video RTP channel...\n", bytes);
1997
                        //~ rtp_header_t *rtp = (rtp_header_t *)buffer;
1998
                        //~ JANUS_LOG(LOG_VERB, " ... parsed RTP packet (ssrc=%u, pt=%u, seq=%u, ts=%u)...\n",
1999
                                //~ ntohl(rtp->ssrc), rtp->type, ntohs(rtp->seq_number), ntohl(rtp->timestamp));
2000
                        if(session->media.video_ssrc_peer == 0) {
2001
                                rtp_header *header = (rtp_header *)buffer;
2002
                                session->media.video_ssrc_peer = ntohl(header->ssrc);
2003
                                JANUS_LOG(LOG_VERB, "Got SIP peer video SSRC: %"SCNu32"\n", session->media.video_ssrc_peer);
2004
                        }
2005
                        /* Relay to browser */
2006
                        gateway->relay_rtp(session->handle, 1, buffer, bytes);
2007
                        continue;
2008
                }
2009
                if(session->media.video_rtcp_fd && (fds[3].revents & POLLIN)) {
2010
                        /* Got something video (RTCP) */
2011
                        fds[3].revents = 0;
2012
                        addrlen = sizeof(remote);
2013
                        bytes = recvfrom(session->media.video_rtcp_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
2014
                        //~ JANUS_LOG(LOG_VERB, "************************\nGot %d bytes on the video RTCP channel...\n", bytes);
2015
                        //~ rtp_header_t *rtp = (rtp_header_t *)buffer;
2016
                        //~ JANUS_LOG(LOG_VERB, " ... parsed RTP packet (ssrc=%u, pt=%u, seq=%u, ts=%u)...\n",
2017
                                //~ ntohl(rtp->ssrc), rtp->type, ntohs(rtp->seq_number), ntohl(rtp->timestamp));
2018
                        /* Relay to browser */
2019
                        gateway->relay_rtcp(session->handle, 1, buffer, bytes);
2020
                        continue;
2021
                }
2022
        }
2023
        JANUS_LOG(LOG_VERB, "Leaving SIP relay thread\n");
2024
        g_thread_unref(g_thread_self());
2025
        return NULL;
2026
}
2027

    
2028

    
2029
/* Sofia Event thread */
2030
gpointer janus_sip_sofia_thread(gpointer user_data) {
2031
        janus_sip_session *session = (janus_sip_session *)user_data;
2032
        if(session == NULL || session->account.username == NULL || session->stack == NULL) {
2033
                g_thread_unref(g_thread_self());
2034
                return NULL;
2035
        }
2036
        JANUS_LOG(LOG_VERB, "Joining sofia loop thread (%s)...\n", session->account.username);
2037
        session->stack->s_root = su_root_create(session->stack);
2038
        JANUS_LOG(LOG_VERB, "Setting up sofia stack (sip:%s@%s)\n", session->account.username, local_ip);
2039
        char sip_url[128];
2040
        char sips_url[128];
2041
        char *ipv6;
2042
        ipv6 = strstr(local_ip, ":");
2043
        g_snprintf(sip_url, sizeof(sip_url), "sip:%s%s%s:*", ipv6 ? "[" : "", local_ip, ipv6 ? "]" : "");
2044
        g_snprintf(sips_url, sizeof(sips_url), "sips:%s%s%s:*", ipv6 ? "[" : "", local_ip, ipv6 ? "]" : "");
2045
        char outbound_options[256] = "use-rport no-validate";
2046
        if(keepalive_interval > 0)
2047
                g_strlcat(outbound_options, " options-keepalive", sizeof(outbound_options));
2048
        if(!behind_nat)
2049
                g_strlcat(outbound_options, " no-natify", sizeof(outbound_options));
2050
        session->stack->s_nua = nua_create(session->stack->s_root,
2051
                                janus_sip_sofia_callback,
2052
                                session,
2053
                                SIPTAG_ALLOW_STR("INVITE, ACK, BYE, CANCEL, OPTIONS"),
2054
                                NUTAG_M_USERNAME(session->account.username),
2055
                                NUTAG_URL(sip_url),
2056
                                NUTAG_SIPS_URL(sips_url),
2057
                                SIPTAG_USER_AGENT_STR(user_agent),
2058
                                NUTAG_KEEPALIVE(keepalive_interval * 1000),        /* Sofia expects it in milliseconds */
2059
                                NUTAG_OUTBOUND(outbound_options),
2060
                                SIPTAG_SUPPORTED(NULL),
2061
                                TAG_NULL());
2062
        su_root_run(session->stack->s_root);
2063
        /* When we get here, we're done */
2064
        nua_destroy(session->stack->s_nua);
2065
        su_root_destroy(session->stack->s_root);
2066
        session->stack->s_root = NULL;
2067
        su_home_deinit(session->stack->s_home);
2068
        su_deinit();
2069
        //~ stop = 1;
2070
        JANUS_LOG(LOG_VERB, "Leaving sofia loop thread...\n");
2071
        g_thread_unref(g_thread_self());
2072
        return NULL;
2073
}