Statistics
| Branch: | Revision:

janus-gateway / plugins / janus_sip.c @ 77d8e4c0

History | View | Annotate | Download (81.9 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 <ifaddrs.h>
55
#include <net/if.h>
56

    
57
#include <jansson.h>
58

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

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

    
74

    
75
/* Plugin information */
76
#define JANUS_SIP_VERSION                        5
77
#define JANUS_SIP_VERSION_STRING        "0.0.5"
78
#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."
79
#define JANUS_SIP_NAME                                "JANUS SIP plugin"
80
#define JANUS_SIP_AUTHOR                        "Meetecho s.r.l."
81
#define JANUS_SIP_PACKAGE                        "janus.plugin.sip"
82

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

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

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

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

    
133

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

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

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

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

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

    
163
        msg->handle = NULL;
164

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

    
174
        g_free(msg);
175
}
176

    
177

    
178
typedef enum janus_sip_status {
179
        janus_sip_status_failed = -1,
180
        janus_sip_status_unregistered = 0,
181
        janus_sip_status_registering,
182
        janus_sip_status_registered,
183
        janus_sip_status_inviting,
184
        janus_sip_status_invited,
185
        janus_sip_status_incall,
186
        janus_sip_status_closing,
187
        janus_sip_status_unregistering,
188
} janus_sip_status;
189
const char *janus_sip_status_string(janus_sip_status status);
190
const char *janus_sip_status_string(janus_sip_status status) {
191
        switch(status) {
192
                case janus_sip_status_failed:
193
                        return "failed";
194
                case janus_sip_status_unregistered:
195
                        return "unregistered";
196
                case janus_sip_status_registering:
197
                        return "registering";
198
                case janus_sip_status_registered:
199
                        return "registered";
200
                case janus_sip_status_inviting:
201
                        return "inviting";
202
                case janus_sip_status_invited:
203
                        return "invited";
204
                case janus_sip_status_incall:
205
                        return "incall";
206
                case janus_sip_status_closing:
207
                        return "closing";
208
                case janus_sip_status_unregistering:
209
                        return "unregistering";
210
                default:
211
                        break;
212
        }
213
        return "unknown";
214
}
215

    
216

    
217
/* Sofia stuff */
218
typedef struct ssip_s ssip_t;
219
typedef struct ssip_oper_s ssip_oper_t;
220

    
221
typedef struct janus_sip_account {
222
        char *identity;
223
        char *username;
224
        char *secret;
225
        int sip_port;
226
        char *proxy;
227
} janus_sip_account;
228

    
229
typedef struct janus_sip_media {
230
        char *remote_ip;
231
        int ready:1;
232
        int has_audio:1;
233
        int audio_rtp_fd, audio_rtcp_fd;
234
        int local_audio_rtp_port, remote_audio_rtp_port;
235
        int local_audio_rtcp_port, remote_audio_rtcp_port;
236
        guint32 audio_ssrc, audio_ssrc_peer;
237
        int has_video:1;
238
        int video_rtp_fd, video_rtcp_fd;
239
        int local_video_rtp_port, remote_video_rtp_port;
240
        int local_video_rtcp_port, remote_video_rtcp_port;
241
        guint32 video_ssrc, video_ssrc_peer;
242
} janus_sip_media;
243

    
244
typedef struct janus_sip_session {
245
        janus_plugin_session *handle;
246
        ssip_t *stack;
247
        janus_sip_account account;
248
        janus_sip_status status;
249
        janus_sip_media media;
250
        char *transaction;
251
        char *callee;
252
        guint64 destroyed;        /* Time at which this session was marked as destroyed */
253
        janus_mutex mutex;
254
} janus_sip_session;
255
static GHashTable *sessions;
256
static GList *old_sessions;
257
static janus_mutex sessions_mutex;
258

    
259

    
260
#undef SU_ROOT_MAGIC_T
261
#define SU_ROOT_MAGIC_T        ssip_t
262
#undef NUA_MAGIC_T
263
#define NUA_MAGIC_T                ssip_t
264
#undef NUA_HMAGIC_T
265
#define NUA_HMAGIC_T        ssip_oper_t
266

    
267
struct ssip_s {
268
        su_home_t s_home[1];
269
        su_root_t *s_root;
270
        nua_t *s_nua;
271
        nua_handle_t *s_nh_r, *s_nh_i;
272
        janus_sip_session *session;
273
};
274

    
275

    
276
/* Sofia Event thread */
277
gpointer janus_sip_sofia_thread(gpointer user_data);
278
/* Sofia callbacks */
279
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[]);
280
/* SDP parsing */
281
void janus_sip_sdp_process(janus_sip_session *session, sdp_session_t *sdp);
282
/* Media */
283
static int janus_sip_allocate_local_ports(janus_sip_session *session);
284
static void *janus_sip_relay_thread(void *data);
285

    
286

    
287
/* URI parsing utilies */
288

    
289
#define JANUS_SIP_URI_MAXLEN        1024
290
typedef struct {
291
        char data[JANUS_SIP_URI_MAXLEN];
292
        url_t url[1];
293
} janus_sip_uri_t;
294

    
295
/* Parses a SIP URI (SIPS is not supported), returns 0 on success, -1 otherwise */
296
static int janus_sip_parse_uri(janus_sip_uri_t *sip_uri, const char *data) {
297
        g_strlcpy(sip_uri->data, data, JANUS_SIP_URI_MAXLEN);
298
        if (url_d(sip_uri->url, sip_uri->data) < 0 || sip_uri->url->url_type != url_sip)
299
                return -1;
300
        return 0;
301
}
302

    
303
/* Similar to th above function, but it also accepts SIPS URIs */
304
static int janus_sip_parse_proxy_uri(janus_sip_uri_t *sip_uri, const char *data) {
305
        g_strlcpy(sip_uri->data, data, JANUS_SIP_URI_MAXLEN);
306
        if (url_d(sip_uri->url, sip_uri->data) < 0 || (sip_uri->url->url_type != url_sip && sip_uri->url->url_type != url_sips))
307
                return -1;
308
        return 0;
309
}
310

    
311
/* Error codes */
312
#define JANUS_SIP_ERROR_UNKNOWN_ERROR                499
313
#define JANUS_SIP_ERROR_NO_MESSAGE                        440
314
#define JANUS_SIP_ERROR_INVALID_JSON                441
315
#define JANUS_SIP_ERROR_INVALID_REQUEST                442
316
#define JANUS_SIP_ERROR_MISSING_ELEMENT                443
317
#define JANUS_SIP_ERROR_INVALID_ELEMENT                444
318
#define JANUS_SIP_ERROR_ALREADY_REGISTERED        445
319
#define JANUS_SIP_ERROR_INVALID_ADDRESS                446
320
#define JANUS_SIP_ERROR_WRONG_STATE                        447
321
#define JANUS_SIP_ERROR_MISSING_SDP                        448
322
#define JANUS_SIP_ERROR_LIBSOFIA_ERROR                449
323
#define JANUS_SIP_ERROR_IO_ERROR                        450
324

    
325

    
326
/* SIP watchdog/garbage collector (sort of) */
327
void *janus_sip_watchdog(void *data);
328
void *janus_sip_watchdog(void *data) {
329
        JANUS_LOG(LOG_INFO, "SIP watchdog started\n");
330
        gint64 now = 0;
331
        while(g_atomic_int_get(&initialized) && !g_atomic_int_get(&stopping)) {
332
                janus_mutex_lock(&sessions_mutex);
333
                /* Iterate on all the sessions */
334
                now = janus_get_monotonic_time();
335
                if(old_sessions != NULL) {
336
                        GList *sl = old_sessions;
337
                        JANUS_LOG(LOG_HUGE, "Checking %d old SIP sessions...\n", g_list_length(old_sessions));
338
                        while(sl) {
339
                                janus_sip_session *session = (janus_sip_session *)sl->data;
340
                                if(!session) {
341
                                        sl = sl->next;
342
                                        continue;
343
                                }
344
                                if(now-session->destroyed >= 5*G_USEC_PER_SEC) {
345
                                        /* We're lazy and actually get rid of the stuff only after a few seconds */
346
                                        JANUS_LOG(LOG_VERB, "Freeing old SIP session\n");
347
                                        GList *rm = sl->next;
348
                                        old_sessions = g_list_delete_link(old_sessions, sl);
349
                                        sl = rm;
350
                                        session->handle = NULL;
351
                                        g_free(session);
352
                                        session = NULL;
353
                                        continue;
354
                                }
355
                                sl = sl->next;
356
                        }
357
                }
358
                janus_mutex_unlock(&sessions_mutex);
359
                g_usleep(500000);
360
        }
361
        JANUS_LOG(LOG_INFO, "SIP watchdog stopped\n");
362
        return NULL;
363
}
364

    
365

    
366
static void janus_sip_detect_local_ip(void) {
367
        JANUS_LOG(LOG_VERB, "Autodetecting local IP...\n");
368

    
369
        struct sockaddr_in addr;
370
        socklen_t len;
371
        int fd = socket(AF_INET, SOCK_DGRAM, 0);
372
        if (fd == -1)
373
                goto error;
374
        addr.sin_family = AF_INET;
375
        addr.sin_port = htons(1);
376
        inet_pton(AF_INET, "1.2.3.4", &addr.sin_addr.s_addr);
377
        if (connect(fd, (const struct sockaddr*) &addr, sizeof(addr)) < 0)
378
                goto error;
379
        len = sizeof(addr);
380
        if (getsockname(fd, (struct sockaddr*) &addr, &len) < 0)
381
                goto error;
382
        getnameinfo((const struct sockaddr*) &addr, sizeof(addr),
383
                        local_ip, sizeof(local_ip),
384
                        NULL, 0, NI_NUMERICHOST);
385
        return;
386

    
387
error:
388
        if (fd != -1)
389
                close(fd);
390
        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");
391
        g_strlcpy(local_ip, "127.0.0.1", sizeof(local_ip));
392
}
393

    
394

    
395
/* Plugin implementation */
396
int janus_sip_init(janus_callbacks *callback, const char *config_path) {
397
        if(g_atomic_int_get(&stopping)) {
398
                /* Still stopping from before */
399
                return -1;
400
        }
401
        if(callback == NULL || config_path == NULL) {
402
                /* Invalid arguments */
403
                return -1;
404
        }
405

    
406
        /* Read configuration */
407
        char filename[255];
408
        g_snprintf(filename, 255, "%s/%s.cfg", config_path, JANUS_SIP_PACKAGE);
409
        JANUS_LOG(LOG_VERB, "Configuration file: %s\n", filename);
410
        janus_config *config = janus_config_parse(filename);
411
        if(config != NULL)
412
                janus_config_print(config);
413

    
414
        gboolean local_ip_set = FALSE;
415
        janus_config_item *item = janus_config_get_item_drilldown(config, "general", "local_ip");
416
        if(item && item->value) {
417
                /* FIXME: IPv6 is not supported yet */
418
                struct in_addr addr;
419
                if (inet_pton(AF_INET, item->value, &addr) != 1) {
420
                        JANUS_LOG(LOG_WARN, "Invalid local IP specified: %s, guessing the default...\n", item->value);
421
                } else {
422
                        /* Verify that we can actually bind to that address */
423
                        struct sockaddr_in addr;
424
                        int r;
425
                        int fd = socket(AF_INET, SOCK_DGRAM, 0);
426
                        if (fd == -1)
427
                                JANUS_LOG(LOG_WARN, "Error creating test socket, falling back to detecting IP address...\n");
428
                        addr.sin_family = AF_INET;
429
                        addr.sin_port = 0;
430
                        inet_pton(AF_INET, item->value, &addr.sin_addr.s_addr);
431
                        r = bind(fd, (const struct sockaddr*) &addr, sizeof(addr));
432
                        close(fd);
433
                        if (r < 0) {
434
                                JANUS_LOG(LOG_WARN, "Error setting local IP address to %s, falling back to detecting IP address...\n", item->value);
435
                        } else {
436
                                g_strlcpy(local_ip, item->value, sizeof(local_ip));
437
                                local_ip_set = TRUE;
438
                        }
439
                }
440
        }
441
        if (!local_ip_set)
442
                janus_sip_detect_local_ip();
443
        JANUS_LOG(LOG_VERB, "Local IP set to %s\n", local_ip);
444

    
445
        item = janus_config_get_item_drilldown(config, "general", "keepalive_interval");
446
        if(item && item->value)
447
                keepalive_interval = atoi(item->value);
448
        JANUS_LOG(LOG_VERB, "SIP keep-alive interval set to %d seconds\n", keepalive_interval);
449

    
450
        item = janus_config_get_item_drilldown(config, "general", "register_ttl");
451
        if(item && item->value)
452
                register_ttl = atoi(item->value);
453
        JANUS_LOG(LOG_VERB, "SIP registration TTL set to %d seconds\n", register_ttl);
454

    
455
        item = janus_config_get_item_drilldown(config, "general", "behind_nat");
456
        if(item && item->value)
457
                behind_nat = janus_is_true(item->value);
458

    
459
        item = janus_config_get_item_drilldown(config, "general", "user_agent");
460
        if(item && item->value)
461
                user_agent = g_strdup(item->value);
462
        else
463
                user_agent = g_strdup("Janus WebRTC Gateway SIP Plugin "JANUS_SIP_VERSION_STRING);
464
        JANUS_LOG(LOG_VERB, "SIP User-Agent set to %s\n", user_agent);
465

    
466
        /* This plugin actually has nothing to configure... */
467
        janus_config_destroy(config);
468
        config = NULL;
469

    
470
        /* Setup sofia */
471
        su_init();
472

    
473
        sessions = g_hash_table_new(NULL, NULL);
474
        janus_mutex_init(&sessions_mutex);
475
        messages = g_async_queue_new_full((GDestroyNotify) janus_sip_message_free);
476
        /* This is the callback we'll need to invoke to contact the gateway */
477
        gateway = callback;
478

    
479
        g_atomic_int_set(&initialized, 1);
480

    
481
        GError *error = NULL;
482
        /* Start the sessions watchdog */
483
        watchdog = g_thread_try_new("etest watchdog", &janus_sip_watchdog, NULL, &error);
484
        if(error != NULL) {
485
                g_atomic_int_set(&initialized, 0);
486
                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the SIP watchdog thread...\n", error->code, error->message ? error->message : "??");
487
                return -1;
488
        }
489
        /* Launch the thread that will handle incoming messages */
490
        handler_thread = g_thread_try_new("janus sip handler", janus_sip_handler, NULL, &error);
491
        if(error != NULL) {
492
                g_atomic_int_set(&initialized, 0);
493
                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the SIP handler thread...\n", error->code, error->message ? error->message : "??");
494
                return -1;
495
        }
496
        JANUS_LOG(LOG_INFO, "%s initialized!\n", JANUS_SIP_NAME);
497
        return 0;
498
}
499

    
500
void janus_sip_destroy(void) {
501
        if(!g_atomic_int_get(&initialized))
502
                return;
503
        g_atomic_int_set(&stopping, 1);
504
        if(handler_thread != NULL) {
505
                g_thread_join(handler_thread);
506
                handler_thread = NULL;
507
        }
508
        if(watchdog != NULL) {
509
                g_thread_join(watchdog);
510
                watchdog = NULL;
511
        }
512
        /* FIXME We should destroy the sessions cleanly */
513
        janus_mutex_lock(&sessions_mutex);
514
        g_hash_table_destroy(sessions);
515
        janus_mutex_unlock(&sessions_mutex);
516
        g_async_queue_unref(messages);
517
        messages = NULL;
518
        sessions = NULL;
519
        g_atomic_int_set(&initialized, 0);
520
        g_atomic_int_set(&stopping, 0);
521
        JANUS_LOG(LOG_INFO, "%s destroyed!\n", JANUS_SIP_NAME);
522
}
523

    
524
int janus_sip_get_api_compatibility(void) {
525
        /* Important! This is what your plugin MUST always return: don't lie here or bad things will happen */
526
        return JANUS_PLUGIN_API_VERSION;
527
}
528

    
529
int janus_sip_get_version(void) {
530
        return JANUS_SIP_VERSION;
531
}
532

    
533
const char *janus_sip_get_version_string(void) {
534
        return JANUS_SIP_VERSION_STRING;
535
}
536

    
537
const char *janus_sip_get_description(void) {
538
        return JANUS_SIP_DESCRIPTION;
539
}
540

    
541
const char *janus_sip_get_name(void) {
542
        return JANUS_SIP_NAME;
543
}
544

    
545
const char *janus_sip_get_author(void) {
546
        return JANUS_SIP_AUTHOR;
547
}
548

    
549
const char *janus_sip_get_package(void) {
550
        return JANUS_SIP_PACKAGE;
551
}
552

    
553
void janus_sip_create_session(janus_plugin_session *handle, int *error) {
554
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
555
                *error = -1;
556
                return;
557
        }        
558
        janus_sip_session *session = (janus_sip_session *)calloc(1, sizeof(janus_sip_session));
559
        if(session == NULL) {
560
                JANUS_LOG(LOG_FATAL, "Memory error!\n");
561
                *error = -2;
562
                return;
563
        }
564
        session->handle = handle;
565
        session->account.identity = NULL;
566
        session->account.username = NULL;
567
        session->account.secret = NULL;
568
        session->account.sip_port = 0;
569
        session->account.proxy = NULL;
570
        session->stack = calloc(1, sizeof(ssip_t));
571
        if(session->stack == NULL) {
572
                JANUS_LOG(LOG_FATAL, "Memory error!\n");
573
                *error = -2;
574
                g_free(session);
575
                return;
576
        }
577
        session->stack->session = session;
578
        session->stack->s_nua = NULL;
579
        session->stack->s_nh_r = NULL;
580
        session->stack->s_nh_i = NULL;
581
        session->stack->s_root = NULL;
582
        session->transaction = NULL;
583
        session->callee = NULL;
584
        session->media.remote_ip = NULL;
585
        session->media.ready = 0;
586
        session->media.has_audio = 0;
587
        session->media.audio_rtp_fd = 0;
588
        session->media.audio_rtcp_fd= 0;
589
        session->media.local_audio_rtp_port = 0;
590
        session->media.remote_audio_rtp_port = 0;
591
        session->media.local_audio_rtcp_port = 0;
592
        session->media.remote_audio_rtcp_port = 0;
593
        session->media.audio_ssrc = 0;
594
        session->media.audio_ssrc_peer = 0;
595
        session->media.has_video = 0;
596
        session->media.video_rtp_fd = 0;
597
        session->media.video_rtcp_fd= 0;
598
        session->media.local_video_rtp_port = 0;
599
        session->media.remote_video_rtp_port = 0;
600
        session->media.local_video_rtcp_port = 0;
601
        session->media.remote_video_rtcp_port = 0;
602
        session->media.video_ssrc = 0;
603
        session->media.video_ssrc_peer = 0;
604
        session->destroyed = 0;
605
        su_home_init(session->stack->s_home);
606
        janus_mutex_init(&session->mutex);
607
        handle->plugin_handle = session;
608

    
609
        janus_mutex_lock(&sessions_mutex);
610
        g_hash_table_insert(sessions, handle, session);
611
        janus_mutex_unlock(&sessions_mutex);
612

    
613
        return;
614
}
615

    
616
void janus_sip_destroy_session(janus_plugin_session *handle, int *error) {
617
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
618
                *error = -1;
619
                return;
620
        }        
621
        janus_sip_session *session = (janus_sip_session *)handle->plugin_handle; 
622
        if(!session) {
623
                JANUS_LOG(LOG_ERR, "No SIP session associated with this handle...\n");
624
                *error = -2;
625
                return;
626
        }
627
        if(session->destroyed) {
628
                JANUS_LOG(LOG_VERB, "SIP session already destroyed...\n");
629
                return;
630
        }
631
        janus_mutex_lock(&sessions_mutex);
632
        g_hash_table_remove(sessions, handle);
633
        janus_mutex_unlock(&sessions_mutex);
634
        janus_sip_hangup_media(handle);
635
        JANUS_LOG(LOG_VERB, "Destroying SIP session (%s)...\n", session->account.username ? session->account.username : "unregistered user");
636
        /* Shutdown the NUA */
637
        nua_shutdown(session->stack->s_nua);
638
        /* Cleaning up and removing the session is done in a lazy way */
639
        session->destroyed = janus_get_monotonic_time();
640
        janus_mutex_lock(&sessions_mutex);
641
        old_sessions = g_list_append(old_sessions, session);
642
        janus_mutex_unlock(&sessions_mutex);
643
        return;
644
}
645

    
646
char *janus_sip_query_session(janus_plugin_session *handle) {
647
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
648
                return NULL;
649
        }        
650
        janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;
651
        if(!session) {
652
                JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
653
                return NULL;
654
        }
655
        /* Provide some generic info, e.g., if we're in a call and with whom */
656
        json_t *info = json_object();
657
        json_object_set_new(info, "username", session->account.username ? json_string(session->account.username) : NULL);
658
        json_object_set_new(info, "identity", session->account.identity ? json_string(session->account.identity) : NULL);
659
        json_object_set_new(info, "status", json_string(janus_sip_status_string(session->status)));
660
        if(session->callee)
661
                json_object_set_new(info, "callee", json_string(session->callee ? session->callee : "??"));
662
        json_object_set_new(info, "destroyed", json_integer(session->destroyed));
663
        char *info_text = json_dumps(info, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
664
        json_decref(info);
665
        return info_text;
666
}
667

    
668
struct janus_plugin_result *janus_sip_handle_message(janus_plugin_session *handle, char *transaction, char *message, char *sdp_type, char *sdp) {
669
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
670
                return janus_plugin_result_new(JANUS_PLUGIN_ERROR, g_atomic_int_get(&stopping) ? "Shutting down" : "Plugin not initialized");
671
        JANUS_LOG(LOG_VERB, "%s\n", message);
672
        janus_sip_message *msg = calloc(1, sizeof(janus_sip_message));
673
        if(msg == NULL) {
674
                JANUS_LOG(LOG_FATAL, "Memory error!\n");
675
                return janus_plugin_result_new(JANUS_PLUGIN_ERROR, "Memory error");
676
        }
677
        msg->handle = handle;
678
        msg->transaction = transaction;
679
        msg->message = message;
680
        msg->sdp_type = sdp_type;
681
        msg->sdp = sdp;
682
        g_async_queue_push(messages, msg);
683

    
684
        /* All the requests to this plugin are handled asynchronously */
685
        return janus_plugin_result_new(JANUS_PLUGIN_OK_WAIT, NULL);
686
}
687

    
688
void janus_sip_setup_media(janus_plugin_session *handle) {
689
        JANUS_LOG(LOG_INFO, "WebRTC media is now available\n");
690
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
691
                return;
692
        janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;        
693
        if(!session) {
694
                JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
695
                return;
696
        }
697
        if(session->destroyed)
698
                return;
699
        /* TODO Only relay RTP/RTCP when we get this event */
700
}
701

    
702
void janus_sip_incoming_rtp(janus_plugin_session *handle, int video, char *buf, int len) {
703
        if(handle == NULL || handle->stopped || g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
704
                return;
705
        if(gateway) {
706
                /* Honour the audio/video active flags */
707
                janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;        
708
                if(!session || session->destroyed) {
709
                        JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
710
                        return;
711
                }
712
                if(session->status != janus_sip_status_incall)
713
                        return;
714
                /* Forward to our SIP peer */
715
                if(video) {
716
                        if(session->media.video_ssrc == 0) {
717
                                rtp_header *header = (rtp_header *)buf;
718
                                session->media.video_ssrc = ntohl(header->ssrc);
719
                                JANUS_LOG(LOG_VERB, "Got SIP video SSRC: %"SCNu32"\n", session->media.video_ssrc);
720
                        }
721
                        if(session->media.has_video && session->media.video_rtp_fd) {
722
                                send(session->media.video_rtp_fd, buf, len, 0);
723
                        }
724
                } else {
725
                        if(session->media.audio_ssrc == 0) {
726
                                rtp_header *header = (rtp_header *)buf;
727
                                session->media.audio_ssrc = ntohl(header->ssrc);
728
                                JANUS_LOG(LOG_VERB, "Got SIP audio SSRC: %"SCNu32"\n", session->media.audio_ssrc);
729
                        }
730
                        if(session->media.has_audio && session->media.audio_rtp_fd) {
731
                                send(session->media.audio_rtp_fd, buf, len, 0);
732
                        }
733
                }
734
        }
735
}
736

    
737
void janus_sip_incoming_rtcp(janus_plugin_session *handle, int video, char *buf, int len) {
738
        if(handle == NULL || handle->stopped || g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
739
                return;
740
        if(gateway) {
741
                janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;        
742
                if(!session || session->destroyed) {
743
                        JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
744
                        return;
745
                }
746
                if(session->status != janus_sip_status_incall)
747
                        return;
748
                /* Fix SSRCs as the gateway does */
749
                JANUS_LOG(LOG_HUGE, "[SIP] Fixing SSRCs (local %u, peer %u)\n",
750
                        video ? session->media.video_ssrc : session->media.audio_ssrc,
751
                        video ? session->media.video_ssrc_peer : session->media.audio_ssrc_peer);
752
                janus_rtcp_fix_ssrc((char *)buf, len, 1,
753
                        video ? session->media.video_ssrc : session->media.audio_ssrc,
754
                        video ? session->media.video_ssrc_peer : session->media.audio_ssrc_peer);
755
                /* Forward to our SIP peer */
756
                if(video) {
757
                        if(session->media.has_video && session->media.video_rtcp_fd) {
758
                                send(session->media.video_rtcp_fd, buf, len, 0);
759
                        }
760
                } else {
761
                        if(session->media.has_audio && session->media.audio_rtcp_fd) {
762
                                send(session->media.audio_rtcp_fd, buf, len, 0);
763
                        }
764
                }
765
        }
766
}
767

    
768
void janus_sip_hangup_media(janus_plugin_session *handle) {
769
        JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
770
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
771
                return;
772
        janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;        
773
        if(!session) {
774
                JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
775
                return;
776
        }
777
        if(session->destroyed)
778
                return;
779
        if(session->status < janus_sip_status_inviting || session->status > janus_sip_status_incall)
780
                return;
781
        /* FIXME Simulate a "hangup" coming from the browser */
782
        janus_sip_message *msg = calloc(1, sizeof(janus_sip_message));
783
        if(msg == NULL) {
784
                JANUS_LOG(LOG_FATAL, "Memory error!\n");
785
                return;
786
        }
787
        msg->handle = handle;
788
        msg->message = g_strdup("{\"request\":\"hangup\"}");
789
        msg->transaction = NULL;
790
        msg->sdp_type = NULL;
791
        msg->sdp = NULL;
792
        g_async_queue_push(messages, msg);
793
}
794

    
795
/* Thread to handle incoming messages */
796
static void *janus_sip_handler(void *data) {
797
        JANUS_LOG(LOG_VERB, "Joining SIP handler thread\n");
798
        janus_sip_message *msg = NULL;
799
        int error_code = 0;
800
        char *error_cause = calloc(512, sizeof(char));
801
        if(error_cause == NULL) {
802
                JANUS_LOG(LOG_FATAL, "Memory error!\n");
803
                return NULL;
804
        }
805
        json_t *root = NULL;
806
        while(g_atomic_int_get(&initialized) && !g_atomic_int_get(&stopping)) {
807
                if(!messages || (msg = g_async_queue_try_pop(messages)) == NULL) {
808
                        usleep(50000);
809
                        continue;
810
                }
811
                janus_sip_session *session = (janus_sip_session *)msg->handle->plugin_handle;
812
                if(!session) {
813
                        JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
814
                        janus_sip_message_free(msg);
815
                        continue;
816
                }
817
                if(session->destroyed) {
818
                        janus_sip_message_free(msg);
819
                        continue;
820
                }
821
                /* Handle request */
822
                error_code = 0;
823
                root = NULL;
824
                JANUS_LOG(LOG_VERB, "Handling message: %s\n", msg->message);
825
                if(msg->message == NULL) {
826
                        JANUS_LOG(LOG_ERR, "No message??\n");
827
                        error_code = JANUS_SIP_ERROR_NO_MESSAGE;
828
                        g_snprintf(error_cause, 512, "%s", "No message??");
829
                        goto error;
830
                }
831
                json_error_t error;
832
                root = json_loads(msg->message, 0, &error);
833
                if(!root) {
834
                        JANUS_LOG(LOG_ERR, "JSON error: on line %d: %s\n", error.line, error.text);
835
                        error_code = JANUS_SIP_ERROR_INVALID_JSON;
836
                        g_snprintf(error_cause, 512, "JSON error: on line %d: %s", error.line, error.text);
837
                        goto error;
838
                }
839
                if(!json_is_object(root)) {
840
                        JANUS_LOG(LOG_ERR, "JSON error: not an object\n");
841
                        error_code = JANUS_SIP_ERROR_INVALID_JSON;
842
                        g_snprintf(error_cause, 512, "JSON error: not an object");
843
                        goto error;
844
                }
845
                json_t *request = json_object_get(root, "request");
846
                if(!request) {
847
                        JANUS_LOG(LOG_ERR, "Missing element (request)\n");
848
                        error_code = JANUS_SIP_ERROR_MISSING_ELEMENT;
849
                        g_snprintf(error_cause, 512, "Missing element (request)");
850
                        goto error;
851
                }
852
                if(!json_is_string(request)) {
853
                        JANUS_LOG(LOG_ERR, "Invalid element (request should be a string)\n");
854
                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
855
                        g_snprintf(error_cause, 512, "Invalid element (request should be a string)");
856
                        goto error;
857
                }
858
                const char *request_text = json_string_value(request);
859
                json_t *result = NULL;
860
                char *sdp_type = NULL, *sdp = NULL;
861
                if(!strcasecmp(request_text, "register")) {
862
                        /* Send a REGISTER */
863
                        if(session->status > janus_sip_status_unregistered) {
864
                                JANUS_LOG(LOG_ERR, "Already registered (%s)\n", session->account.username);
865
                                error_code = JANUS_SIP_ERROR_ALREADY_REGISTERED;
866
                                g_snprintf(error_cause, 512, "Already registered (%s)", session->account.username);
867
                                goto error;
868
                        }
869

    
870
                        /* Cleanup old values */
871
                        if(session->account.identity != NULL)
872
                                g_free(session->account.identity);
873
                        if(session->account.username != NULL)
874
                                g_free(session->account.username);
875
                        if(session->account.secret != NULL)
876
                                g_free(session->account.secret);
877
                        if(session->account.proxy != NULL)
878
                                g_free(session->account.proxy);
879

    
880
                        gboolean guest = FALSE;
881
                        json_t *type = json_object_get(root, "type");
882
                        if(type != NULL) {
883
                                if(!type) {
884
                                        JANUS_LOG(LOG_ERR, "Missing element (type)\n");
885
                                        error_code = JANUS_SIP_ERROR_MISSING_ELEMENT;
886
                                        g_snprintf(error_cause, 512, "Missing element (type)");
887
                                        goto error;
888
                                }
889
                                if(!json_is_string(type)) {
890
                                        JANUS_LOG(LOG_ERR, "Invalid element (type should be a string)\n");
891
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
892
                                        g_snprintf(error_cause, 512, "Invalid element (type should be a string)");
893
                                        goto error;
894
                                }
895
                                const char *type_text = json_string_value(type);
896
                                if(!strcmp(type_text, "guest")) {
897
                                        JANUS_LOG(LOG_INFO, "Registering as a guest\n");
898
                                        guest = TRUE;
899
                                } else {
900
                                        JANUS_LOG(LOG_WARN, "Unknown type '%s', ignoring...\n", type_text);
901
                                }
902
                        }
903
                        /* Parse address */
904
                        json_t *proxy = json_object_get(root, "proxy");
905
                        const char *proxy_text = NULL;
906

    
907
                        if (proxy && !json_is_null(proxy)) {
908
                                if(!json_is_string(proxy)) {
909
                                        JANUS_LOG(LOG_ERR, "Invalid element (proxy should be a string)\n");
910
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
911
                                        g_snprintf(error_cause, 512, "Invalid element (proxy should be a string)");
912
                                        goto error;
913
                                }
914
                                proxy_text = json_string_value(proxy);
915
                                janus_sip_uri_t proxy_uri;
916
                                if (janus_sip_parse_proxy_uri(&proxy_uri, proxy_text) < 0) {
917
                                        JANUS_LOG(LOG_ERR, "Invalid proxy address %s\n", proxy_text);
918
                                        error_code = JANUS_SIP_ERROR_INVALID_ADDRESS;
919
                                        g_snprintf(error_cause, 512, "Invalid proxy address %s\n", proxy_text);
920
                                        goto error;
921
                                }
922
                        }
923

    
924
                        /* Parse register TTL */
925
                        int ttl = register_ttl;
926
                        json_t *reg_ttl = json_object_get(root, "register_ttl");
927
                        if (reg_ttl && json_is_integer(reg_ttl))
928
                                ttl = json_integer_value(reg_ttl);
929
                        if (ttl <= 0)
930
                                ttl = JANUS_DEFAULT_REGISTER_TTL;
931

    
932
                        /* Now the user part, if needed */
933
                        json_t *username = json_object_get(root, "username");
934
                        if(!guest && !username) {
935
                                /* The username is mandatory if we're not registering as guests */
936
                                JANUS_LOG(LOG_ERR, "Missing element (username)\n");
937
                                error_code = JANUS_SIP_ERROR_MISSING_ELEMENT;
938
                                g_snprintf(error_cause, 512, "Missing element (username)");
939
                                goto error;
940
                        }
941
                        const char *username_text = NULL;
942
                        janus_sip_uri_t username_uri;
943
                        char user_id[256];
944
                        if(username) {
945
                                if(!json_is_string(username)) {
946
                                        JANUS_LOG(LOG_ERR, "Invalid element (username should be a string)\n");
947
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
948
                                        g_snprintf(error_cause, 512, "Invalid element (username should be a string)");
949
                                        goto error;
950
                                }
951
                                /* Parse address */
952
                                username_text = json_string_value(username);
953
                                if (janus_sip_parse_uri(&username_uri, username_text) < 0) {
954
                                        JANUS_LOG(LOG_ERR, "Invalid user address %s\n", username_text);
955
                                        error_code = JANUS_SIP_ERROR_INVALID_ADDRESS;
956
                                        g_snprintf(error_cause, 512, "Invalid user address %s\n", username_text);
957
                                        goto error;
958
                                }
959
                                g_strlcpy(user_id, username_uri.url->url_user, sizeof(user_id));
960
                        }
961
                        if(guest) {
962
                                /* Not needed, we can stop here: just pick a random username if it wasn't provided and say we're registered */
963
                                if(!username)
964
                                        g_snprintf(user_id, 255, "janus-sip-%"SCNu32"", g_random_int());
965
                                JANUS_LOG(LOG_INFO, "Guest will have username %s\n", user_id);
966
                        } else {
967
                                json_t *secret = json_object_get(root, "secret");
968
                                if(!secret) {
969
                                        JANUS_LOG(LOG_ERR, "Missing element (secret)\n");
970
                                        error_code = JANUS_SIP_ERROR_MISSING_ELEMENT;
971
                                        g_snprintf(error_cause, 512, "Missing element (secret)");
972
                                        goto error;
973
                                }
974
                                if(!json_is_string(secret)) {
975
                                        JANUS_LOG(LOG_ERR, "Invalid element (secret should be a string)\n");
976
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
977
                                        g_snprintf(error_cause, 512, "Invalid element (secret should be a string)");
978
                                        goto error;
979
                                }
980
                                const char *secret_text = json_string_value(secret);
981
                                session->account.secret = g_strdup(secret_text);
982
                                if (session->account.secret == NULL) {
983
                                        JANUS_LOG(LOG_FATAL, "Memory error!\n");
984
                                        error_code = JANUS_SIP_ERROR_UNKNOWN_ERROR;
985
                                        g_snprintf(error_cause, 512, "Memory error");
986
                                        goto error;
987
                                }
988
                                /* Got the values, try registering now */
989
                                JANUS_LOG(LOG_VERB, "Registering user %s (secret %s) @ %s through %s\n",
990
                                        username_text, secret_text, username_uri.url->url_host, proxy_text != NULL ? proxy_text : "(null)");
991
                        }
992

    
993
                        session->account.identity = g_strdup(username_text);
994
                        session->account.username = g_strdup(user_id);
995
                        if(session->account.identity == NULL || session->account.username == NULL) {
996
                                JANUS_LOG(LOG_FATAL, "Memory error!\n");
997
                                error_code = JANUS_SIP_ERROR_UNKNOWN_ERROR;
998
                                g_snprintf(error_cause, 512, "Memory error");
999
                                goto error;
1000
                        }
1001
                        if (proxy_text) {
1002
                                session->account.proxy = g_strdup(proxy_text);
1003
                                if(session->account.proxy == NULL) {
1004
                                        JANUS_LOG(LOG_FATAL, "Memory error!\n");
1005
                                        error_code = JANUS_SIP_ERROR_UNKNOWN_ERROR;
1006
                                        g_snprintf(error_cause, 512, "Memory error");
1007
                                        goto error;
1008
                                }
1009
                        }
1010

    
1011
                        session->status = janus_sip_status_registering;
1012
                        if(session->stack->s_nua == NULL) {
1013
                                /* Start the thread first */
1014
                                GError *error = NULL;
1015
                                g_thread_try_new("worker", janus_sip_sofia_thread, session, &error);
1016
                                if(error != NULL) {
1017
                                        JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the SIP Sofia thread...\n", error->code, error->message ? error->message : "??");
1018
                                        error_code = JANUS_SIP_ERROR_UNKNOWN_ERROR;
1019
                                        g_snprintf(error_cause, 512, "Got error %d (%s) trying to launch the SIP Sofia thread", error->code, error->message ? error->message : "??");
1020
                                        goto error;
1021
                                }
1022
                                long int timeout = 0;
1023
                                while(session->stack->s_nua == NULL) {
1024
                                        g_usleep(100000);
1025
                                        timeout += 100000;
1026
                                        if(timeout >= 2000000) {
1027
                                                break;
1028
                                        }
1029
                                }
1030
                                if(timeout >= 2000000) {
1031
                                        JANUS_LOG(LOG_ERR, "Two seconds passed and still no NUA, problems with the thread?\n");
1032
                                        error_code = JANUS_SIP_ERROR_UNKNOWN_ERROR;
1033
                                        g_snprintf(error_cause, 512, "Two seconds passed and still no NUA, problems with the thread?");
1034
                                        goto error;
1035
                                }
1036
                        }
1037
                        if(session->stack->s_nh_r != NULL)
1038
                                nua_handle_destroy(session->stack->s_nh_r);
1039

    
1040
                        if (!guest) {
1041
                                session->stack->s_nh_r = nua_handle(session->stack->s_nua, session, TAG_END());
1042
                                if(session->stack->s_nh_r == NULL) {
1043
                                        JANUS_LOG(LOG_ERR, "NUA Handle for REGISTER still null??\n");
1044
                                        error_code = JANUS_SIP_ERROR_LIBSOFIA_ERROR;
1045
                                        g_snprintf(error_cause, 512, "Invalid NUA Handle");
1046
                                        goto error;
1047
                                }
1048
                                char ttl_text[20];
1049
                                g_snprintf(ttl_text, sizeof(ttl_text), "%d", ttl);
1050
                                nua_register(session->stack->s_nh_r,
1051
                                        NUTAG_M_USERNAME(session->account.username),
1052
                                        SIPTAG_FROM_STR(username_text),
1053
                                        SIPTAG_TO_STR(username_text),
1054
                                        SIPTAG_EXPIRES_STR(ttl_text),
1055
                                        NUTAG_PROXY(proxy_text),
1056
                                        TAG_END());
1057
                                result = json_object();
1058
                                json_object_set_new(result, "event", json_string("registering"));
1059
                        } else {
1060
                                session->status = janus_sip_status_registered;
1061
                                result = json_object();
1062
                                json_object_set_new(result, "event", json_string("registered"));
1063
                                json_object_set_new(result, "username", json_string(session->account.username));
1064
                        }
1065
                } else if(!strcasecmp(request_text, "call")) {
1066
                        /* Call another peer */
1067
                        if(session->status >= janus_sip_status_inviting) {
1068
                                JANUS_LOG(LOG_ERR, "Wrong state (already in a call? status=%s)\n", janus_sip_status_string(session->status));
1069
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1070
                                g_snprintf(error_cause, 512, "Wrong state (already in a call? status=%s)", janus_sip_status_string(session->status));
1071
                                goto error;
1072
                        }
1073
                        json_t *uri = json_object_get(root, "uri");
1074
                        if(!uri) {
1075
                                JANUS_LOG(LOG_ERR, "Missing element (uri)\n");
1076
                                error_code = JANUS_SIP_ERROR_MISSING_ELEMENT;
1077
                                g_snprintf(error_cause, 512, "Missing element (uri)");
1078
                                goto error;
1079
                        }
1080
                        if(!json_is_string(uri)) {
1081
                                JANUS_LOG(LOG_ERR, "Invalid element (uri should be a string)\n");
1082
                                error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
1083
                                g_snprintf(error_cause, 512, "Invalid element (uri should be a string)");
1084
                                goto error;
1085
                        }
1086
                        /* Parse address */
1087
                        const char *uri_text = json_string_value(uri);
1088
                        janus_sip_uri_t target_uri;
1089
                        if (janus_sip_parse_uri(&target_uri, uri_text) < 0) {
1090
                                JANUS_LOG(LOG_ERR, "Invalid user address %s\n", uri_text);
1091
                                error_code = JANUS_SIP_ERROR_INVALID_ADDRESS;
1092
                                g_snprintf(error_cause, 512, "Invalid user address %s\n", uri_text);
1093
                                goto error;
1094
                        }
1095
                        /* Any SDP to handle? if not, something's wrong */
1096
                        if(!msg->sdp) {
1097
                                JANUS_LOG(LOG_ERR, "Missing SDP\n");
1098
                                error_code = JANUS_SIP_ERROR_MISSING_SDP;
1099
                                g_snprintf(error_cause, 512, "Missing SDP");
1100
                                goto error;
1101
                        }
1102
                        JANUS_LOG(LOG_VERB, "%s is calling %s\n", session->account.username, uri_text);
1103
                        JANUS_LOG(LOG_VERB, "This is involving a negotiation (%s) as well:\n%s\n", msg->sdp_type, msg->sdp);
1104
                        /* Allocate RTP ports and merge them with the anonymized SDP */
1105
                        if(strstr(msg->sdp, "m=audio")) {
1106
                                JANUS_LOG(LOG_VERB, "Going to negotiate audio...\n");
1107
                                session->media.has_audio = 1;        /* FIXME Maybe we need a better way to signal this */
1108
                        }
1109
                        if(strstr(msg->sdp, "m=video")) {
1110
                                JANUS_LOG(LOG_VERB, "Going to negotiate video...\n");
1111
                                session->media.has_video = 1;        /* FIXME Maybe we need a better way to signal this */
1112
                        }
1113
                        if(janus_sip_allocate_local_ports(session) < 0) {
1114
                                JANUS_LOG(LOG_ERR, "Could not allocate RTP/RTCP ports\n");
1115
                                error_code = JANUS_SIP_ERROR_IO_ERROR;
1116
                                g_snprintf(error_cause, 512, "Could not allocate RTP/RTCP ports");
1117
                                goto error;
1118
                        }
1119
                        char *sdp = g_strdup(msg->sdp);
1120
                        if(sdp == NULL) {
1121
                                JANUS_LOG(LOG_FATAL, "Memory error!\n");
1122
                                error_code = JANUS_SIP_ERROR_UNKNOWN_ERROR;
1123
                                g_snprintf(error_cause, 512, "Memory error");
1124
                                goto error;
1125
                        }
1126
                        sdp = janus_string_replace(sdp, "RTP/SAVPF", "RTP/AVP");
1127
                        sdp = janus_string_replace(sdp, "1.1.1.1", local_ip);
1128
                        if(session->media.has_audio) {
1129
                                JANUS_LOG(LOG_VERB, "Setting local audio port: %d\n", session->media.local_audio_rtp_port);
1130
                                char mline[20];
1131
                                g_snprintf(mline, 20, "m=audio %d", session->media.local_audio_rtp_port);
1132
                                sdp = janus_string_replace(sdp, "m=audio 1", mline);
1133
                        }
1134
                        if(session->media.has_video) {
1135
                                JANUS_LOG(LOG_VERB, "Setting local video port: %d\n", session->media.local_video_rtp_port);
1136
                                char mline[20];
1137
                                g_snprintf(mline, 20, "m=video %d", session->media.local_video_rtp_port);
1138
                                sdp = janus_string_replace(sdp, "m=video 1", mline);
1139
                        }
1140
                        /* Send INVITE */
1141
                        if(session->stack->s_nh_i != NULL)
1142
                                nua_handle_destroy(session->stack->s_nh_i);
1143
                        session->stack->s_nh_i = nua_handle(session->stack->s_nua, session, TAG_END());
1144
                        if(session->stack->s_nh_i == NULL) {
1145
                                JANUS_LOG(LOG_WARN, "NUA Handle for INVITE still null??\n");
1146
                                error_code = JANUS_SIP_ERROR_LIBSOFIA_ERROR;
1147
                                g_snprintf(error_cause, 512, "Invalid NUA Handle");
1148
                                goto error;
1149
                        }
1150
                        session->status = janus_sip_status_inviting;
1151
                        nua_invite(session->stack->s_nh_i,
1152
                                SIPTAG_FROM_STR(session->account.identity),
1153
                                SIPTAG_TO_STR(uri_text),
1154
                                SOATAG_USER_SDP_STR(sdp),
1155
                                NUTAG_PROXY(session->account.proxy),
1156
                                TAG_END());
1157
                        g_free(sdp);
1158
                        session->callee = g_strdup(uri_text);
1159
                        if(session->transaction)
1160
                                g_free(session->transaction);
1161
                        session->transaction = msg->transaction ? g_strdup(msg->transaction) : NULL;
1162
                        /* Send an ack back */
1163
                        result = json_object();
1164
                        json_object_set_new(result, "event", json_string("calling"));
1165
                } else if(!strcasecmp(request_text, "accept")) {
1166
                        if(session->status != janus_sip_status_invited) {
1167
                                JANUS_LOG(LOG_ERR, "Wrong state (not invited? status=%s)\n", janus_sip_status_string(session->status));
1168
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1169
                                g_snprintf(error_cause, 512, "Wrong state (not invited? status=%s)", janus_sip_status_string(session->status));
1170
                                goto error;
1171
                        }
1172
                        if(session->callee == NULL) {
1173
                                JANUS_LOG(LOG_ERR, "Wrong state (no caller?)\n");
1174
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1175
                                g_snprintf(error_cause, 512, "Wrong state (no caller?)");
1176
                                goto error;
1177
                        }
1178
                        /* Any SDP to handle? if not, something's wrong */
1179
                        if(!msg->sdp) {
1180
                                JANUS_LOG(LOG_ERR, "Missing SDP\n");
1181
                                error_code = JANUS_SIP_ERROR_MISSING_SDP;
1182
                                g_snprintf(error_cause, 512, "Missing SDP");
1183
                                goto error;
1184
                        }
1185
                        /* Accept a call from another peer */
1186
                        JANUS_LOG(LOG_VERB, "We're accepting the call from %s\n", session->callee);
1187
                        JANUS_LOG(LOG_VERB, "This is involving a negotiation (%s) as well:\n%s\n", msg->sdp_type, msg->sdp);
1188
                        /* Allocate RTP ports and merge them with the anonymized SDP */
1189
                        if(strstr(msg->sdp, "m=audio")) {
1190
                                JANUS_LOG(LOG_VERB, "Going to negotiate audio...\n");
1191
                                session->media.has_audio = 1;        /* FIXME Maybe we need a better way to signal this */
1192
                        }
1193
                        if(strstr(msg->sdp, "m=video")) {
1194
                                JANUS_LOG(LOG_VERB, "Going to negotiate video...\n");
1195
                                session->media.has_video = 1;        /* FIXME Maybe we need a better way to signal this */
1196
                        }
1197
                        if(janus_sip_allocate_local_ports(session) < 0) {
1198
                                JANUS_LOG(LOG_ERR, "Could not allocate RTP/RTCP ports\n");
1199
                                error_code = JANUS_SIP_ERROR_IO_ERROR;
1200
                                g_snprintf(error_cause, 512, "Could not allocate RTP/RTCP ports");
1201
                                goto error;
1202
                        }
1203
                        char *sdp = g_strdup(msg->sdp);
1204
                        if(sdp == NULL) {
1205
                                JANUS_LOG(LOG_FATAL, "Memory error!\n");
1206
                                error_code = JANUS_SIP_ERROR_UNKNOWN_ERROR;
1207
                                g_snprintf(error_cause, 512, "Memory error");
1208
                                goto error;
1209
                        }
1210
                        sdp = janus_string_replace(sdp, "RTP/SAVPF", "RTP/AVP");
1211
                        sdp = janus_string_replace(sdp, "1.1.1.1", local_ip);
1212
                        if(session->media.has_audio) {
1213
                                JANUS_LOG(LOG_VERB, "Setting local audio port: %d\n", session->media.local_audio_rtp_port);
1214
                                char mline[20];
1215
                                g_snprintf(mline, 20, "m=audio %d", session->media.local_audio_rtp_port);
1216
                                sdp = janus_string_replace(sdp, "m=audio 1", mline);
1217
                        }
1218
                        if(session->media.has_video) {
1219
                                JANUS_LOG(LOG_VERB, "Setting local video port: %d\n", session->media.local_video_rtp_port);
1220
                                char mline[20];
1221
                                g_snprintf(mline, 20, "m=video %d", session->media.local_video_rtp_port);
1222
                                sdp = janus_string_replace(sdp, "m=video 1", mline);
1223
                        }
1224
                        /* Send 200 OK */
1225
                        session->status = janus_sip_status_incall;
1226
                        if(session->stack->s_nh_i == NULL) {
1227
                                JANUS_LOG(LOG_WARN, "NUA Handle for 200 OK still null??\n");
1228
                        }
1229
                        nua_respond(session->stack->s_nh_i,
1230
                                200, sip_status_phrase(200),
1231
                                SOATAG_USER_SDP_STR(sdp),
1232
                                TAG_END());
1233
                        g_free(sdp);
1234
                        /* Send an ack back */
1235
                        result = json_object();
1236
                        json_object_set_new(result, "event", json_string("accepted"));
1237
                        /* Start the media */
1238
                        session->media.ready = 1;        /* FIXME Maybe we need a better way to signal this */
1239
                        GError *error = NULL;
1240
                        g_thread_try_new("janus rtp handler", janus_sip_relay_thread, session, &error);
1241
                        if(error != NULL) {
1242
                                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the RTP/RTCP thread...\n", error->code, error->message ? error->message : "??");
1243
                        }
1244
                } else if(!strcasecmp(request_text, "decline")) {
1245
                        /* Reject an incoming call */
1246
                        if(session->status != janus_sip_status_invited) {
1247
                                JANUS_LOG(LOG_ERR, "Wrong state (not invited? status=%s)\n", janus_sip_status_string(session->status));
1248
                                /* Ignore */
1249
                                json_decref(root);
1250
                                continue;
1251
                                //~ g_snprintf(error_cause, 512, "Wrong state (not in a call?)");
1252
                                //~ goto error;
1253
                        }
1254
                        if(session->callee == NULL) {
1255
                                JANUS_LOG(LOG_ERR, "Wrong state (no callee?)\n");
1256
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1257
                                g_snprintf(error_cause, 512, "Wrong state (no callee?)");
1258
                                goto error;
1259
                        }
1260
                        session->status = janus_sip_status_registered;        /* FIXME */
1261
                        if(session->stack->s_nh_i == NULL) {
1262
                                JANUS_LOG(LOG_WARN, "NUA Handle for 200 OK still null??\n");
1263
                        }
1264
                        nua_respond(session->stack->s_nh_i, 603, sip_status_phrase(603), TAG_END());
1265
                        g_free(session->callee);
1266
                        session->callee = NULL;
1267
                        /* Notify the operation */
1268
                        result = json_object();
1269
                        json_object_set_new(result, "event", json_string("ack"));
1270
                } else if(!strcasecmp(request_text, "hangup")) {
1271
                        /* Hangup an ongoing call */
1272
                        if(session->status < janus_sip_status_inviting || session->status > janus_sip_status_incall) {
1273
                                JANUS_LOG(LOG_ERR, "Wrong state (not in a call? status=%s)\n", janus_sip_status_string(session->status));
1274
                                /* Ignore */
1275
                                json_decref(root);
1276
                                continue;
1277
                                //~ g_snprintf(error_cause, 512, "Wrong state (not in a call?)");
1278
                                //~ goto error;
1279
                        }
1280
                        if(session->callee == NULL) {
1281
                                JANUS_LOG(LOG_ERR, "Wrong state (no callee?)\n");
1282
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1283
                                g_snprintf(error_cause, 512, "Wrong state (no callee?)");
1284
                                goto error;
1285
                        }
1286
                        session->status = janus_sip_status_closing;
1287
                        nua_bye(session->stack->s_nh_i, TAG_END());
1288
                        g_free(session->callee);
1289
                        session->callee = NULL;
1290
                        /* Notify the operation */
1291
                        result = json_object();
1292
                        json_object_set_new(result, "event", json_string("hangingup"));
1293
                } else {
1294
                        JANUS_LOG(LOG_ERR, "Unknown request (%s)\n", request_text);
1295
                        error_code = JANUS_SIP_ERROR_INVALID_REQUEST;
1296
                        g_snprintf(error_cause, 512, "Unknown request (%s)", request_text);
1297
                        goto error;
1298
                }
1299

    
1300
                json_decref(root);
1301
                /* Prepare JSON event */
1302
                json_t *event = json_object();
1303
                json_object_set_new(event, "sip", json_string("event"));
1304
                if(result != NULL)
1305
                        json_object_set_new(event, "result", result);
1306
                char *event_text = json_dumps(event, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1307
                json_decref(event);
1308
                JANUS_LOG(LOG_VERB, "Pushing event: %s\n", event_text);
1309
                int ret = gateway->push_event(msg->handle, &janus_sip_plugin, msg->transaction, event_text, sdp_type, sdp);
1310
                JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1311
                g_free(event_text);
1312
                if(sdp)
1313
                        g_free(sdp);
1314
                janus_sip_message_free(msg);
1315
                continue;
1316
                
1317
error:
1318
                {
1319
                        if(root != NULL)
1320
                                json_decref(root);
1321
                        /* Prepare JSON error event */
1322
                        json_t *event = json_object();
1323
                        json_object_set_new(event, "sip", json_string("event"));
1324
                        json_object_set_new(event, "error_code", json_integer(error_code));
1325
                        json_object_set_new(event, "error", json_string(error_cause));
1326
                        char *event_text = json_dumps(event, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1327
                        json_decref(event);
1328
                        JANUS_LOG(LOG_VERB, "Pushing event: %s\n", event_text);
1329
                        int ret = gateway->push_event(msg->handle, &janus_sip_plugin, msg->transaction, event_text, NULL, NULL);
1330
                        JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1331
                        g_free(event_text);
1332
                        janus_sip_message_free(msg);
1333
                }
1334
        }
1335
        g_free(error_cause);
1336
        JANUS_LOG(LOG_VERB, "Leaving SIP handler thread\n");
1337
        return NULL;
1338
}
1339

    
1340

    
1341
/* Sofia callbacks */
1342
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[])
1343
{
1344
        janus_sip_session *session = (janus_sip_session *)magic;
1345
        ssip_t *ssip = session->stack;
1346
        switch (event) {
1347
        /* Status or Error Indications */
1348
                case nua_i_active:
1349
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1350
                        break;
1351
                case nua_i_error:
1352
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1353
                        break;
1354
                case nua_i_fork:
1355
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1356
                        break;
1357
                case nua_i_media_error:
1358
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1359
                        break;
1360
                case nua_i_subscription:
1361
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1362
                        break;
1363
                case nua_i_state:
1364
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1365
                        break;
1366
                case nua_i_terminated:
1367
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1368
                        break;
1369
        /* SIP requests */
1370
                case nua_i_ack:
1371
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1372
                        break;
1373
                case nua_i_outbound:
1374
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1375
                        break;
1376
                case nua_i_bye: {
1377
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1378
                        /* Call ended, notify the browser */
1379
                        session->status = janus_sip_status_registered;        /* FIXME What about a 'closing' state? */
1380
                        char reason[100];
1381
                        memset(reason, 0, 100);
1382
                        g_snprintf(reason, 100, "%d %s", status, phrase);
1383
                        json_t *call = json_object();
1384
                        json_object_set_new(call, "sip", json_string("event"));
1385
                        json_t *calling = json_object();
1386
                        json_object_set_new(calling, "event", json_string("hangup"));
1387
                        json_object_set_new(calling, "username", json_string(session->callee));
1388
                        json_object_set_new(calling, "reason", json_string(reason));
1389
                        json_object_set_new(call, "result", calling);
1390
                        char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1391
                        json_decref(call);
1392
                        JANUS_LOG(LOG_VERB, "Pushing event: %s\n", call_text);
1393
                        int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call_text, NULL, NULL);
1394
                        JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1395
                        g_free(call_text);
1396
                        /* Get rid of any PeerConnection that may have been set up in the meanwhile */
1397
                        if(session->transaction)
1398
                                g_free(session->transaction);
1399
                        session->transaction = NULL;
1400
                        gateway->close_pc(session->handle);
1401
                        break;
1402
                }
1403
                case nua_i_cancel: {
1404
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1405
                        /* FIXME Check state? */
1406
                        session->status = janus_sip_status_registered;        /* FIXME What about a 'closing' state? */
1407
                        /* Notify the browser */
1408
                        json_t *call = json_object();
1409
                        json_object_set_new(call, "sip", json_string("event"));
1410
                        json_t *calling = json_object();
1411
                        json_object_set_new(calling, "event", json_string("hangup"));
1412
                        json_object_set_new(calling, "username", json_string(session->callee));
1413
                        json_object_set_new(calling, "reason", json_string("Remote cancel"));
1414
                        json_object_set_new(call, "result", calling);
1415
                        char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1416
                        json_decref(call);
1417
                        JANUS_LOG(LOG_VERB, "Pushing event: %s\n", call_text);
1418
                        int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call_text, NULL, NULL);
1419
                        JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1420
                        g_free(call_text);
1421
                        /* Get rid of any PeerConnection that may have been set up in the meanwhile */
1422
                        if(session->transaction)
1423
                                g_free(session->transaction);
1424
                        session->transaction = NULL;
1425
                        gateway->close_pc(session->handle);
1426
                        break;
1427
                }
1428
                case nua_i_invite: {
1429
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1430
                        sdp_parser_t *parser = sdp_parse(ssip->s_home, sip->sip_payload->pl_data, sip->sip_payload->pl_len, 0);
1431
                        if(!sdp_session(parser)) {
1432
                                JANUS_LOG(LOG_ERR, "\tError parsing SDP!\n");
1433
                                nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
1434
                                break;
1435
                        }
1436
                        if(session->status >= janus_sip_status_inviting) {
1437
                                /* Busy */
1438
                                JANUS_LOG(LOG_VERB, "\tAlready in a call (busy, status=%s)\n", janus_sip_status_string(session->status));
1439
                                nua_respond(nh, 486, sip_status_phrase(486), TAG_END());
1440
                                break;
1441
                        }
1442
                        const char *caller = sip->sip_from->a_url->url_user;
1443
                        session->callee = g_strdup(url_as_string(session->stack->s_home, sip->sip_from->a_url));
1444
                        session->status = janus_sip_status_invited;
1445
                        /* Parse SDP */
1446
                        char *fixed_sdp = g_strdup(sip->sip_payload->pl_data);
1447
                        if(fixed_sdp == NULL) {
1448
                                JANUS_LOG(LOG_FATAL, "Memory error!\n");
1449
                                nua_respond(nh, 500, sip_status_phrase(500), TAG_END());
1450
                                break;
1451
                        }
1452
                        JANUS_LOG(LOG_VERB, "Someone is inviting us in a call:\n%s", sip->sip_payload->pl_data);
1453
                        sdp_session_t *sdp = sdp_session(parser);
1454
                        janus_sip_sdp_process(session, sdp);
1455
                        /* Send SDP to the browser */
1456
                        json_t *call = json_object();
1457
                        json_object_set_new(call, "sip", json_string("event"));
1458
                        json_t *calling = json_object();
1459
                        json_object_set_new(calling, "event", json_string("incomingcall"));
1460
                        json_object_set_new(calling, "username", json_string(caller));
1461
                        json_object_set_new(call, "result", calling);
1462
                        char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1463
                        json_decref(call);
1464
                        JANUS_LOG(LOG_VERB, "Pushing event to peer: %s\n", call_text);
1465
                        int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call_text, "offer", sip->sip_payload->pl_data);
1466
                        JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1467
                        g_free(call_text);
1468
                        /* Send a Ringing back */
1469
                        nua_respond(nh, 180, sip_status_phrase(180), TAG_END());
1470
                        session->stack->s_nh_i = nh;
1471
                        break;
1472
                }
1473
                case nua_i_options:
1474
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1475
                        /* FIXME Should we handle this message? for now we reply with a 405 Method Not Implemented */
1476
                        nua_respond(nh, 405, sip_status_phrase(405), TAG_END());
1477
                        break;
1478
        /* Responses */
1479
                case nua_r_get_params:
1480
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1481
                        break;
1482
                case nua_r_set_params:
1483
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1484
                        break;
1485
                case nua_r_notifier:
1486
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1487
                        break;
1488
                case nua_r_shutdown:
1489
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1490
                        if(status < 200 && stopping < 3) {
1491
                                /* shutdown in progress -> return */
1492
                                break;
1493
                        }
1494
                        /* end the event loop. su_root_run() will return */
1495
                        su_root_break(ssip->s_root);
1496
                        break;
1497
                case nua_r_terminate:
1498
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1499
                        break;
1500
        /* SIP responses */
1501
                case nua_r_bye:
1502
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1503
                        /* Call ended, notify the browser */
1504
                        session->status = janus_sip_status_registered;
1505
                        char reason[100];
1506
                        memset(reason, 0, 100);
1507
                        g_snprintf(reason, 100, "%d %s", status, phrase);
1508
                        json_t *call = json_object();
1509
                        json_object_set_new(call, "sip", json_string("event"));
1510
                        json_t *calling = json_object();
1511
                        json_object_set_new(calling, "event", json_string("hangup"));
1512
                        json_object_set_new(calling, "username", json_string(session->callee));
1513
                        json_object_set_new(calling, "reason", json_string("Bye"));
1514
                        json_object_set_new(call, "result", calling);
1515
                        char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1516
                        json_decref(call);
1517
                        JANUS_LOG(LOG_VERB, "Pushing event: %s\n", call_text);
1518
                        int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call_text, NULL, NULL);
1519
                        JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1520
                        g_free(call_text);
1521
                        /* Get rid of any PeerConnection that may have been set up in the meanwhile */
1522
                        if(session->transaction)
1523
                                g_free(session->transaction);
1524
                        session->transaction = NULL;
1525
                        gateway->close_pc(session->handle);
1526
                        break;
1527
                case nua_r_cancel:
1528
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1529
                        break;
1530
                case nua_r_invite: {
1531
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1532
                        if(status < 200) {
1533
                                /* Not ready yet (FIXME May this be pranswer?? we don't handle it yet...) */
1534
                                break;
1535
                        } else if(status == 401) {
1536
                                 /* Get scheme/realm from 401 error */
1537
                                sip_www_authenticate_t const* www_auth = sip->sip_www_authenticate;
1538
                                char const* scheme = www_auth->au_scheme;
1539
                                const char* realm = msg_params_find(www_auth->au_params, "realm=");
1540
                                char auth[100];
1541
                                memset(auth, 0, 100);
1542
                                g_snprintf(auth, 100, "%s:%s:%s:%s", scheme, realm,
1543
                                        session->account.username ? session->account.username : "null",
1544
                                        session->account.secret ? session->account.secret : "null");
1545
                                JANUS_LOG(LOG_VERB, "\t%s\n", auth);
1546
                                /* Authenticate */
1547
                                nua_authenticate(nh,
1548
                                        NUTAG_AUTH(auth),
1549
                                        TAG_END());
1550
                                break;
1551
                        } else if(status == 407) {
1552
                                 /* Get scheme/realm from 407 error, proxy-auth */
1553
                                sip_proxy_authenticate_t const* proxy_auth = sip->sip_proxy_authenticate;
1554
                                char const* scheme = proxy_auth->au_scheme;
1555
                                const char* realm = msg_params_find(proxy_auth->au_params, "realm=");
1556
                                char auth[100];
1557
                                memset(auth, 0, 100);
1558
                                g_snprintf(auth, 100, "%s:%s:%s:%s", scheme, realm,
1559
                                        session->account.username ? session->account.username : "null",
1560
                                        session->account.secret ? session->account.secret : "null");
1561
                                JANUS_LOG(LOG_VERB, "\t%s\n", auth);
1562
                                /* Authenticate */
1563
                                nua_authenticate(nh,
1564
                                        NUTAG_AUTH(auth),
1565
                                        TAG_END());
1566
                                break;
1567
                        } else if(status >= 400) {
1568
                                /* Something went wrong, notify the browser */
1569
                                session->status = janus_sip_status_registered;
1570
                                char reason[100];
1571
                                memset(reason, 0, 100);
1572
                                g_snprintf(reason, 100, "%d %s", status, phrase);
1573
                                json_t *call = json_object();
1574
                                json_object_set_new(call, "sip", json_string("event"));
1575
                                json_t *calling = json_object();
1576
                                json_object_set_new(calling, "event", json_string("hangup"));
1577
                                json_object_set_new(calling, "username", json_string(session->callee));
1578
                                json_object_set_new(calling, "reason", json_string(reason));
1579
                                json_object_set_new(call, "result", calling);
1580
                                char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1581
                                json_decref(call);
1582
                                JANUS_LOG(LOG_VERB, "Pushing event: %s\n", call_text);
1583
                                int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call_text, NULL, NULL);
1584
                                JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1585
                                g_free(call_text);
1586
                                /* Get rid of any PeerConnection that may have been set up in the meanwhile */
1587
                                if(session->transaction)
1588
                                        g_free(session->transaction);
1589
                                session->transaction = NULL;
1590
                                gateway->close_pc(session->handle);
1591
                                break;
1592
                        }
1593
                        ssip_t *ssip = session->stack;
1594
                        sdp_parser_t *parser = sdp_parse(ssip->s_home, sip->sip_payload->pl_data, sip->sip_payload->pl_len, 0);
1595
                        if(!sdp_session(parser)) {
1596
                                JANUS_LOG(LOG_ERR, "\tError parsing SDP!\n");
1597
                                nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
1598
                                break;
1599
                        }
1600
                        JANUS_LOG(LOG_VERB, "Peer accepted our call:\n%s", sip->sip_payload->pl_data);
1601
                        session->status = janus_sip_status_incall;
1602
                        char *fixed_sdp = g_strdup(sip->sip_payload->pl_data);
1603
                        if(fixed_sdp == NULL) {
1604
                                JANUS_LOG(LOG_FATAL, "Memory error!\n");
1605
                                nua_respond(nh, 500, sip_status_phrase(500), TAG_END());
1606
                                break;
1607
                        }
1608
                        sdp_session_t *sdp = sdp_session(parser);
1609
                        janus_sip_sdp_process(session, sdp);
1610
                        session->media.ready = 1;        /* FIXME Maybe we need a better way to signal this */
1611
                        GError *error = NULL;
1612
                        g_thread_try_new("janus rtp handler", janus_sip_relay_thread, session, &error);
1613
                        if(error != NULL) {
1614
                                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the RTP/RTCP thread...\n", error->code, error->message ? error->message : "??");
1615
                        }
1616
                        /* Send SDP to the browser */
1617
                        session->status = janus_sip_status_incall;
1618
                        json_t *call = json_object();
1619
                        json_object_set_new(call, "sip", json_string("event"));
1620
                        json_t *calling = json_object();
1621
                        json_object_set_new(calling, "event", json_string("accepted"));
1622
                        json_object_set_new(calling, "username", json_string(session->callee));
1623
                        json_object_set_new(call, "result", calling);
1624
                        char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1625
                        json_decref(call);
1626
                        JANUS_LOG(LOG_VERB, "Pushing event to peer: %s\n", call_text);
1627
                        int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call_text, "answer", fixed_sdp);
1628
                        JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1629
                        g_free(call_text);
1630
                        break;
1631
                }
1632
                case nua_r_register: {
1633
                        JANUS_LOG(LOG_VERB, "[%s]: %d %s\n", nua_event_name(event), status, phrase ? phrase : "??");
1634
                        if(status == 200) {
1635
                                if(session->status < janus_sip_status_registered)
1636
                                        session->status = janus_sip_status_registered;
1637
                                JANUS_LOG(LOG_VERB, "Successfully registered\n");
1638
                                /* Notify the browser */
1639
                                json_t *call = json_object();
1640
                                json_object_set_new(call, "sip", json_string("event"));
1641
                                json_t *calling = json_object();
1642
                                json_object_set_new(calling, "event", json_string("registered"));
1643
                                json_object_set_new(calling, "username", json_string(session->account.username));
1644
                                json_object_set_new(call, "result", calling);
1645
                                char *call_text = json_dumps(call, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1646
                                json_decref(call);
1647
                                JANUS_LOG(LOG_VERB, "Pushing event: %s\n", call_text);
1648
                                int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call_text, NULL, NULL);
1649
                                JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1650
                                g_free(call_text);
1651
                        } else if(status == 401) {
1652
                                /* Get scheme/realm from 401 error */
1653
                                sip_www_authenticate_t const* www_auth = sip->sip_www_authenticate;
1654
                                char const* scheme = www_auth->au_scheme;
1655
                                const char* realm = msg_params_find(www_auth->au_params, "realm=");
1656
                                char auth[100];
1657
                                memset(auth, 0, 100);
1658
                                g_snprintf(auth, 100, "%s:%s:%s:%s", scheme, realm, session->account.username, session->account.secret);
1659
                                JANUS_LOG(LOG_VERB, "\t%s\n", auth);
1660
                                /* Authenticate */
1661
                                nua_authenticate(nh,
1662
                                        NUTAG_AUTH(auth),
1663
                                        TAG_END());
1664
                        } else if(status >= 400) {
1665
                                /* Authentication failed? */
1666
                                session->status = janus_sip_status_failed;
1667
                                /* Tell the browser... */
1668
                                json_t *event = json_object();
1669
                                json_object_set_new(event, "sip", json_string("event"));
1670
                                char error_cause[256];
1671
                                g_snprintf(error_cause, 512, "Registration failed: %d %s", status, phrase ? phrase : "??");
1672
                                json_object_set_new(event, "error", json_string(error_cause));
1673
                                char *event_text = json_dumps(event, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
1674
                                json_decref(event);
1675
                                JANUS_LOG(LOG_VERB, "Pushing event: %s\n", event_text);
1676
                                int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, event_text, NULL, NULL);
1677
                                JANUS_LOG(LOG_VERB, "  >> %d (%s)\n", ret, janus_get_api_error(ret));
1678
                                g_free(event_text);
1679
                        }
1680
                        break;
1681
                }
1682
                default:
1683
                        /* unknown event -> print out error message */
1684
                        JANUS_LOG(LOG_ERR, "Unknown event %d (%s)\n", event, nua_event_name(event));
1685
                        break;
1686
        }
1687
}
1688

    
1689
void janus_sip_sdp_process(janus_sip_session *session, sdp_session_t *sdp) {
1690
        if(!session || !sdp)
1691
                return;
1692
        /* c= */
1693
        if(sdp->sdp_connection && sdp->sdp_connection->c_address) {
1694
                if(session->media.remote_ip != NULL)
1695
                        g_free(session->media.remote_ip);
1696
                session->media.remote_ip = g_strdup(sdp->sdp_connection->c_address);
1697
                JANUS_LOG(LOG_VERB, "  >> Media connection:\n");
1698
                JANUS_LOG(LOG_VERB, "       %s\n", session->media.remote_ip);
1699
        }
1700
        JANUS_LOG(LOG_VERB, "  >> Media lines:\n");
1701
        sdp_media_t *m = sdp->sdp_media;
1702
        while(m) {
1703
                if(m->m_type == sdp_media_audio) {
1704
                        JANUS_LOG(LOG_VERB, "       Audio: %lu\n", m->m_port);
1705
                        if(m->m_port) {
1706
                                session->media.has_audio = 1;
1707
                                session->media.remote_audio_rtp_port = m->m_port;
1708
                                session->media.remote_audio_rtcp_port = m->m_port+1;        /* FIXME We're assuming RTCP is on the next port */
1709
                        }
1710
                } else if(m->m_type == sdp_media_video) {
1711
                        JANUS_LOG(LOG_VERB, "       Video: %lu\n", m->m_port);
1712
                        if(m->m_port) {
1713
                                session->media.has_video = 1;
1714
                                session->media.remote_video_rtp_port = m->m_port;
1715
                                session->media.remote_video_rtcp_port = m->m_port+1;        /* FIXME We're assuming RTCP is on the next port */
1716
                        }
1717
                } else {
1718
                        JANUS_LOG(LOG_WARN, "       Unsupported media line (not audio/video)\n");
1719
                        m = m->m_next;
1720
                        continue;
1721
                }
1722
                JANUS_LOG(LOG_VERB, "       Media connections:\n");
1723
                if(m->m_connections) {
1724
                        sdp_connection_t *c = m->m_connections;
1725
                        while(c) {
1726
                                if(c->c_address) {
1727
                                        if(session->media.remote_ip != NULL)
1728
                                                g_free(session->media.remote_ip);
1729
                                        session->media.remote_ip = g_strdup(c->c_address);
1730
                                        JANUS_LOG(LOG_VERB, "         [%s]\n", session->media.remote_ip);
1731
                                }
1732
                                c = c->c_next;
1733
                        }
1734
                }
1735
                JANUS_LOG(LOG_VERB, "       Media RTP maps:\n");
1736
                sdp_rtpmap_t *r = m->m_rtpmaps;
1737
                while(r) {
1738
                        JANUS_LOG(LOG_VERB, "         [%u] %s\n", r->rm_pt, r->rm_encoding);
1739
                        r = r->rm_next;
1740
                }
1741
                JANUS_LOG(LOG_VERB, "       Media attributes:\n");
1742
                sdp_attribute_t *a = m->m_attributes;
1743
                while(a) {
1744
                        if(a->a_name) {
1745
                                if(!strcasecmp(a->a_name, "rtpmap")) {
1746
                                        JANUS_LOG(LOG_VERB, "         RTP Map:     %s\n", a->a_value);
1747
                                }
1748
                        }
1749
                        a = a->a_next;
1750
                }
1751
                m = m->m_next;
1752
        }
1753
}
1754

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

    
1874
/* Thread to relay RTP/RTCP frames coming from the SIP peer */
1875
static void *janus_sip_relay_thread(void *data) {
1876
        janus_sip_session *session = (janus_sip_session *)data;
1877
        if(!session || !session->account.username || !session->callee) {
1878
                g_thread_unref(g_thread_self());
1879
                return NULL;
1880
        }
1881
        JANUS_LOG(LOG_VERB, "Starting relay thread (%s <--> %s)\n", session->account.username, session->callee);
1882
        /* Socket stuff */
1883
        int maxfd = 0;
1884
        if(session->media.audio_rtp_fd > maxfd)
1885
                maxfd = session->media.audio_rtp_fd;
1886
        if(session->media.audio_rtcp_fd > maxfd)
1887
                maxfd = session->media.audio_rtcp_fd;
1888
        if(session->media.video_rtp_fd > maxfd)
1889
                maxfd = session->media.video_rtp_fd;
1890
        if(session->media.video_rtcp_fd > maxfd)
1891
                maxfd = session->media.video_rtcp_fd;
1892
        //~ /* Wait for the remote information */
1893
        //~ while(!session->media.ready) {
1894
                //~ 
1895
        //~ }
1896
        /* Connect peers (FIXME This pretty much sucks right now) */
1897
        if(session->media.remote_audio_rtp_port) {
1898
                struct sockaddr_in server_addr;
1899
                server_addr.sin_family = AF_INET;
1900
                if((inet_aton(session->media.remote_ip, &server_addr.sin_addr)) <= 0) {        /* Not a numeric IP... */
1901
                        struct hostent *host = gethostbyname(session->media.remote_ip);        /* ...resolve name */
1902
                        if(!host) {
1903
                                JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't get host (%s)\n", session->account.username, session->media.remote_ip);
1904
                        } else {
1905
                                server_addr.sin_addr = *(struct in_addr *)host->h_addr_list;
1906
                        }
1907
                }
1908
                server_addr.sin_port = htons(session->media.remote_audio_rtp_port);
1909
                memset(&(server_addr.sin_zero), '\0', 8);
1910
                if(connect(session->media.audio_rtp_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
1911
                        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);
1912
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
1913
                }
1914
        }
1915
        if(session->media.remote_audio_rtcp_port) {
1916
                struct sockaddr_in server_addr;
1917
                server_addr.sin_family = AF_INET;
1918
                if((inet_aton(session->media.remote_ip, &server_addr.sin_addr)) <= 0) {        /* Not a numeric IP... */
1919
                        struct hostent *host = gethostbyname(session->media.remote_ip);        /* ...resolve name */
1920
                        if(!host) {
1921
                                JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't get host (%s)\n", session->account.username, session->media.remote_ip);
1922
                        } else {
1923
                                server_addr.sin_addr = *(struct in_addr *)host->h_addr_list;
1924
                        }
1925
                }
1926
                server_addr.sin_port = htons(session->media.remote_audio_rtcp_port);
1927
                memset(&(server_addr.sin_zero), '\0', 8);
1928
                if(connect(session->media.audio_rtcp_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
1929
                        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);
1930
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
1931
                }
1932
        }
1933
        if(session->media.remote_video_rtp_port) {
1934
                struct sockaddr_in server_addr;
1935
                server_addr.sin_family = AF_INET;
1936
                if((inet_aton(session->media.remote_ip, &server_addr.sin_addr)) <= 0) {        /* Not a numeric IP... */
1937
                        struct hostent *host = gethostbyname(session->media.remote_ip);        /* ...resolve name */
1938
                        if(!host) {
1939
                                JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't get host (%s)\n", session->account.username, session->media.remote_ip);
1940
                        } else {
1941
                                server_addr.sin_addr = *(struct in_addr *)host->h_addr_list;
1942
                        }
1943
                }
1944
                server_addr.sin_port = htons(session->media.remote_video_rtp_port);
1945
                memset(&(server_addr.sin_zero), '\0', 8);
1946
                if(connect(session->media.video_rtp_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
1947
                        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);
1948
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
1949
                }
1950
        }
1951
        if(session->media.remote_video_rtcp_port) {
1952
                struct sockaddr_in server_addr;
1953
                server_addr.sin_family = AF_INET;
1954
                if((inet_aton(session->media.remote_ip, &server_addr.sin_addr)) <= 0) {        /* Not a numeric IP... */
1955
                        struct hostent *host = gethostbyname(session->media.remote_ip);        /* ...resolve name */
1956
                        if(!host) {
1957
                                JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't get host (%s)\n", session->account.username, session->media.remote_ip);
1958
                        } else {
1959
                                server_addr.sin_addr = *(struct in_addr *)host->h_addr_list;
1960
                        }
1961
                }
1962
                server_addr.sin_port = htons(session->media.remote_video_rtcp_port);
1963
                memset(&(server_addr.sin_zero), '\0', 8);
1964
                if(connect(session->media.video_rtcp_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
1965
                        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);
1966
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
1967
                }
1968
        }
1969

    
1970
        if(!session->callee) {
1971
                JANUS_LOG(LOG_VERB, "[SIP-%s] Leaving thread, no callee...\n", session->account.username);
1972
                g_thread_unref(g_thread_self());
1973
                return NULL; 
1974
        }
1975
        /* Loop */
1976
        socklen_t addrlen;
1977
        struct sockaddr_in remote;
1978
        int resfd = 0, bytes = 0;
1979
        struct pollfd fds[4];
1980
        char buffer[1500];
1981
        memset(buffer, 0, 1500);
1982
        while(session != NULL && !session->destroyed &&
1983
                        session->status > janus_sip_status_registered &&
1984
                        session->status < janus_sip_status_closing) {        /* FIXME We need a per-call watchdog as well */
1985
                /* Wait for some data */
1986
                fds[0].fd = 0;
1987
                fds[0].events = 0;
1988
                fds[0].revents = 0;
1989
                if(session->media.audio_rtp_fd > 0) {
1990
                        fds[0].fd = session->media.audio_rtp_fd;
1991
                        fds[0].events = POLLIN;
1992
                }
1993
                fds[1].fd = 0;
1994
                fds[1].events = 0;
1995
                fds[1].revents = 0;
1996
                if(session->media.audio_rtcp_fd > 0) {
1997
                        fds[1].fd = session->media.audio_rtcp_fd;
1998
                        fds[1].events = POLLIN;
1999
                }
2000
                fds[2].fd = 0;
2001
                fds[2].events = 0;
2002
                fds[2].revents = 0;
2003
                if(session->media.video_rtp_fd > 0) {
2004
                        fds[2].fd = session->media.video_rtp_fd;
2005
                        fds[2].events = POLLIN;
2006
                }
2007
                fds[3].fd = 0;
2008
                fds[3].events = 0;
2009
                fds[3].revents = 0;
2010
                if(session->media.video_rtcp_fd > 0) {
2011
                        fds[3].fd = session->media.video_rtcp_fd;
2012
                        fds[3].events = POLLIN;
2013
                }
2014
                resfd = poll(fds, 4, 1000);
2015
                if(resfd < 0) {
2016
                        JANUS_LOG(LOG_ERR, "[SIP-%s] Error polling...\n", session->account.username);
2017
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2018
                        break;
2019
                } else if(resfd == 0) {
2020
                        /* No data, keep going */
2021
                        continue;
2022
                }
2023
                if(session == NULL || session->destroyed ||
2024
                                session->status <= janus_sip_status_registered ||
2025
                                session->status >= janus_sip_status_closing)
2026
                        break;
2027
                if(session->media.audio_rtp_fd && (fds[0].revents & POLLIN)) {
2028
                        /* Got something audio (RTP) */
2029
                        fds[0].revents = 0;
2030
                        addrlen = sizeof(remote);
2031
                        bytes = recvfrom(session->media.audio_rtp_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
2032
                        //~ JANUS_LOG(LOG_VERB, "************************\nGot %d bytes on the audio RTP channel...\n", bytes);
2033
                        //~ rtp_header_t *rtp = (rtp_header_t *)buffer;
2034
                        //~ JANUS_LOG(LOG_VERB, " ... parsed RTP packet (ssrc=%u, pt=%u, seq=%u, ts=%u)...\n",
2035
                                //~ ntohl(rtp->ssrc), rtp->type, ntohs(rtp->seq_number), ntohl(rtp->timestamp));
2036
                        if(session->media.audio_ssrc_peer == 0) {
2037
                                rtp_header *header = (rtp_header *)buffer;
2038
                                session->media.audio_ssrc_peer = ntohl(header->ssrc);
2039
                                JANUS_LOG(LOG_VERB, "Got SIP peer audio SSRC: %"SCNu32"\n", session->media.audio_ssrc_peer);
2040
                        }
2041
                        /* Relay to browser */
2042
                        gateway->relay_rtp(session->handle, 0, buffer, bytes);
2043
                        continue;
2044
                }
2045
                if(session->media.audio_rtcp_fd && (fds[1].revents & POLLIN)) {
2046
                        /* Got something audio (RTCP) */
2047
                        fds[1].revents = 0;
2048
                        addrlen = sizeof(remote);
2049
                        bytes = recvfrom(session->media.audio_rtcp_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
2050
                        //~ JANUS_LOG(LOG_VERB, "************************\nGot %d bytes on the audio RTCP channel...\n", bytes);
2051
                        //~ rtp_header_t *rtp = (rtp_header_t *)buffer;
2052
                        //~ JANUS_LOG(LOG_VERB, " ... parsed RTP packet (ssrc=%u, pt=%u, seq=%u, ts=%u)...\n",
2053
                                //~ ntohl(rtp->ssrc), rtp->type, ntohs(rtp->seq_number), ntohl(rtp->timestamp));
2054
                        /* Relay to browser */
2055
                        gateway->relay_rtcp(session->handle, 0, buffer, bytes);
2056
                        continue;
2057
                }
2058
                if(session->media.video_rtp_fd && (fds[2].revents & POLLIN)) {
2059
                        /* Got something video (RTP) */
2060
                        fds[2].revents = 0;
2061
                        addrlen = sizeof(remote);
2062
                        bytes = recvfrom(session->media.video_rtp_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
2063
                        //~ JANUS_LOG(LOG_VERB, "************************\nGot %d bytes on the video RTP channel...\n", bytes);
2064
                        //~ rtp_header_t *rtp = (rtp_header_t *)buffer;
2065
                        //~ JANUS_LOG(LOG_VERB, " ... parsed RTP packet (ssrc=%u, pt=%u, seq=%u, ts=%u)...\n",
2066
                                //~ ntohl(rtp->ssrc), rtp->type, ntohs(rtp->seq_number), ntohl(rtp->timestamp));
2067
                        if(session->media.video_ssrc_peer == 0) {
2068
                                rtp_header *header = (rtp_header *)buffer;
2069
                                session->media.video_ssrc_peer = ntohl(header->ssrc);
2070
                                JANUS_LOG(LOG_VERB, "Got SIP peer video SSRC: %"SCNu32"\n", session->media.video_ssrc_peer);
2071
                        }
2072
                        /* Relay to browser */
2073
                        gateway->relay_rtp(session->handle, 1, buffer, bytes);
2074
                        continue;
2075
                }
2076
                if(session->media.video_rtcp_fd && (fds[3].revents & POLLIN)) {
2077
                        /* Got something video (RTCP) */
2078
                        fds[3].revents = 0;
2079
                        addrlen = sizeof(remote);
2080
                        bytes = recvfrom(session->media.video_rtcp_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
2081
                        //~ JANUS_LOG(LOG_VERB, "************************\nGot %d bytes on the video RTCP channel...\n", bytes);
2082
                        //~ rtp_header_t *rtp = (rtp_header_t *)buffer;
2083
                        //~ JANUS_LOG(LOG_VERB, " ... parsed RTP packet (ssrc=%u, pt=%u, seq=%u, ts=%u)...\n",
2084
                                //~ ntohl(rtp->ssrc), rtp->type, ntohs(rtp->seq_number), ntohl(rtp->timestamp));
2085
                        /* Relay to browser */
2086
                        gateway->relay_rtcp(session->handle, 1, buffer, bytes);
2087
                        continue;
2088
                }
2089
        }
2090
        JANUS_LOG(LOG_VERB, "Leaving SIP relay thread\n");
2091
        g_thread_unref(g_thread_self());
2092
        return NULL;
2093
}
2094

    
2095

    
2096
/* Sofia Event thread */
2097
gpointer janus_sip_sofia_thread(gpointer user_data) {
2098
        janus_sip_session *session = (janus_sip_session *)user_data;
2099
        if(session == NULL || session->account.username == NULL || session->stack == NULL) {
2100
                g_thread_unref(g_thread_self());
2101
                return NULL;
2102
        }
2103
        JANUS_LOG(LOG_VERB, "Joining sofia loop thread (%s)...\n", session->account.username);
2104
        session->stack->s_root = su_root_create(session->stack);
2105
        JANUS_LOG(LOG_VERB, "Setting up sofia stack (sip:%s@%s)\n", session->account.username, local_ip);
2106
        char sip_url[128];
2107
        char sips_url[128];
2108
        char *ipv6;
2109
        ipv6 = strstr(local_ip, ":");
2110
        g_snprintf(sip_url, sizeof(sip_url), "sip:%s%s%s:*", ipv6 ? "[" : "", local_ip, ipv6 ? "]" : "");
2111
        g_snprintf(sips_url, sizeof(sips_url), "sips:%s%s%s:*", ipv6 ? "[" : "", local_ip, ipv6 ? "]" : "");
2112
        char outbound_options[256] = "use-rport no-validate";
2113
        if(keepalive_interval > 0)
2114
                g_strlcat(outbound_options, " options-keepalive", sizeof(outbound_options));
2115
        if(!behind_nat)
2116
                g_strlcat(outbound_options, " no-natify", sizeof(outbound_options));
2117
        session->stack->s_nua = nua_create(session->stack->s_root,
2118
                                janus_sip_sofia_callback,
2119
                                session,
2120
                                TPTAG_SERVER(0),
2121
                                SIPTAG_ALLOW_STR("INVITE, ACK, BYE, CANCEL, OPTIONS"),
2122
                                NUTAG_M_USERNAME(session->account.username),
2123
                                NUTAG_URL(sip_url),
2124
                                NUTAG_SIPS_URL(sips_url),
2125
                                SIPTAG_USER_AGENT_STR(user_agent),
2126
                                NUTAG_KEEPALIVE(keepalive_interval * 1000),        /* Sofia expects it in milliseconds */
2127
                                NUTAG_OUTBOUND(outbound_options),
2128
                                SIPTAG_SUPPORTED(NULL),
2129
                                TAG_NULL());
2130
        su_root_run(session->stack->s_root);
2131
        /* When we get here, we're done */
2132
        nua_destroy(session->stack->s_nua);
2133
        su_root_destroy(session->stack->s_root);
2134
        session->stack->s_root = NULL;
2135
        su_home_deinit(session->stack->s_home);
2136
        su_deinit();
2137
        //~ stop = 1;
2138
        JANUS_LOG(LOG_VERB, "Leaving sofia loop thread...\n");
2139
        g_thread_unref(g_thread_self());
2140
        return NULL;
2141
}