Statistics
| Branch: | Revision:

janus-gateway / plugins / janus_sip.c @ d4f87512

History | View | Annotate | Download (155 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. Calls can do plain RTP or SDES-SRTP.
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
 * \section sipapi SIP Plugin API
27
 *
28
 * All requests you can send in the SIP Plugin API are asynchronous,
29
 * which means all responses (successes and errors) will be delivered
30
 * as events with the same transaction.
31
 *
32
 * The supported requests are \c register , \c unregister , \c call ,
33
 * \c accept, \c info , \c message , \c dtmf_info , \c recording ,
34
 * \c hold , \c unhold and \c hangup . \c register can be used,
35
 * as the name suggests, to register a username at a SIP registrar to
36
 * call and be called, while \c unregister unregisters it; \c call is used
37
 * to send an INVITE to a different SIP URI through the plugin, while
38
 * \c accept is used to accept the call in case one is invited instead
39
 * of inviting; \c hold and \c unhold can be used respectively to put a
40
 * call on-hold and to resume it; \c info allows you to send a generic
41
 * SIP INFO request, while \c dtmf_info is focused on using INFO for DTMF
42
 * instead; \c message is the method you use to send a SIP message
43
 * to the other peer; \c recording is used, instead, to record the
44
 * conversation to one or more .mjr files (depending on the direction you
45
 * want to record); finally, \c hangup can be used to terminate the
46
 * communication at any time, either to hangup (BYE) an ongoing call or
47
 * to cancel/decline (CANCEL/BYE) a call that hasn't started yet.
48
 *
49
 * Actual API docs: TBD.
50
 *
51
 * \ingroup plugins
52
 * \ref plugins
53
 */
54

    
55
#include "plugin.h"
56

    
57
#include <arpa/inet.h>
58
#include <net/if.h>
59

    
60
#include <jansson.h>
61

    
62
#include <sofia-sip/msg_header.h>
63
#include <sofia-sip/nua.h>
64
#include <sofia-sip/sdp.h>
65
#include <sofia-sip/sip_status.h>
66
#include <sofia-sip/url.h>
67
#include <sofia-sip/tport_tag.h>
68
#include <sofia-sip/su_log.h>
69

    
70
#include "../debug.h"
71
#include "../apierror.h"
72
#include "../config.h"
73
#include "../mutex.h"
74
#include "../record.h"
75
#include "../rtp.h"
76
#include "../rtcp.h"
77
#include "../sdp-utils.h"
78
#include "../utils.h"
79
#include "../ip-utils.h"
80

    
81

    
82
/* Plugin information */
83
#define JANUS_SIP_VERSION                        6
84
#define JANUS_SIP_VERSION_STRING        "0.0.6"
85
#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."
86
#define JANUS_SIP_NAME                                "JANUS SIP plugin"
87
#define JANUS_SIP_AUTHOR                        "Meetecho s.r.l."
88
#define JANUS_SIP_PACKAGE                        "janus.plugin.sip"
89

    
90
/* Plugin methods */
91
janus_plugin *create(void);
92
int janus_sip_init(janus_callbacks *callback, const char *config_path);
93
void janus_sip_destroy(void);
94
int janus_sip_get_api_compatibility(void);
95
int janus_sip_get_version(void);
96
const char *janus_sip_get_version_string(void);
97
const char *janus_sip_get_description(void);
98
const char *janus_sip_get_name(void);
99
const char *janus_sip_get_author(void);
100
const char *janus_sip_get_package(void);
101
void janus_sip_create_session(janus_plugin_session *handle, int *error);
102
struct janus_plugin_result *janus_sip_handle_message(janus_plugin_session *handle, char *transaction, json_t *message, json_t *jsep);
103
void janus_sip_setup_media(janus_plugin_session *handle);
104
void janus_sip_incoming_rtp(janus_plugin_session *handle, int video, char *buf, int len);
105
void janus_sip_incoming_rtcp(janus_plugin_session *handle, int video, char *buf, int len);
106
void janus_sip_hangup_media(janus_plugin_session *handle);
107
void janus_sip_destroy_session(janus_plugin_session *handle, int *error);
108
json_t *janus_sip_query_session(janus_plugin_session *handle);
109

    
110
/* Plugin setup */
111
static janus_plugin janus_sip_plugin =
112
        JANUS_PLUGIN_INIT (
113
                .init = janus_sip_init,
114
                .destroy = janus_sip_destroy,
115

    
116
                .get_api_compatibility = janus_sip_get_api_compatibility,
117
                .get_version = janus_sip_get_version,
118
                .get_version_string = janus_sip_get_version_string,
119
                .get_description = janus_sip_get_description,
120
                .get_name = janus_sip_get_name,
121
                .get_author = janus_sip_get_author,
122
                .get_package = janus_sip_get_package,
123

    
124
                .create_session = janus_sip_create_session,
125
                .handle_message = janus_sip_handle_message,
126
                .setup_media = janus_sip_setup_media,
127
                .incoming_rtp = janus_sip_incoming_rtp,
128
                .incoming_rtcp = janus_sip_incoming_rtcp,
129
                .hangup_media = janus_sip_hangup_media,
130
                .destroy_session = janus_sip_destroy_session,
131
                .query_session = janus_sip_query_session,
132
        );
133

    
134
/* Plugin creator */
135
janus_plugin *create(void) {
136
        JANUS_LOG(LOG_VERB, "%s created!\n", JANUS_SIP_NAME);
137
        return &janus_sip_plugin;
138
}
139

    
140
/* Parameter validation */
141
static struct janus_json_parameter request_parameters[] = {
142
        {"request", JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
143
};
144
static struct janus_json_parameter register_parameters[] = {
145
        {"type", JSON_STRING, 0},
146
        {"send_register", JANUS_JSON_BOOL, 0},
147
        {"sips", JANUS_JSON_BOOL, 0},
148
        {"username", JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
149
        {"secret", JSON_STRING, 0},
150
        {"ha1_secret", JSON_STRING, 0},
151
        {"authuser", JSON_STRING, 0},
152
        {"headers", JSON_OBJECT, 0},
153
        {"refresh", JANUS_JSON_BOOL, 0}
154
};
155
static struct janus_json_parameter proxy_parameters[] = {
156
        {"proxy", JSON_STRING, 0},
157
        {"outbound_proxy", JSON_STRING, 0}
158
};
159
static struct janus_json_parameter call_parameters[] = {
160
        {"uri", JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
161
        {"autoack", JANUS_JSON_BOOL, 0},
162
        {"headers", JSON_OBJECT, 0},
163
        {"srtp", JSON_STRING, 0}
164
};
165
static struct janus_json_parameter accept_parameters[] = {
166
        {"srtp", JSON_STRING, 0}
167
};
168
static struct janus_json_parameter recording_parameters[] = {
169
        {"action", JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
170
        {"audio", JANUS_JSON_BOOL, 0},
171
        {"video", JANUS_JSON_BOOL, 0},
172
        {"peer_audio", JANUS_JSON_BOOL, 0},
173
        {"peer_video", JANUS_JSON_BOOL, 0},
174
        {"filename", JSON_STRING, 0}
175
};
176
static struct janus_json_parameter dtmf_info_parameters[] = {
177
        {"digit", JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
178
        {"duration", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE}
179
};
180
static struct janus_json_parameter info_parameters[] = {
181
        {"type", JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
182
        {"content", JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
183
};
184
static struct janus_json_parameter sipmessage_parameters[] = {
185
        {"content", JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
186
};
187

    
188
/* Useful stuff */
189
static volatile gint initialized = 0, stopping = 0;
190
static gboolean notify_events = TRUE;
191
static janus_callbacks *gateway = NULL;
192

    
193
static char *local_ip = NULL;
194
static int keepalive_interval = 120;
195
static gboolean behind_nat = FALSE;
196
static char *user_agent;
197
#define JANUS_DEFAULT_REGISTER_TTL        3600
198
static int register_ttl = JANUS_DEFAULT_REGISTER_TTL;
199

    
200
static GThread *handler_thread;
201
static GThread *watchdog;
202
static void *janus_sip_handler(void *data);
203

    
204
typedef struct janus_sip_message {
205
        janus_plugin_session *handle;
206
        char *transaction;
207
        json_t *message;
208
        json_t *jsep;
209
} janus_sip_message;
210
static GAsyncQueue *messages = NULL;
211
static janus_sip_message exit_message;
212

    
213
static void janus_sip_message_free(janus_sip_message *msg) {
214
        if(!msg || msg == &exit_message)
215
                return;
216

    
217
        msg->handle = NULL;
218

    
219
        g_free(msg->transaction);
220
        msg->transaction = NULL;
221
        if(msg->message)
222
                json_decref(msg->message);
223
        msg->message = NULL;
224
        if(msg->jsep)
225
                json_decref(msg->jsep);
226
        msg->jsep = NULL;
227

    
228
        g_free(msg);
229
}
230

    
231

    
232
typedef enum {
233
        janus_sip_registration_status_disabled = -2,
234
        janus_sip_registration_status_failed = -1,
235
        janus_sip_registration_status_unregistered = 0,
236
        janus_sip_registration_status_registering,
237
        janus_sip_registration_status_registered,
238
        janus_sip_registration_status_unregistering,
239
} janus_sip_registration_status;
240

    
241
static const char *janus_sip_registration_status_string(janus_sip_registration_status status) {
242
        switch(status) {
243
                case janus_sip_registration_status_disabled:
244
                        return "disabled";
245
                case janus_sip_registration_status_failed:
246
                        return "failed";
247
                case janus_sip_registration_status_unregistered:
248
                        return "unregistered";
249
                case janus_sip_registration_status_registering:
250
                        return "registering";
251
                case janus_sip_registration_status_registered:
252
                        return "registered";
253
                case janus_sip_registration_status_unregistering:
254
                        return "unregistering";
255
                default:
256
                        return "unknown";
257
        }
258
}
259

    
260

    
261
typedef enum {
262
        janus_sip_call_status_idle = 0,
263
        janus_sip_call_status_inviting,
264
        janus_sip_call_status_invited,
265
        janus_sip_call_status_incall,
266
        janus_sip_call_status_closing,
267
} janus_sip_call_status;
268

    
269
static const char *janus_sip_call_status_string(janus_sip_call_status status) {
270
        switch(status) {
271
                case janus_sip_call_status_idle:
272
                        return "idle";
273
                case janus_sip_call_status_inviting:
274
                        return "inviting";
275
                case janus_sip_call_status_invited:
276
                        return "invited";
277
                case janus_sip_call_status_incall:
278
                        return "incall";
279
                case janus_sip_call_status_closing:
280
                        return "closing";
281
                default:
282
                        return "unknown";
283
        }
284
}
285

    
286

    
287
/* Sofia stuff */
288
typedef struct ssip_s ssip_t;
289
typedef struct ssip_oper_s ssip_oper_t;
290

    
291
typedef enum {
292
        janus_sip_secret_type_plaintext = 1,
293
        janus_sip_secret_type_hashed = 2,
294
        janus_sip_secret_type_unknown
295
} janus_sip_secret_type;
296

    
297
typedef struct janus_sip_account {
298
        char *identity;
299
        char *user_agent;                /* Used to override the general UA string */
300
        gboolean sips;
301
        char *username;
302
        char *display_name;                /* Used for outgoing calls in the From header */
303
        char *authuser;                        /**< username to use for authentication */
304
        char *secret;
305
        janus_sip_secret_type secret_type;
306
        int sip_port;
307
        char *proxy;
308
        char *outbound_proxy;
309
        janus_sip_registration_status registration_status;
310
} janus_sip_account;
311

    
312
typedef struct janus_sip_media {
313
        char *remote_ip;
314
        gboolean earlymedia;
315
        gboolean ready;
316
        gboolean autoack;
317
        gboolean require_srtp, has_srtp_local, has_srtp_remote;
318
        gboolean on_hold;
319
        gboolean has_audio;
320
        int audio_rtp_fd, audio_rtcp_fd;
321
        int local_audio_rtp_port, remote_audio_rtp_port;
322
        int local_audio_rtcp_port, remote_audio_rtcp_port;
323
        guint32 audio_ssrc, audio_ssrc_peer;
324
        int audio_pt;
325
        const char *audio_pt_name;
326
        srtp_t audio_srtp_in, audio_srtp_out;
327
        srtp_policy_t audio_remote_policy, audio_local_policy;
328
        int audio_srtp_suite_in, audio_srtp_suite_out;
329
        gboolean audio_send;
330
        janus_sdp_mdirection pre_hold_audio_dir;
331
        gboolean has_video;
332
        int video_rtp_fd, video_rtcp_fd;
333
        int local_video_rtp_port, remote_video_rtp_port;
334
        int local_video_rtcp_port, remote_video_rtcp_port;
335
        guint32 video_ssrc, video_ssrc_peer;
336
        int video_pt;
337
        const char *video_pt_name;
338
        srtp_t video_srtp_in, video_srtp_out;
339
        srtp_policy_t video_remote_policy, video_local_policy;
340
        int video_srtp_suite_in, video_srtp_suite_out;
341
        gboolean video_send;
342
        janus_sdp_mdirection pre_hold_video_dir;
343
        janus_rtp_switching_context context;
344
        int pipefd[2];
345
        gboolean updated;
346
} janus_sip_media;
347

    
348
typedef struct janus_sip_session {
349
        janus_plugin_session *handle;
350
        ssip_t *stack;
351
        janus_sip_account account;
352
        janus_sip_call_status status;
353
        janus_sip_media media;
354
        char *transaction;
355
        char *callee;
356
        char *callid;
357
        janus_sdp *sdp;                                /* The SDP this user sent */
358
        janus_recorder *arc;                /* The Janus recorder instance for this user's audio, if enabled */
359
        janus_recorder *arc_peer;        /* The Janus recorder instance for the peer's audio, if enabled */
360
        janus_recorder *vrc;                /* The Janus recorder instance for this user's video, if enabled */
361
        janus_recorder *vrc_peer;        /* The Janus recorder instance for the peer's video, if enabled */
362
        janus_mutex rec_mutex;                /* Mutex to protect the recorders from race conditions */
363
        volatile gint hangingup;
364
        gint64 destroyed;        /* Time at which this session was marked as destroyed */
365
        janus_mutex mutex;
366
} janus_sip_session;
367
static GHashTable *sessions;
368
static GList *old_sessions;
369
static GHashTable *identities;
370
static GHashTable *callids;
371
static janus_mutex sessions_mutex;
372

    
373

    
374
#undef SU_ROOT_MAGIC_T
375
#define SU_ROOT_MAGIC_T        ssip_t
376
#undef NUA_MAGIC_T
377
#define NUA_MAGIC_T                ssip_t
378
#undef NUA_HMAGIC_T
379
#define NUA_HMAGIC_T        ssip_oper_t
380

    
381
struct ssip_s {
382
        su_home_t s_home[1];
383
        su_root_t *s_root;
384
        nua_t *s_nua;
385
        nua_handle_t *s_nh_r, *s_nh_i;
386
        janus_sip_session *session;
387
};
388

    
389

    
390
/* SRTP stuff (in case we need SDES) */
391
static int janus_sip_srtp_set_local(janus_sip_session *session, gboolean video, char **crypto) {
392
        if(session == NULL)
393
                return -1;
394
        /* Generate key/salt */
395
        uint8_t *key = g_malloc0(SRTP_MASTER_LENGTH);
396
        srtp_crypto_get_random(key, SRTP_MASTER_LENGTH);
397
        /* Set SRTP policies */
398
        srtp_policy_t *policy = video ? &session->media.video_local_policy : &session->media.audio_local_policy;
399
        srtp_crypto_policy_set_rtp_default(&(policy->rtp));
400
        srtp_crypto_policy_set_rtcp_default(&(policy->rtcp));
401
        policy->ssrc.type = ssrc_any_inbound;
402
        policy->key = key;
403
        policy->next = NULL;
404
        /* Create SRTP context */
405
        srtp_err_status_t res = srtp_create(video ? &session->media.video_srtp_out : &session->media.audio_srtp_out, policy);
406
        if(res != srtp_err_status_ok) {
407
                /* Something went wrong... */
408
                JANUS_LOG(LOG_ERR, "Oops, error creating outbound SRTP session: %d (%s)\n", res, janus_srtp_error_str(res));
409
                g_free(key);
410
                policy->key = NULL;
411
                return -2;
412
        }
413
        /* Base64 encode the salt */
414
        *crypto = g_base64_encode(key, SRTP_MASTER_LENGTH);
415
        if((video && session->media.video_srtp_out) || (!video && session->media.audio_srtp_out)) {
416
                JANUS_LOG(LOG_VERB, "%s outbound SRTP session created\n", video ? "Video" : "Audio");
417
        }
418
        return 0;
419
}
420
static int janus_sip_srtp_set_remote(janus_sip_session *session, gboolean video, const char *crypto, int suite) {
421
        if(session == NULL || crypto == NULL)
422
                return -1;
423
        /* Base64 decode the crypto string and set it as the remote SRTP context */
424
        gsize len = 0;
425
        guchar *decoded = g_base64_decode(crypto, &len);
426
        if(len < SRTP_MASTER_LENGTH) {
427
                /* FIXME Can this happen? */
428
                g_free(decoded);
429
                return -2;
430
        }
431
        /* Set SRTP policies */
432
        srtp_policy_t *policy = video ? &session->media.video_remote_policy : &session->media.audio_remote_policy;
433
        srtp_crypto_policy_set_rtp_default(&(policy->rtp));
434
        srtp_crypto_policy_set_rtcp_default(&(policy->rtcp));
435
        if(suite == 32) {
436
                srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&(policy->rtp));
437
                srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&(policy->rtcp));
438
        } else if(suite == 80) {
439
                srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&(policy->rtp));
440
                srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&(policy->rtcp));
441
        }
442
        policy->ssrc.type = ssrc_any_inbound;
443
        policy->key = decoded;
444
        policy->next = NULL;
445
        /* Create SRTP context */
446
        srtp_err_status_t res = srtp_create(video ? &session->media.video_srtp_in : &session->media.audio_srtp_in, policy);
447
        if(res != srtp_err_status_ok) {
448
                /* Something went wrong... */
449
                JANUS_LOG(LOG_ERR, "Oops, error creating inbound SRTP session: %d (%s)\n", res, janus_srtp_error_str(res));
450
                g_free(decoded);
451
                policy->key = NULL;
452
                return -2;
453
        }
454
        if((video && session->media.video_srtp_in) || (!video && session->media.audio_srtp_in)) {
455
                JANUS_LOG(LOG_VERB, "%s inbound SRTP session created\n", video ? "Video" : "Audio");
456
        }
457
        return 0;
458
}
459
static void janus_sip_srtp_cleanup(janus_sip_session *session) {
460
        if(session == NULL)
461
                return;
462
        session->media.autoack = TRUE;
463
        session->media.require_srtp = FALSE;
464
        session->media.has_srtp_local = FALSE;
465
        session->media.has_srtp_remote = FALSE;
466
        /* Audio */
467
        if(session->media.audio_srtp_out)
468
                srtp_dealloc(session->media.audio_srtp_out);
469
        session->media.audio_srtp_out = NULL;
470
        g_free(session->media.audio_local_policy.key);
471
        session->media.audio_local_policy.key = NULL;
472
        session->media.audio_srtp_suite_out = 0;
473
        if(session->media.audio_srtp_in)
474
                srtp_dealloc(session->media.audio_srtp_in);
475
        session->media.audio_srtp_in = NULL;
476
        g_free(session->media.audio_remote_policy.key);
477
        session->media.audio_remote_policy.key = NULL;
478
        session->media.audio_srtp_suite_in = 0;
479
        /* Video */
480
        if(session->media.video_srtp_out)
481
                srtp_dealloc(session->media.video_srtp_out);
482
        session->media.video_srtp_out = NULL;
483
        g_free(session->media.video_local_policy.key);
484
        session->media.video_local_policy.key = NULL;
485
        session->media.video_srtp_suite_out = 0;
486
        if(session->media.video_srtp_in)
487
                srtp_dealloc(session->media.video_srtp_in);
488
        session->media.video_srtp_in = NULL;
489
        g_free(session->media.video_remote_policy.key);
490
        session->media.video_remote_policy.key = NULL;
491
        session->media.video_srtp_suite_in = 0;
492
}
493

    
494

    
495
/* Sofia Event thread */
496
gpointer janus_sip_sofia_thread(gpointer user_data);
497
/* Sofia callbacks */
498
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[]);
499
/* SDP parsing and manipulation */
500
void janus_sip_sdp_process(janus_sip_session *session, janus_sdp *sdp, gboolean answer, gboolean update, gboolean *changed);
501
char *janus_sip_sdp_manipulate(janus_sip_session *session, janus_sdp *sdp, gboolean answer);
502
/* Media */
503
static int janus_sip_allocate_local_ports(janus_sip_session *session);
504
static void *janus_sip_relay_thread(void *data);
505

    
506

    
507
/* URI parsing utilies */
508

    
509
#define JANUS_SIP_URI_MAXLEN        1024
510
typedef struct {
511
        char data[JANUS_SIP_URI_MAXLEN];
512
        url_t url[1];
513
} janus_sip_uri_t;
514

    
515
/* Parses a SIP URI (SIPS is not supported), returns 0 on success, -1 otherwise */
516
static int janus_sip_parse_uri(janus_sip_uri_t *sip_uri, const char *data) {
517
        g_strlcpy(sip_uri->data, data, JANUS_SIP_URI_MAXLEN);
518
        if (url_d(sip_uri->url, sip_uri->data) < 0 || sip_uri->url->url_type != url_sip)
519
                return -1;
520
        return 0;
521
}
522

    
523
/* Similar to the above function, but it also accepts SIPS URIs */
524
static int janus_sip_parse_proxy_uri(janus_sip_uri_t *sip_uri, const char *data) {
525
        g_strlcpy(sip_uri->data, data, JANUS_SIP_URI_MAXLEN);
526
        if (url_d(sip_uri->url, sip_uri->data) < 0 || (sip_uri->url->url_type != url_sip && sip_uri->url->url_type != url_sips))
527
                return -1;
528
        return 0;
529
}
530

    
531
/* Error codes */
532
#define JANUS_SIP_ERROR_UNKNOWN_ERROR                499
533
#define JANUS_SIP_ERROR_NO_MESSAGE                        440
534
#define JANUS_SIP_ERROR_INVALID_JSON                441
535
#define JANUS_SIP_ERROR_INVALID_REQUEST                442
536
#define JANUS_SIP_ERROR_MISSING_ELEMENT                443
537
#define JANUS_SIP_ERROR_INVALID_ELEMENT                444
538
#define JANUS_SIP_ERROR_ALREADY_REGISTERED        445
539
#define JANUS_SIP_ERROR_INVALID_ADDRESS                446
540
#define JANUS_SIP_ERROR_WRONG_STATE                        447
541
#define JANUS_SIP_ERROR_MISSING_SDP                        448
542
#define JANUS_SIP_ERROR_LIBSOFIA_ERROR                449
543
#define JANUS_SIP_ERROR_IO_ERROR                        450
544
#define JANUS_SIP_ERROR_RECORDING_ERROR                451
545
#define JANUS_SIP_ERROR_TOO_STRICT                        452
546

    
547

    
548
/* SIP watchdog/garbage collector (sort of) */
549
static void *janus_sip_watchdog(void *data) {
550
        JANUS_LOG(LOG_INFO, "SIP watchdog started\n");
551
        gint64 now = 0;
552
        while(g_atomic_int_get(&initialized) && !g_atomic_int_get(&stopping)) {
553
                janus_mutex_lock(&sessions_mutex);
554
                /* Iterate on all the sessions */
555
                now = janus_get_monotonic_time();
556
                if(old_sessions != NULL) {
557
                        GList *sl = old_sessions;
558
                        JANUS_LOG(LOG_HUGE, "Checking %d old SIP sessions...\n", g_list_length(old_sessions));
559
                        while(sl) {
560
                                janus_sip_session *session = (janus_sip_session *)sl->data;
561
                                if(!session) {
562
                                        sl = sl->next;
563
                                        continue;
564
                                }
565
                                if (now-session->destroyed >= 5*G_USEC_PER_SEC) {
566
                                        /* We're lazy and actually get rid of the stuff only after a few seconds */
567
                                        JANUS_LOG(LOG_VERB, "Freeing old SIP session\n");
568
                                        GList *rm = sl->next;
569
                                        old_sessions = g_list_delete_link(old_sessions, sl);
570
                                        sl = rm;
571
                                        if (session->account.identity) {
572
                                            g_hash_table_remove(identities, session->account.identity);
573
                                            g_free(session->account.identity);
574
                                            session->account.identity = NULL;
575
                                        }
576
                                        session->account.sips = TRUE;
577
                                        if (session->account.proxy) {
578
                                            g_free(session->account.proxy);
579
                                            session->account.proxy = NULL;
580
                                        }
581
                                        if (session->account.outbound_proxy) {
582
                                            g_free(session->account.outbound_proxy);
583
                                            session->account.outbound_proxy = NULL;
584
                                        }
585
                                        if (session->account.secret) {
586
                                            g_free(session->account.secret);
587
                                            session->account.secret = NULL;
588
                                        }
589
                                        if (session->account.username) {
590
                                            g_free(session->account.username);
591
                                            session->account.username = NULL;
592
                                        }
593
                                        if (session->account.display_name) {
594
                                            g_free(session->account.display_name);
595
                                            session->account.display_name = NULL;
596
                                        }
597
                                        if (session->account.user_agent) {
598
                                            g_free(session->account.user_agent);
599
                                            session->account.user_agent = NULL;
600
                                        }
601
                                        if (session->account.authuser) {
602
                                            g_free(session->account.authuser);
603
                                            session->account.authuser = NULL;
604
                                        }
605
                                        if (session->callee) {
606
                                            g_free(session->callee);
607
                                            session->callee = NULL;
608
                                        }
609
                                        if (session->callid) {
610
                                            g_hash_table_remove(callids, session->callid);
611
                                            g_free(session->callid);
612
                                            session->callid = NULL;
613
                                        }
614
                                        if (session->sdp) {
615
                                            janus_sdp_free(session->sdp);
616
                                            session->sdp = NULL;
617
                                        }
618
                                        if (session->transaction) {
619
                                            g_free(session->transaction);
620
                                            session->transaction = NULL;
621
                                        }
622
                                        if (session->media.remote_ip) {
623
                                            g_free(session->media.remote_ip);
624
                                            session->media.remote_ip = NULL;
625
                                        }
626
                                        janus_sip_srtp_cleanup(session);
627
                                        session->handle = NULL;
628
                                        g_free(session);
629
                                        session = NULL;
630
                                        continue;
631
                                }
632
                                sl = sl->next;
633
                        }
634
                }
635
                janus_mutex_unlock(&sessions_mutex);
636
                g_usleep(500000);
637
        }
638
        JANUS_LOG(LOG_INFO, "SIP watchdog stopped\n");
639
        return NULL;
640
}
641

    
642

    
643
/* Random string helper (for call-ids) */
644
static char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
645
static void janus_sip_random_string(int length, char *buffer) {
646
        if(length > 0 && buffer) {
647
                int l = (int)(sizeof(charset)-1);
648
                int i=0;
649
                for(i=0; i<length; i++) {
650
                        int key = rand() % l;
651
                        buffer[i] = charset[key];
652
                }
653
                buffer[length-1] = '\0';
654
        }
655
}
656

    
657

    
658
/* Sofia SIP logger function: when the Event Handlers mechanism is enabled,
659
 * we use this to intercept SIP messages sent by the stack (received
660
 * messages are more easily recoverable in janus_sip_sofia_callback) */
661
char sofia_log[2048];
662
char call_id[255];
663
gboolean skip = FALSE, started = FALSE, append = FALSE;
664
static void janus_sip_sofia_logger(void *stream, char const *fmt, va_list ap) {
665
        if(!fmt)
666
                return;
667
        char line[255];
668
        g_vsnprintf(line, sizeof(line), fmt, ap);
669
        if(skip) {
670
                /* This is a message we're not interested in: just check when it ends */
671
                if(line[3] == '-') {
672
                        skip = FALSE;
673
                        append = FALSE;
674
                }
675
                return;
676
        }
677
        if(append) {
678
                /* We're copying a message in our buffer: check if this is the end */
679
                if(line[3] == '-') {
680
                        if(!started) {
681
                                /* Ok, start appending from now on */
682
                                started = TRUE;
683
                                sofia_log[0] = '\0';
684
                                call_id[0] = '\0';
685
                        } else {
686
                                /* Message ended, handle it */
687
                                skip = FALSE;
688
                                append = FALSE;
689
                                /* Look for the session this message belongs to */
690
                                janus_sip_session *session = NULL;
691
                                if(strlen(call_id))
692
                                        session = g_hash_table_lookup(callids, call_id);
693
                                if(!session) {
694
                                        /* Couldn't find any SIP session with that Call-ID, check the request */
695
                                        if(strstr(sofia_log, "REGISTER") == sofia_log || strstr(sofia_log, "SIP/2.0 ") == sofia_log) {
696
                                                /* FIXME This is a REGISTER or a response code:
697
                                                 * check the To header and get the identity from there */
698
                                                char *from = strstr(sofia_log, "To: ");
699
                                                if(from) {
700
                                                        from = from+4;
701
                                                        char *start = strstr(from, "<");
702
                                                        if(start) {
703
                                                                start++;
704
                                                                char *end = strstr(from, ">");
705
                                                                if(end) {
706
                                                                        *end = '\0';
707
                                                                        g_snprintf(call_id, sizeof(call_id), "%s", start);
708
                                                                        *end = '>';
709
                                                                        session = g_hash_table_lookup(identities, call_id);
710
                                                                }
711
                                                        }
712
                                                }
713
                                        }
714
                                }
715
                                if(session) {
716
                                        /* Notify event handlers about the content of the whole outgoing SIP message */
717
                                        json_t *info = json_object();
718
                                        json_object_set_new(info, "event", json_string("sip-out"));
719
                                        json_object_set_new(info, "sip", json_string(sofia_log));
720
                                        gateway->notify_event(&janus_sip_plugin, session->handle, info);
721
                                } else {
722
                                        JANUS_LOG(LOG_WARN, "Couldn't find a session associated to this message, dropping it...\n%s", sofia_log);
723
                                }
724
                                /* Done, reset the buffers */
725
                                sofia_log[0] = '\0';
726
                                call_id[0] = '\0';
727
                        }
728
                        return;
729
                }
730
                if(strlen(line) == 1) {
731
                        /* Append a carriage and return */
732
                        g_strlcat(sofia_log, "\r\n", sizeof(sofia_log));
733
                } else {
734
                        /* If this is an OPTIONS, we don't care: drop it */
735
                        char *header = &line[3];
736
                        if(strstr(header, "OPTIONS") == header) {
737
                                skip = TRUE;
738
                                return;
739
                        }
740
                        /* Is this a Call-ID header? Keep note of it */
741
                        if(strstr(header, "Call-ID") == header) {
742
                                g_snprintf(call_id, sizeof(call_id), "%s", header+9);
743
                        }
744
                        /* Append the line to our buffer, skipping the indent */
745
                        g_strlcat(sofia_log, &line[3], sizeof(sofia_log));
746
                }
747
                return;
748
        }
749
        /* Still waiting to decide if this is a message we need */
750
        if(line[0] == 's' && line[1] == 'e' && line[2] == 'n' && line[3] == 'd' && line[4] == ' ') {
751
                /* An outgoing message is going to be logged, prepare for that */
752
                skip = FALSE;
753
                started = FALSE;
754
                append = TRUE;
755
                int length = atoi(&line[5]);
756
                JANUS_LOG(LOG_HUGE, "Intercepting message (%d bytes)\n", length);
757
                if(strstr(line, "-----"))
758
                        started = TRUE;
759
        }
760
}
761

    
762

    
763
/* Plugin implementation */
764
int janus_sip_init(janus_callbacks *callback, const char *config_path) {
765
        if(g_atomic_int_get(&stopping)) {
766
                /* Still stopping from before */
767
                return -1;
768
        }
769
        if(callback == NULL || config_path == NULL) {
770
                /* Invalid arguments */
771
                return -1;
772
        }
773

    
774
        /* Read configuration */
775
        char filename[255];
776
        g_snprintf(filename, 255, "%s/%s.cfg", config_path, JANUS_SIP_PACKAGE);
777
        JANUS_LOG(LOG_VERB, "Configuration file: %s\n", filename);
778
        janus_config *config = janus_config_parse(filename);
779
        if(config != NULL) {
780
                janus_config_print(config);
781

    
782
                janus_config_item *item = janus_config_get_item_drilldown(config, "general", "local_ip");
783
                if(item && item->value) {
784
                        /* Verify that the address is valid */
785
                        struct ifaddrs *ifas = NULL;
786
                        janus_network_address iface;
787
                        janus_network_address_string_buffer ibuf;
788
                        if(getifaddrs(&ifas) || ifas == NULL) {
789
                                JANUS_LOG(LOG_ERR, "Unable to acquire list of network devices/interfaces; some configurations may not work as expected...\n");
790
                        } else {
791
                                if(janus_network_lookup_interface(ifas, item->value, &iface) != 0) {
792
                                        JANUS_LOG(LOG_WARN, "Error setting local IP address to %s, falling back to detecting IP address...\n", item->value);
793
                                } else {
794
                                        if(janus_network_address_to_string_buffer(&iface, &ibuf) != 0 || janus_network_address_string_buffer_is_null(&ibuf)) {
795
                                                JANUS_LOG(LOG_WARN, "Error getting local IP address from %s, falling back to detecting IP address...\n", item->value);
796
                                        } else {
797
                                                local_ip = g_strdup(janus_network_address_string_from_buffer(&ibuf));
798
                                        }
799
                                }
800
                        }
801
                }
802

    
803
                item = janus_config_get_item_drilldown(config, "general", "keepalive_interval");
804
                if(item && item->value)
805
                        keepalive_interval = atoi(item->value);
806
                JANUS_LOG(LOG_VERB, "SIP keep-alive interval set to %d seconds\n", keepalive_interval);
807

    
808
                item = janus_config_get_item_drilldown(config, "general", "register_ttl");
809
                if(item && item->value)
810
                        register_ttl = atoi(item->value);
811
                JANUS_LOG(LOG_VERB, "SIP registration TTL set to %d seconds\n", register_ttl);
812

    
813
                item = janus_config_get_item_drilldown(config, "general", "behind_nat");
814
                if(item && item->value)
815
                        behind_nat = janus_is_true(item->value);
816

    
817
                item = janus_config_get_item_drilldown(config, "general", "user_agent");
818
                if(item && item->value)
819
                        user_agent = g_strdup(item->value);
820
                else
821
                        user_agent = g_strdup("Janus WebRTC Gateway SIP Plugin "JANUS_SIP_VERSION_STRING);
822
                JANUS_LOG(LOG_VERB, "SIP User-Agent set to %s\n", user_agent);
823

    
824
                item = janus_config_get_item_drilldown(config, "general", "events");
825
                if(item != NULL && item->value != NULL)
826
                        notify_events = janus_is_true(item->value);
827
                if(!notify_events && callback->events_is_enabled()) {
828
                        JANUS_LOG(LOG_WARN, "Notification of events to handlers disabled for %s\n", JANUS_SIP_NAME);
829
                }
830

    
831
                janus_config_destroy(config);
832
        }
833
        config = NULL;
834

    
835
        if(local_ip == NULL) {
836
                local_ip = janus_network_detect_local_ip_as_string(janus_network_query_options_any_ip);
837
                if(local_ip == NULL) {
838
                        JANUS_LOG(LOG_WARN, "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");
839
                        local_ip = g_strdup("127.0.0.1");
840
                }
841
        }
842
        JANUS_LOG(LOG_VERB, "Local IP set to %s\n", local_ip);
843

    
844
#ifdef HAVE_SRTP_2
845
        /* Init randomizer (for randum numbers in SRTP) */
846
        RAND_poll();
847
#endif
848

    
849
        /* Setup sofia */
850
        su_init();
851
        if(callback->events_is_enabled()) {
852
                /* Enable the transport logging, as we want to have access to the SIP messages */
853
                setenv("TPORT_LOG", "1", 1);
854
                su_log_redirect(NULL, janus_sip_sofia_logger, NULL);
855
        }
856

    
857
        sessions = g_hash_table_new(NULL, NULL);
858
        callids = g_hash_table_new(g_str_hash, g_str_equal);
859
        identities = g_hash_table_new(g_str_hash, g_str_equal);
860
        janus_mutex_init(&sessions_mutex);
861
        messages = g_async_queue_new_full((GDestroyNotify) janus_sip_message_free);
862
        /* This is the callback we'll need to invoke to contact the gateway */
863
        gateway = callback;
864

    
865
        g_atomic_int_set(&initialized, 1);
866

    
867
        GError *error = NULL;
868
        /* Start the sessions watchdog */
869
        watchdog = g_thread_try_new("sip watchdog", &janus_sip_watchdog, NULL, &error);
870
        if(error != NULL) {
871
                g_atomic_int_set(&initialized, 0);
872
                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the SIP watchdog thread...\n", error->code, error->message ? error->message : "??");
873
                return -1;
874
        }
875
        /* Launch the thread that will handle incoming messages */
876
        handler_thread = g_thread_try_new("sip handler", janus_sip_handler, NULL, &error);
877
        if(error != NULL) {
878
                g_atomic_int_set(&initialized, 0);
879
                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the SIP handler thread...\n", error->code, error->message ? error->message : "??");
880
                return -1;
881
        }
882
        JANUS_LOG(LOG_INFO, "%s initialized!\n", JANUS_SIP_NAME);
883
        return 0;
884
}
885

    
886
void janus_sip_destroy(void) {
887
        if(!g_atomic_int_get(&initialized))
888
                return;
889
        g_atomic_int_set(&stopping, 1);
890

    
891
        g_async_queue_push(messages, &exit_message);
892
        if(handler_thread != NULL) {
893
                g_thread_join(handler_thread);
894
                handler_thread = NULL;
895
        }
896
        if(watchdog != NULL) {
897
                g_thread_join(watchdog);
898
                watchdog = NULL;
899
        }
900
        /* FIXME We should destroy the sessions cleanly */
901
        janus_mutex_lock(&sessions_mutex);
902
        g_hash_table_destroy(sessions);
903
        g_hash_table_destroy(callids);
904
        g_hash_table_destroy(identities);
905
        sessions = NULL;
906
        callids = NULL;
907
        identities = NULL;
908
        janus_mutex_unlock(&sessions_mutex);
909
        g_async_queue_unref(messages);
910
        messages = NULL;
911
        g_atomic_int_set(&initialized, 0);
912
        g_atomic_int_set(&stopping, 0);
913

    
914
        /* Deinitialize sofia */
915
        su_deinit();
916

    
917
        g_free(local_ip);
918

    
919
        JANUS_LOG(LOG_INFO, "%s destroyed!\n", JANUS_SIP_NAME);
920
}
921

    
922
int janus_sip_get_api_compatibility(void) {
923
        /* Important! This is what your plugin MUST always return: don't lie here or bad things will happen */
924
        return JANUS_PLUGIN_API_VERSION;
925
}
926

    
927
int janus_sip_get_version(void) {
928
        return JANUS_SIP_VERSION;
929
}
930

    
931
const char *janus_sip_get_version_string(void) {
932
        return JANUS_SIP_VERSION_STRING;
933
}
934

    
935
const char *janus_sip_get_description(void) {
936
        return JANUS_SIP_DESCRIPTION;
937
}
938

    
939
const char *janus_sip_get_name(void) {
940
        return JANUS_SIP_NAME;
941
}
942

    
943
const char *janus_sip_get_author(void) {
944
        return JANUS_SIP_AUTHOR;
945
}
946

    
947
const char *janus_sip_get_package(void) {
948
        return JANUS_SIP_PACKAGE;
949
}
950

    
951
void janus_sip_create_session(janus_plugin_session *handle, int *error) {
952
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
953
                *error = -1;
954
                return;
955
        }
956
        janus_sip_session *session = g_malloc0(sizeof(janus_sip_session));
957
        session->handle = handle;
958
        session->account.identity = NULL;
959
        session->account.sips = TRUE;
960
        session->account.username = NULL;
961
        session->account.display_name = NULL;
962
        session->account.user_agent = NULL;
963
        session->account.authuser = NULL;
964
        session->account.secret = NULL;
965
        session->account.secret_type = janus_sip_secret_type_unknown;
966
        session->account.sip_port = 0;
967
        session->account.proxy = NULL;
968
        session->account.outbound_proxy = NULL;
969
        session->account.registration_status = janus_sip_registration_status_unregistered;
970
        session->status = janus_sip_call_status_idle;
971
        session->stack = NULL;
972
        session->transaction = NULL;
973
        session->callee = NULL;
974
        session->callid = NULL;
975
        session->sdp = NULL;
976
        session->media.remote_ip = NULL;
977
        session->media.earlymedia = FALSE;
978
        session->media.ready = FALSE;
979
        session->media.autoack = TRUE;
980
        session->media.require_srtp = FALSE;
981
        session->media.has_srtp_local = FALSE;
982
        session->media.has_srtp_remote = FALSE;
983
        session->media.on_hold = FALSE;
984
        session->media.has_audio = FALSE;
985
        session->media.audio_rtp_fd = -1;
986
        session->media.audio_rtcp_fd= -1;
987
        session->media.local_audio_rtp_port = 0;
988
        session->media.remote_audio_rtp_port = 0;
989
        session->media.local_audio_rtcp_port = 0;
990
        session->media.remote_audio_rtcp_port = 0;
991
        session->media.audio_ssrc = 0;
992
        session->media.audio_ssrc_peer = 0;
993
        session->media.audio_pt = -1;
994
        session->media.audio_pt_name = NULL;
995
        session->media.audio_srtp_suite_in = 0;
996
        session->media.audio_srtp_suite_out = 0;
997
        session->media.audio_send = TRUE;
998
        session->media.pre_hold_audio_dir = JANUS_SDP_DEFAULT;
999
        session->media.has_video = FALSE;
1000
        session->media.video_rtp_fd = -1;
1001
        session->media.video_rtcp_fd= -1;
1002
        session->media.local_video_rtp_port = 0;
1003
        session->media.remote_video_rtp_port = 0;
1004
        session->media.local_video_rtcp_port = 0;
1005
        session->media.remote_video_rtcp_port = 0;
1006
        session->media.video_ssrc = 0;
1007
        session->media.video_ssrc_peer = 0;
1008
        session->media.video_pt = -1;
1009
        session->media.video_pt_name = NULL;
1010
        session->media.video_srtp_suite_in = 0;
1011
        session->media.video_srtp_suite_out = 0;
1012
        session->media.video_send = TRUE;
1013
        session->media.pre_hold_video_dir = JANUS_SDP_DEFAULT;
1014
        /* Initialize the RTP context */
1015
        janus_rtp_switching_context_reset(&session->media.context);
1016
        session->media.pipefd[0] = -1;
1017
        session->media.pipefd[1] = -1;
1018
        session->media.updated = FALSE;
1019
        janus_mutex_init(&session->rec_mutex);
1020
        session->destroyed = 0;
1021
        g_atomic_int_set(&session->hangingup, 0);
1022
        janus_mutex_init(&session->mutex);
1023
        handle->plugin_handle = session;
1024

    
1025
        janus_mutex_lock(&sessions_mutex);
1026
        g_hash_table_insert(sessions, handle, session);
1027
        janus_mutex_unlock(&sessions_mutex);
1028

    
1029
        return;
1030
}
1031

    
1032
void janus_sip_destroy_session(janus_plugin_session *handle, int *error) {
1033
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
1034
                *error = -1;
1035
                return;
1036
        }
1037
        janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;
1038
        if(!session) {
1039
                JANUS_LOG(LOG_ERR, "No SIP session associated with this handle...\n");
1040
                *error = -2;
1041
                return;
1042
        }
1043
        janus_mutex_lock(&sessions_mutex);
1044
        if(!session->destroyed) {
1045
                g_hash_table_remove(sessions, handle);
1046
                janus_sip_hangup_media(handle);
1047
                session->destroyed = janus_get_monotonic_time();
1048
                JANUS_LOG(LOG_VERB, "Destroying SIP session (%s)...\n", session->account.username ? session->account.username : "unregistered user");
1049
                if(session->stack != NULL) {
1050
                        /* Shutdown the NUA: this will remove the session later on */
1051
                        nua_shutdown(session->stack->s_nua);
1052
                } else {
1053
                        /* No stack, maybe never registered: cleaning up and removing the session is done in a lazy way */
1054
                        old_sessions = g_list_append(old_sessions, session);
1055
                }
1056
        }
1057
        janus_mutex_unlock(&sessions_mutex);
1058
        return;
1059
}
1060

    
1061
json_t *janus_sip_query_session(janus_plugin_session *handle) {
1062
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
1063
                return NULL;
1064
        }
1065
        janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;
1066
        if(!session) {
1067
                JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1068
                return NULL;
1069
        }
1070
        /* Provide some generic info, e.g., if we're in a call and with whom */
1071
        json_t *info = json_object();
1072
        json_object_set_new(info, "username", session->account.username ? json_string(session->account.username) : NULL);
1073
        json_object_set_new(info, "display_name", session->account.display_name ? json_string(session->account.display_name) : NULL);
1074
        json_object_set_new(info, "user_agent", session->account.user_agent ? json_string(session->account.user_agent) : NULL);
1075
        json_object_set_new(info, "identity", session->account.identity ? json_string(session->account.identity) : NULL);
1076
        json_object_set_new(info, "registration_status", json_string(janus_sip_registration_status_string(session->account.registration_status)));
1077
        json_object_set_new(info, "call_status", json_string(janus_sip_call_status_string(session->status)));
1078
        if(session->callee) {
1079
                json_object_set_new(info, "callee", json_string(session->callee ? session->callee : "??"));
1080
                json_object_set_new(info, "auto-ack", json_string(session->media.autoack ? "yes" : "no"));
1081
                json_object_set_new(info, "srtp-required", json_string(session->media.require_srtp ? "yes" : "no"));
1082
                json_object_set_new(info, "sdes-local", json_string(session->media.has_srtp_local ? "yes" : "no"));
1083
                json_object_set_new(info, "sdes-remote", json_string(session->media.has_srtp_remote ? "yes" : "no"));
1084
        }
1085
        if(session->arc || session->vrc || session->arc_peer || session->vrc_peer) {
1086
                json_t *recording = json_object();
1087
                if(session->arc && session->arc->filename)
1088
                        json_object_set_new(recording, "audio", json_string(session->arc->filename));
1089
                if(session->vrc && session->vrc->filename)
1090
                        json_object_set_new(recording, "video", json_string(session->vrc->filename));
1091
                if(session->arc_peer && session->arc_peer->filename)
1092
                        json_object_set_new(recording, "audio-peer", json_string(session->arc_peer->filename));
1093
                if(session->vrc_peer && session->vrc_peer->filename)
1094
                        json_object_set_new(recording, "video-peer", json_string(session->vrc_peer->filename));
1095
                json_object_set_new(info, "recording", recording);
1096
        }
1097
        json_object_set_new(info, "destroyed", json_integer(session->destroyed));
1098
        return info;
1099
}
1100

    
1101
struct janus_plugin_result *janus_sip_handle_message(janus_plugin_session *handle, char *transaction, json_t *message, json_t *jsep) {
1102
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
1103
                return janus_plugin_result_new(JANUS_PLUGIN_ERROR, g_atomic_int_get(&stopping) ? "Shutting down" : "Plugin not initialized", NULL);
1104
        janus_sip_message *msg = g_malloc0(sizeof(janus_sip_message));
1105
        msg->handle = handle;
1106
        msg->transaction = transaction;
1107
        msg->message = message;
1108
        msg->jsep = jsep;
1109
        g_async_queue_push(messages, msg);
1110

    
1111
        /* All the requests to this plugin are handled asynchronously */
1112
        return janus_plugin_result_new(JANUS_PLUGIN_OK_WAIT, NULL, NULL);
1113
}
1114

    
1115
void janus_sip_setup_media(janus_plugin_session *handle) {
1116
        JANUS_LOG(LOG_INFO, "WebRTC media is now available\n");
1117
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
1118
                return;
1119
        janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;
1120
        if(!session) {
1121
                JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1122
                return;
1123
        }
1124
        if(session->destroyed)
1125
                return;
1126
        g_atomic_int_set(&session->hangingup, 0);
1127
        /* TODO Only relay RTP/RTCP when we get this event */
1128
}
1129

    
1130
void janus_sip_incoming_rtp(janus_plugin_session *handle, int video, char *buf, int len) {
1131
        if(handle == NULL || handle->stopped || g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
1132
                return;
1133
        if(gateway) {
1134
                /* Honour the audio/video active flags */
1135
                janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;
1136
                if(!session || session->destroyed) {
1137
                        JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1138
                        return;
1139
                }
1140
                if(session->status != janus_sip_call_status_incall)
1141
                        return;
1142
                /* Forward to our SIP peer */
1143
                if(video) {
1144
                        if(!session->media.video_send) {
1145
                                /* Dropping video packet, peer doesn't want to receive it */
1146
                                return;
1147
                        }
1148
                        if(session->media.video_ssrc == 0) {
1149
                                rtp_header *header = (rtp_header *)buf;
1150
                                session->media.video_ssrc = ntohl(header->ssrc);
1151
                                JANUS_LOG(LOG_VERB, "Got SIP video SSRC: %"SCNu32"\n", session->media.video_ssrc);
1152
                        }
1153
                        if(session->media.has_video && session->media.video_rtp_fd != -1) {
1154
                                /* Save the frame if we're recording */
1155
                                janus_recorder_save_frame(session->vrc, buf, len);
1156
                                /* Is SRTP involved? */
1157
                                if(session->media.has_srtp_local) {
1158
                                        char sbuf[2048];
1159
                                        memcpy(&sbuf, buf, len);
1160
                                        int protected = len;
1161
                                        int res = srtp_protect(session->media.video_srtp_out, &sbuf, &protected);
1162
                                        if(res != srtp_err_status_ok) {
1163
                                                rtp_header *header = (rtp_header *)&sbuf;
1164
                                                guint32 timestamp = ntohl(header->timestamp);
1165
                                                guint16 seq = ntohs(header->seq_number);
1166
                                                JANUS_LOG(LOG_ERR, "[SIP-%s] Video SRTP protect error... %s (len=%d-->%d, ts=%"SCNu32", seq=%"SCNu16")...\n",
1167
                                                        session->account.username, janus_srtp_error_str(res), len, protected, timestamp, seq);
1168
                                        } else {
1169
                                                /* Forward the frame to the peer */
1170
                                                send(session->media.video_rtp_fd, sbuf, protected, 0);
1171
                                        }
1172
                                } else {
1173
                                        /* Forward the frame to the peer */
1174
                                        send(session->media.video_rtp_fd, buf, len, 0);
1175
                                }
1176
                        }
1177
                } else {
1178
                        if(!session->media.audio_send) {
1179
                                /* Dropping audio packet, peer doesn't want to receive it */
1180
                                return;
1181
                        }
1182
                        if(session->media.audio_ssrc == 0) {
1183
                                rtp_header *header = (rtp_header *)buf;
1184
                                session->media.audio_ssrc = ntohl(header->ssrc);
1185
                                JANUS_LOG(LOG_VERB, "Got SIP audio SSRC: %"SCNu32"\n", session->media.audio_ssrc);
1186
                        }
1187
                        if(session->media.has_audio && session->media.audio_rtp_fd != -1) {
1188
                                /* Save the frame if we're recording */
1189
                                janus_recorder_save_frame(session->arc, buf, len);
1190
                                /* Is SRTP involved? */
1191
                                if(session->media.has_srtp_local) {
1192
                                        char sbuf[2048];
1193
                                        memcpy(&sbuf, buf, len);
1194
                                        int protected = len;
1195
                                        int res = srtp_protect(session->media.audio_srtp_out, &sbuf, &protected);
1196
                                        if(res != srtp_err_status_ok) {
1197
                                                rtp_header *header = (rtp_header *)&sbuf;
1198
                                                guint32 timestamp = ntohl(header->timestamp);
1199
                                                guint16 seq = ntohs(header->seq_number);
1200
                                                JANUS_LOG(LOG_ERR, "[SIP-%s] Audio SRTP protect error... %s (len=%d-->%d, ts=%"SCNu32", seq=%"SCNu16")...\n",
1201
                                                        session->account.username, janus_srtp_error_str(res), len, protected, timestamp, seq);
1202
                                        } else {
1203
                                                /* Forward the frame to the peer */
1204
                                                send(session->media.audio_rtp_fd, sbuf, protected, 0);
1205
                                        }
1206
                                } else {
1207
                                        /* Forward the frame to the peer */
1208
                                        send(session->media.audio_rtp_fd, buf, len, 0);
1209
                                }
1210
                        }
1211
                }
1212
        }
1213
}
1214

    
1215
void janus_sip_incoming_rtcp(janus_plugin_session *handle, int video, char *buf, int len) {
1216
        if(handle == NULL || handle->stopped || g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
1217
                return;
1218
        if(gateway) {
1219
                janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;
1220
                if(!session || session->destroyed) {
1221
                        JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1222
                        return;
1223
                }
1224
                if(session->status != janus_sip_call_status_incall)
1225
                        return;
1226
                /* Forward to our SIP peer */
1227
                if(video) {
1228
                        if(session->media.has_video && session->media.video_rtcp_fd != -1) {
1229
                                /* Fix SSRCs as the gateway does */
1230
                                JANUS_LOG(LOG_HUGE, "[SIP] Fixing SSRCs (local %u, peer %u)\n",
1231
                                        session->media.video_ssrc, session->media.video_ssrc_peer);
1232
                                janus_rtcp_fix_ssrc(NULL, (char *)buf, len, 1, session->media.video_ssrc, session->media.video_ssrc_peer);
1233
                                /* Is SRTP involved? */
1234
                                if(session->media.has_srtp_local) {
1235
                                        char sbuf[2048];
1236
                                        memcpy(&sbuf, buf, len);
1237
                                        int protected = len;
1238
                                        int res = srtp_protect_rtcp(session->media.video_srtp_out, &sbuf, &protected);
1239
                                        if(res != srtp_err_status_ok) {
1240
                                                JANUS_LOG(LOG_ERR, "[SIP-%s] Video SRTCP protect error... %s (len=%d-->%d)...\n",
1241
                                                        session->account.username, janus_srtp_error_str(res), len, protected);
1242
                                        } else {
1243
                                                /* Forward the message to the peer */
1244
                                                send(session->media.video_rtcp_fd, sbuf, protected, 0);
1245
                                        }
1246
                                } else {
1247
                                        /* Forward the message to the peer */
1248
                                        send(session->media.video_rtcp_fd, buf, len, 0);
1249
                                }
1250
                        }
1251
                } else {
1252
                        if(session->media.has_audio && session->media.audio_rtcp_fd != -1) {
1253
                                /* Fix SSRCs as the gateway does */
1254
                                JANUS_LOG(LOG_HUGE, "[SIP] Fixing SSRCs (local %u, peer %u)\n",
1255
                                        session->media.audio_ssrc, session->media.audio_ssrc_peer);
1256
                                janus_rtcp_fix_ssrc(NULL, (char *)buf, len, 1, session->media.audio_ssrc, session->media.audio_ssrc_peer);
1257
                                /* Is SRTP involved? */
1258
                                if(session->media.has_srtp_local) {
1259
                                        char sbuf[2048];
1260
                                        memcpy(&sbuf, buf, len);
1261
                                        int protected = len;
1262
                                        int res = srtp_protect_rtcp(session->media.audio_srtp_out, &sbuf, &protected);
1263
                                        if(res != srtp_err_status_ok) {
1264
                                                JANUS_LOG(LOG_ERR, "[SIP-%s] Audio SRTCP protect error... %s (len=%d-->%d)...\n",
1265
                                                        session->account.username, janus_srtp_error_str(res), len, protected);
1266
                                        } else {
1267
                                                /* Forward the message to the peer */
1268
                                                send(session->media.audio_rtcp_fd, sbuf, protected, 0);
1269
                                        }
1270
                                } else {
1271
                                        /* Forward the message to the peer */
1272
                                        send(session->media.audio_rtcp_fd, buf, len, 0);
1273
                                }
1274
                        }
1275
                }
1276
        }
1277
}
1278

    
1279
void janus_sip_hangup_media(janus_plugin_session *handle) {
1280
        JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
1281
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
1282
                return;
1283
        janus_sip_session *session = (janus_sip_session *)handle->plugin_handle;
1284
        if(!session) {
1285
                JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1286
                return;
1287
        }
1288
        if(session->destroyed)
1289
                return;
1290
        if(g_atomic_int_add(&session->hangingup, 1))
1291
                return;
1292
        if(!(session->status == janus_sip_call_status_inviting ||
1293
                 session->status == janus_sip_call_status_invited ||
1294
                 session->status == janus_sip_call_status_incall))
1295
                return;
1296
        /* Get rid of the recorders, if available */
1297
        janus_mutex_lock(&session->rec_mutex);
1298
        if(session->arc) {
1299
                janus_recorder_close(session->arc);
1300
                JANUS_LOG(LOG_INFO, "Closed user's audio recording %s\n", session->arc->filename ? session->arc->filename : "??");
1301
                janus_recorder_free(session->arc);
1302
        }
1303
        session->arc = NULL;
1304
        if(session->arc_peer) {
1305
                janus_recorder_close(session->arc_peer);
1306
                JANUS_LOG(LOG_INFO, "Closed peer's audio recording %s\n", session->arc_peer->filename ? session->arc_peer->filename : "??");
1307
                janus_recorder_free(session->arc_peer);
1308
        }
1309
        session->arc_peer = NULL;
1310
        if(session->vrc) {
1311
                janus_recorder_close(session->vrc);
1312
                JANUS_LOG(LOG_INFO, "Closed user's video recording %s\n", session->vrc->filename ? session->vrc->filename : "??");
1313
                janus_recorder_free(session->vrc);
1314
        }
1315
        session->vrc = NULL;
1316
        if(session->vrc_peer) {
1317
                janus_recorder_close(session->vrc_peer);
1318
                JANUS_LOG(LOG_INFO, "Closed peer's video recording %s\n", session->vrc_peer->filename ? session->vrc_peer->filename : "??");
1319
                janus_recorder_free(session->vrc_peer);
1320
        }
1321
        session->vrc_peer = NULL;
1322
        janus_mutex_unlock(&session->rec_mutex);
1323
        /* FIXME Simulate a "hangup" coming from the browser */
1324
        janus_sip_message *msg = g_malloc0(sizeof(janus_sip_message));
1325
        msg->handle = handle;
1326
        msg->message = json_pack("{ss}", "request", "hangup");
1327
        msg->transaction = NULL;
1328
        msg->jsep = NULL;
1329
        g_async_queue_push(messages, msg);
1330
}
1331

    
1332
/* Thread to handle incoming messages */
1333
static void *janus_sip_handler(void *data) {
1334
        JANUS_LOG(LOG_VERB, "Joining SIP handler thread\n");
1335
        janus_sip_message *msg = NULL;
1336
        int error_code = 0;
1337
        char error_cause[512];
1338
        json_t *root = NULL;
1339
        while(g_atomic_int_get(&initialized) && !g_atomic_int_get(&stopping)) {
1340
                msg = g_async_queue_pop(messages);
1341
                if(msg == NULL)
1342
                        continue;
1343
                if(msg == &exit_message)
1344
                        break;
1345
                if(msg->handle == NULL) {
1346
                        janus_sip_message_free(msg);
1347
                        continue;
1348
                }
1349
                janus_sip_session *session = NULL;
1350
                janus_mutex_lock(&sessions_mutex);
1351
                if(g_hash_table_lookup(sessions, msg->handle) != NULL ) {
1352
                        session = (janus_sip_session *)msg->handle->plugin_handle;
1353
                }
1354
                janus_mutex_unlock(&sessions_mutex);
1355
                if(!session) {
1356
                        JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1357
                        janus_sip_message_free(msg);
1358
                        continue;
1359
                }
1360
                if(session->destroyed) {
1361
                        janus_sip_message_free(msg);
1362
                        continue;
1363
                }
1364
                /* Handle request */
1365
                error_code = 0;
1366
                root = msg->message;
1367
                if(msg->message == NULL) {
1368
                        JANUS_LOG(LOG_ERR, "No message??\n");
1369
                        error_code = JANUS_SIP_ERROR_NO_MESSAGE;
1370
                        g_snprintf(error_cause, 512, "%s", "No message??");
1371
                        goto error;
1372
                }
1373
                if(!json_is_object(root)) {
1374
                        JANUS_LOG(LOG_ERR, "JSON error: not an object\n");
1375
                        error_code = JANUS_SIP_ERROR_INVALID_JSON;
1376
                        g_snprintf(error_cause, 512, "JSON error: not an object");
1377
                        goto error;
1378
                }
1379
                JANUS_VALIDATE_JSON_OBJECT(root, request_parameters,
1380
                        error_code, error_cause, TRUE,
1381
                        JANUS_SIP_ERROR_MISSING_ELEMENT, JANUS_SIP_ERROR_INVALID_ELEMENT);
1382
                if(error_code != 0)
1383
                        goto error;
1384
                json_t *request = json_object_get(root, "request");
1385
                const char *request_text = json_string_value(request);
1386
                json_t *result = NULL;
1387

    
1388
                if(!strcasecmp(request_text, "register")) {
1389
                        /* Send a REGISTER */
1390
                        JANUS_VALIDATE_JSON_OBJECT(root, register_parameters,
1391
                                error_code, error_cause, TRUE,
1392
                                JANUS_SIP_ERROR_MISSING_ELEMENT, JANUS_SIP_ERROR_INVALID_ELEMENT);
1393
                        if(error_code != 0)
1394
                                goto error;
1395
                        gboolean refresh = json_is_true(json_object_get(root, "refresh"));
1396
                        if(session->account.registration_status > janus_sip_registration_status_unregistered && !refresh) {
1397
                                JANUS_LOG(LOG_ERR, "Already registered (%s)\n", session->account.username);
1398
                                error_code = JANUS_SIP_ERROR_ALREADY_REGISTERED;
1399
                                g_snprintf(error_cause, 512, "Already registered (%s)", session->account.username);
1400
                                goto error;
1401
                        }
1402
                        /* Parse the request */
1403
                        gboolean guest = FALSE;
1404
                        json_t *type = json_object_get(root, "type");
1405
                        if(type != NULL) {
1406
                                const char *type_text = json_string_value(type);
1407
                                if(!strcmp(type_text, "guest")) {
1408
                                        JANUS_LOG(LOG_INFO, "Registering as a guest\n");
1409
                                        guest = TRUE;
1410
                                } else {
1411
                                        JANUS_LOG(LOG_WARN, "Unknown type '%s', ignoring...\n", type_text);
1412
                                }
1413
                        }
1414

    
1415
                        gboolean send_register = TRUE;
1416
                        json_t *do_register = json_object_get(root, "send_register");
1417
                        if(do_register != NULL) {
1418
                                if(guest) {
1419
                                        JANUS_LOG(LOG_ERR, "Conflicting elements: send_register cannot be true if guest is true\n");
1420
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
1421
                                        g_snprintf(error_cause, 512, "Conflicting elements: send_register cannot be true if guest is true");
1422
                                        goto error;
1423
                                }
1424
                                send_register = json_is_true(do_register);
1425
                        }
1426

    
1427
                        gboolean sips = TRUE;
1428
                        json_t *do_sips = json_object_get(root, "sips");
1429
                        if(do_sips != NULL) {
1430
                                sips = json_is_true(do_sips);
1431
                        }
1432

    
1433
                        /* Parse addresses */
1434
                        json_t *proxy = json_object_get(root, "proxy");
1435
                        const char *proxy_text = NULL;
1436
                        if (proxy && !json_is_null(proxy)) {
1437
                                /* Has to be validated separately because it could be null */
1438
                                JANUS_VALIDATE_JSON_OBJECT(root, proxy_parameters,
1439
                                        error_code, error_cause, TRUE,
1440
                                        JANUS_SIP_ERROR_MISSING_ELEMENT, JANUS_SIP_ERROR_INVALID_ELEMENT);
1441
                                if(error_code != 0)
1442
                                        goto error;
1443
                                proxy_text = json_string_value(proxy);
1444
                                janus_sip_uri_t proxy_uri;
1445
                                if (janus_sip_parse_proxy_uri(&proxy_uri, proxy_text) < 0) {
1446
                                        JANUS_LOG(LOG_ERR, "Invalid proxy address %s\n", proxy_text);
1447
                                        error_code = JANUS_SIP_ERROR_INVALID_ADDRESS;
1448
                                        g_snprintf(error_cause, 512, "Invalid proxy address %s\n", proxy_text);
1449
                                        goto error;
1450
                                }
1451
                        }
1452
                        json_t *outbound_proxy = json_object_get(root, "outbound_proxy");
1453
                        const char *obproxy_text = NULL;
1454
                        if (outbound_proxy && !json_is_null(outbound_proxy)) {
1455
                                /* Has to be validated separately because it could be null */
1456
                                JANUS_VALIDATE_JSON_OBJECT(root, proxy_parameters,
1457
                                        error_code, error_cause, TRUE,
1458
                                        JANUS_SIP_ERROR_MISSING_ELEMENT, JANUS_SIP_ERROR_INVALID_ELEMENT);
1459
                                if(error_code != 0)
1460
                                        goto error;
1461
                                obproxy_text = json_string_value(outbound_proxy);
1462
                                janus_sip_uri_t outbound_proxy_uri;
1463
                                if (janus_sip_parse_proxy_uri(&outbound_proxy_uri, obproxy_text) < 0) {
1464
                                        JANUS_LOG(LOG_ERR, "Invalid outbound_proxy address %s\n", obproxy_text);
1465
                                        error_code = JANUS_SIP_ERROR_INVALID_ADDRESS;
1466
                                        g_snprintf(error_cause, 512, "Invalid outbound_proxy address %s\n", obproxy_text);
1467
                                        goto error;
1468
                                }
1469
                        }
1470

    
1471
                        /* Parse register TTL */
1472
                        int ttl = register_ttl;
1473
                        json_t *reg_ttl = json_object_get(root, "register_ttl");
1474
                        if (reg_ttl && json_is_integer(reg_ttl))
1475
                                ttl = json_integer_value(reg_ttl);
1476
                        if (ttl <= 0)
1477
                                ttl = JANUS_DEFAULT_REGISTER_TTL;
1478

    
1479
                        /* Parse display name */
1480
                        const char* display_name_text = NULL;
1481
                        json_t *display_name = json_object_get(root, "display_name");
1482
                        if (display_name && json_is_string(display_name))
1483
                                display_name_text = json_string_value(display_name);
1484

    
1485
                        /* Parse user agent */
1486
                        const char* user_agent_text = NULL;
1487
                        json_t *user_agent = json_object_get(root, "user_agent");
1488
                        if (user_agent && json_is_string(user_agent))
1489
                                user_agent_text = json_string_value(user_agent);
1490

    
1491
                        /* Now the user part (always needed, even for the guest case) */
1492
                        json_t *username = json_object_get(root, "username");
1493
                        if(!username) {
1494
                                /* The username is mandatory even when registering as guests */
1495
                                JANUS_LOG(LOG_ERR, "Missing element (username)\n");
1496
                                error_code = JANUS_SIP_ERROR_MISSING_ELEMENT;
1497
                                g_snprintf(error_cause, 512, "Missing element (username)");
1498
                                goto error;
1499
                        }
1500
                        const char *username_text = NULL;
1501
                        const char *secret_text = NULL;
1502
                        const char *authuser_text = NULL;
1503
                        janus_sip_secret_type secret_type = janus_sip_secret_type_plaintext;
1504
                        janus_sip_uri_t username_uri;
1505
                        char user_id[256];
1506
                        /* Parse address */
1507
                        username_text = json_string_value(username);
1508
                        if(janus_sip_parse_uri(&username_uri, username_text) < 0) {
1509
                                JANUS_LOG(LOG_ERR, "Invalid user address %s\n", username_text);
1510
                                error_code = JANUS_SIP_ERROR_INVALID_ADDRESS;
1511
                                g_snprintf(error_cause, 512, "Invalid user address %s\n", username_text);
1512
                                goto error;
1513
                        }
1514
                        g_strlcpy(user_id, username_uri.url->url_user, sizeof(user_id));
1515
                        if(guest) {
1516
                                /* Not needed, we can stop here: just say we're registered */
1517
                                JANUS_LOG(LOG_INFO, "Guest will have username %s\n", user_id);
1518
                                send_register = FALSE;
1519
                        } else {
1520
                                json_t *secret = json_object_get(root, "secret");
1521
                                json_t *ha1_secret = json_object_get(root, "ha1_secret");
1522
                                json_t *authuser = json_object_get(root, "authuser");
1523
                                if(!secret && !ha1_secret) {
1524
                                        JANUS_LOG(LOG_ERR, "Missing element (secret or ha1_secret)\n");
1525
                                        error_code = JANUS_SIP_ERROR_MISSING_ELEMENT;
1526
                                        g_snprintf(error_cause, 512, "Missing element (secret or ha1_secret)");
1527
                                        goto error;
1528
                                }
1529
                                if(secret && ha1_secret) {
1530
                                        JANUS_LOG(LOG_ERR, "Conflicting elements specified (secret and ha1_secret)\n");
1531
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
1532
                                        g_snprintf(error_cause, 512, "Conflicting elements specified (secret and ha1_secret)");
1533
                                        goto error;
1534
                                }
1535
                                if(secret) {
1536
                                        secret_text = json_string_value(secret);
1537
                                        secret_type = janus_sip_secret_type_plaintext;
1538
                                } else {
1539
                                        secret_text = json_string_value(ha1_secret);
1540
                                        secret_type = janus_sip_secret_type_hashed;
1541
                                }
1542
                                if (authuser) {
1543
                                        authuser_text = json_string_value(authuser);
1544
                                }
1545
                                /* Got the values, try registering now */
1546
                                JANUS_LOG(LOG_VERB, "Registering user %s (auth=%s, secret %s) @ %s through %s (outbound proxy: %s)\n",
1547
                                        username_text, secret_text, username_uri.url->url_host,
1548
                                        authuser_text != NULL ? authuser_text : username_text,
1549
                                        proxy_text != NULL ? proxy_text : "(null)",
1550
                                        obproxy_text != NULL ? obproxy_text : "none");
1551
                        }
1552
                        /* If this is a refresh, get rid of the old values */
1553
                        if(refresh) {
1554
                                /* Cleanup old values */
1555
                                if(session->account.identity != NULL) {
1556
                                        g_hash_table_remove(identities, session->account.identity);
1557
                                        g_free(session->account.identity);
1558
                                }
1559
                                session->account.identity = NULL;
1560
                                session->account.sips = TRUE;
1561
                                if(session->account.username != NULL)
1562
                                        g_free(session->account.username);
1563
                                session->account.username = NULL;
1564
                                if(session->account.display_name != NULL)
1565
                                        g_free(session->account.display_name);
1566
                                session->account.display_name = NULL;
1567
                                if(session->account.authuser != NULL)
1568
                                        g_free(session->account.authuser);
1569
                                session->account.authuser = NULL;
1570
                                if(session->account.secret != NULL)
1571
                                        g_free(session->account.secret);
1572
                                session->account.secret = NULL;
1573
                                session->account.secret_type = janus_sip_secret_type_unknown;
1574
                                if(session->account.proxy != NULL)
1575
                                        g_free(session->account.proxy);
1576
                                session->account.proxy = NULL;
1577
                                if(session->account.outbound_proxy != NULL)
1578
                                        g_free(session->account.outbound_proxy);
1579
                                session->account.outbound_proxy = NULL;
1580
                                if(session->account.user_agent != NULL)
1581
                                        g_free(session->account.user_agent);
1582
                                session->account.user_agent = NULL;
1583
                                session->account.registration_status = janus_sip_registration_status_unregistered;
1584
                        }
1585
                        session->account.identity = g_strdup(username_text);
1586
                        g_hash_table_insert(identities, session->account.identity, session);
1587
                        session->account.sips = sips;
1588
                        session->account.username = g_strdup(user_id);
1589
                        session->account.authuser = g_strdup(authuser_text ? authuser_text : user_id);
1590
                        session->account.secret = secret_text ? g_strdup(secret_text) : NULL;
1591
                        session->account.secret_type = secret_type;
1592
                        if(display_name_text) {
1593
                                session->account.display_name = g_strdup(display_name_text);
1594
                        }
1595
                        if(user_agent_text) {
1596
                                session->account.user_agent = g_strdup(user_agent_text);
1597
                        }
1598
                        if(proxy_text) {
1599
                                session->account.proxy = g_strdup(proxy_text);
1600
                        }
1601
                        if(obproxy_text) {
1602
                                session->account.outbound_proxy = g_strdup(obproxy_text);
1603
                        }
1604

    
1605
                        session->account.registration_status = janus_sip_registration_status_registering;
1606
                        if(!refresh && session->stack == NULL) {
1607
                                /* Start the thread first */
1608
                                GError *error = NULL;
1609
                                char tname[16];
1610
                                g_snprintf(tname, sizeof(tname), "sip %s", session->account.username);
1611
                                g_thread_try_new(tname, janus_sip_sofia_thread, session, &error);
1612
                                if(error != NULL) {
1613
                                        JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the SIP Sofia thread...\n", error->code, error->message ? error->message : "??");
1614
                                        error_code = JANUS_SIP_ERROR_UNKNOWN_ERROR;
1615
                                        g_snprintf(error_cause, 512, "Got error %d (%s) trying to launch the SIP Sofia thread", error->code, error->message ? error->message : "??");
1616
                                        goto error;
1617
                                }
1618
                                long int timeout = 0;
1619
                                while(session->stack == NULL || session->stack->s_nua == NULL) {
1620
                                        g_usleep(100000);
1621
                                        timeout += 100000;
1622
                                        if(timeout >= 2000000) {
1623
                                                break;
1624
                                        }
1625
                                }
1626
                                if(timeout >= 2000000) {
1627
                                        JANUS_LOG(LOG_ERR, "Two seconds passed and still no NUA, problems with the thread?\n");
1628
                                        error_code = JANUS_SIP_ERROR_UNKNOWN_ERROR;
1629
                                        g_snprintf(error_cause, 512, "Two seconds passed and still no NUA, problems with the thread?");
1630
                                        goto error;
1631
                                }
1632
                        }
1633
                        if(session->stack->s_nh_r != NULL) {
1634
                                nua_handle_destroy(session->stack->s_nh_r);
1635
                                session->stack->s_nh_r = NULL;
1636
                        }
1637

    
1638
                        if(send_register) {
1639
                                /* Check if the REGISTER needs to be enriched with custom headers */
1640
                                char custom_headers[2048];
1641
                                custom_headers[0] = '\0';
1642
                                json_t *headers = json_object_get(root, "headers");
1643
                                if(headers) {
1644
                                        if(json_object_size(headers) > 0) {
1645
                                                /* Parse custom headers */
1646
                                                const char *key = NULL;
1647
                                                json_t *value = NULL;
1648
                                                void *iter = json_object_iter(headers);
1649
                                                while(iter != NULL) {
1650
                                                        key = json_object_iter_key(iter);
1651
                                                        value = json_object_get(headers, key);
1652
                                                        if(value == NULL || !json_is_string(value)) {
1653
                                                                JANUS_LOG(LOG_WARN, "Skipping header '%s': value is not a string\n", key);
1654
                                                                iter = json_object_iter_next(headers, iter);
1655
                                                                continue;
1656
                                                        }
1657
                                                        char h[255];
1658
                                                        g_snprintf(h, 255, "%s: %s\r\n", key, json_string_value(value));
1659
                                                        JANUS_LOG(LOG_VERB, "Adding custom header, %s", h);
1660
                                                        g_strlcat(custom_headers, h, 2048);
1661
                                                        iter = json_object_iter_next(headers, iter);
1662
                                                }
1663
                                        }
1664
                                }
1665
                                session->stack->s_nh_r = nua_handle(session->stack->s_nua, session, TAG_END());
1666
                                if(session->stack->s_nh_r == NULL) {
1667
                                        JANUS_LOG(LOG_ERR, "NUA Handle for REGISTER still null??\n");
1668
                                        error_code = JANUS_SIP_ERROR_LIBSOFIA_ERROR;
1669
                                        g_snprintf(error_cause, 512, "Invalid NUA Handle");
1670
                                        goto error;
1671
                                }
1672
                                char ttl_text[20];
1673
                                g_snprintf(ttl_text, sizeof(ttl_text), "%d", ttl);
1674
                                nua_register(session->stack->s_nh_r,
1675
                                        NUTAG_M_USERNAME(session->account.authuser),
1676
                                        NUTAG_M_DISPLAY(session->account.display_name),
1677
                                        SIPTAG_FROM_STR(username_text),
1678
                                        SIPTAG_TO_STR(username_text),
1679
                                        TAG_IF(strlen(custom_headers) > 0, SIPTAG_HEADER_STR(custom_headers)),
1680
                                        SIPTAG_EXPIRES_STR(ttl_text),
1681
                                        NUTAG_REGISTRAR(proxy_text),
1682
                                        NUTAG_PROXY(obproxy_text),
1683
                                        TAG_END());
1684
                                result = json_object();
1685
                                json_object_set_new(result, "event", json_string("registering"));
1686
                        } else {
1687
                                JANUS_LOG(LOG_VERB, "Not sending a SIP REGISTER: either send_register was set to false or guest mode was enabled\n");
1688
                                session->account.registration_status = janus_sip_registration_status_disabled;
1689
                                result = json_object();
1690
                                json_object_set_new(result, "event", json_string("registered"));
1691
                                json_object_set_new(result, "username", json_string(session->account.username));
1692
                                json_object_set_new(result, "register_sent", json_false());
1693
                                /* Also notify event handlers */
1694
                                if(notify_events && gateway->events_is_enabled()) {
1695
                                        json_t *info = json_object();
1696
                                        json_object_set_new(info, "event", json_string("registered"));
1697
                                        json_object_set_new(info, "identity", json_string(session->account.identity));
1698
                                        json_object_set_new(info, "type", json_string("guest"));
1699
                                        gateway->notify_event(&janus_sip_plugin, session->handle, info);
1700
                                }
1701
                        }
1702
                } else if(!strcasecmp(request_text, "unregister")) {
1703
                        if(session->stack == NULL) {
1704
                                JANUS_LOG(LOG_ERR, "Wrong state (register first)\n");
1705
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1706
                                g_snprintf(error_cause, 512, "Wrong state (register first)");
1707
                                goto error;
1708
                        }
1709
                        if(session->account.registration_status < janus_sip_registration_status_registered) {
1710
                                JANUS_LOG(LOG_ERR, "Wrong state (not registered)\n");
1711
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1712
                                g_snprintf(error_cause, 512, "Wrong state (not registered)");
1713
                                goto error;
1714
                        }
1715
                        if(session->stack->s_nh_r == NULL) {
1716
                                JANUS_LOG(LOG_ERR, "NUA Handle for REGISTER still null??\n");
1717
                                error_code = JANUS_SIP_ERROR_LIBSOFIA_ERROR;
1718
                                g_snprintf(error_cause, 512, "Invalid NUA Handle");
1719
                                goto error;
1720
                        }
1721
                        /* Unregister now */
1722
                        session->account.registration_status = janus_sip_registration_status_unregistering;
1723
                        nua_unregister(session->stack->s_nh_r, TAG_END());
1724
                        result = json_object();
1725
                        json_object_set_new(result, "event", json_string("unregistering"));
1726
                } else if(!strcasecmp(request_text, "call")) {
1727
                        /* Call another peer */
1728
                        if(session->stack == NULL) {
1729
                                JANUS_LOG(LOG_ERR, "Wrong state (register first)\n");
1730
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1731
                                g_snprintf(error_cause, 512, "Wrong state (register first)");
1732
                                goto error;
1733
                        }
1734
                        if(session->status >= janus_sip_call_status_inviting) {
1735
                                JANUS_LOG(LOG_ERR, "Wrong state (already in a call? status=%s)\n", janus_sip_call_status_string(session->status));
1736
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1737
                                g_snprintf(error_cause, 512, "Wrong state (already in a call? status=%s)", janus_sip_call_status_string(session->status));
1738
                                goto error;
1739
                        }
1740
                        JANUS_VALIDATE_JSON_OBJECT(root, call_parameters,
1741
                                error_code, error_cause, TRUE,
1742
                                JANUS_SIP_ERROR_MISSING_ELEMENT, JANUS_SIP_ERROR_INVALID_ELEMENT);
1743
                        if(error_code != 0)
1744
                                goto error;
1745
                        json_t *uri = json_object_get(root, "uri");
1746
                        /* Check if we need to ACK manually (e.g., for the Record-Route hack) */
1747
                        json_t *autoack = json_object_get(root, "autoack");
1748
                        gboolean do_autoack = autoack ? json_is_true(autoack) : TRUE;
1749
                        /* Check if the INVITE needs to be enriched with custom headers */
1750
                        char custom_headers[2048];
1751
                        custom_headers[0] = '\0';
1752
                        json_t *headers = json_object_get(root, "headers");
1753
                        if(headers) {
1754
                                if(json_object_size(headers) > 0) {
1755
                                        /* Parse custom headers */
1756
                                        const char *key = NULL;
1757
                                        json_t *value = NULL;
1758
                                        void *iter = json_object_iter(headers);
1759
                                        while(iter != NULL) {
1760
                                                key = json_object_iter_key(iter);
1761
                                                value = json_object_get(headers, key);
1762
                                                if(value == NULL || !json_is_string(value)) {
1763
                                                        JANUS_LOG(LOG_WARN, "Skipping header '%s': value is not a string\n", key);
1764
                                                        iter = json_object_iter_next(headers, iter);
1765
                                                        continue;
1766
                                                }
1767
                                                char h[255];
1768
                                                g_snprintf(h, 255, "%s: %s\r\n", key, json_string_value(value));
1769
                                                JANUS_LOG(LOG_VERB, "Adding custom header, %s", h);
1770
                                                g_strlcat(custom_headers, h, 2048);
1771
                                                iter = json_object_iter_next(headers, iter);
1772
                                        }
1773
                                }
1774
                        }
1775
                        /* SDES-SRTP is disabled by default, let's see if we need to enable it */
1776
                        gboolean offer_srtp = FALSE, require_srtp = FALSE;
1777
                        json_t *srtp = json_object_get(root, "srtp");
1778
                        if(srtp) {
1779
                                const char *srtp_text = json_string_value(srtp);
1780
                                if(!strcasecmp(srtp_text, "sdes_optional")) {
1781
                                        /* Negotiate SDES, but make it optional */
1782
                                        offer_srtp = TRUE;
1783
                                } else if(!strcasecmp(srtp_text, "sdes_mandatory")) {
1784
                                        /* Negotiate SDES, and require it */
1785
                                        offer_srtp = TRUE;
1786
                                        require_srtp = TRUE;
1787
                                } else {
1788
                                        JANUS_LOG(LOG_ERR, "Invalid element (srtp can only be sdes_optional or sdes_mandatory)\n");
1789
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
1790
                                        g_snprintf(error_cause, 512, "Invalid element (srtp can only be sdes_optional or sdes_mandatory)");
1791
                                        goto error;
1792
                                }
1793
                        }
1794
                        /* Parse address */
1795
                        const char *uri_text = json_string_value(uri);
1796
                        janus_sip_uri_t target_uri;
1797
                        if (janus_sip_parse_uri(&target_uri, uri_text) < 0) {
1798
                                JANUS_LOG(LOG_ERR, "Invalid user address %s\n", uri_text);
1799
                                error_code = JANUS_SIP_ERROR_INVALID_ADDRESS;
1800
                                g_snprintf(error_cause, 512, "Invalid user address %s\n", uri_text);
1801
                                goto error;
1802
                        }
1803
                        /* Any SDP to handle? if not, something's wrong */
1804
                        const char *msg_sdp_type = json_string_value(json_object_get(msg->jsep, "type"));
1805
                        const char *msg_sdp = json_string_value(json_object_get(msg->jsep, "sdp"));
1806
                        if(!msg_sdp) {
1807
                                JANUS_LOG(LOG_ERR, "Missing SDP\n");
1808
                                error_code = JANUS_SIP_ERROR_MISSING_SDP;
1809
                                g_snprintf(error_cause, 512, "Missing SDP");
1810
                                goto error;
1811
                        }
1812
                        if(strstr(msg_sdp, "m=application")) {
1813
                                JANUS_LOG(LOG_ERR, "The SIP plugin does not support DataChannels\n");
1814
                                error_code = JANUS_SIP_ERROR_MISSING_SDP;
1815
                                g_snprintf(error_cause, 512, "The SIP plugin does not support DataChannels");
1816
                                goto error;
1817
                        }
1818
                        JANUS_LOG(LOG_VERB, "%s is calling %s\n", session->account.username, uri_text);
1819
                        JANUS_LOG(LOG_VERB, "This is involving a negotiation (%s) as well:\n%s\n", msg_sdp_type, msg_sdp);
1820
                        /* Clean up SRTP stuff from before first, in case it's still needed */
1821
                        janus_sip_srtp_cleanup(session);
1822
                        session->media.require_srtp = require_srtp;
1823
                        session->media.has_srtp_local = offer_srtp;
1824
                        if(offer_srtp) {
1825
                                JANUS_LOG(LOG_VERB, "Going to negotiate SDES-SRTP (%s)...\n", require_srtp ? "mandatory" : "optional");
1826
                        }
1827
                        /* Parse the SDP we got, manipulate some things, and generate a new one */
1828
                        char sdperror[100];
1829
                        janus_sdp *parsed_sdp = janus_sdp_parse(msg_sdp, sdperror, sizeof(sdperror));
1830
                        if(!parsed_sdp) {
1831
                                JANUS_LOG(LOG_ERR, "Error parsing SDP: %s\n", sdperror);
1832
                                error_code = JANUS_SIP_ERROR_MISSING_SDP;
1833
                                g_snprintf(error_cause, 512, "Error parsing SDP: %s", sdperror);
1834
                                goto error;
1835
                        }
1836
                        /* Allocate RTP ports and merge them with the anonymized SDP */
1837
                        if(strstr(msg_sdp, "m=audio") && !strstr(msg_sdp, "m=audio 0")) {
1838
                                JANUS_LOG(LOG_VERB, "Going to negotiate audio...\n");
1839
                                session->media.has_audio = TRUE;        /* FIXME Maybe we need a better way to signal this */
1840
                        }
1841
                        if(strstr(msg_sdp, "m=video") && !strstr(msg_sdp, "m=video 0")) {
1842
                                JANUS_LOG(LOG_VERB, "Going to negotiate video...\n");
1843
                                session->media.has_video = TRUE;        /* FIXME Maybe we need a better way to signal this */
1844
                        }
1845
                        if(janus_sip_allocate_local_ports(session) < 0) {
1846
                                JANUS_LOG(LOG_ERR, "Could not allocate RTP/RTCP ports\n");
1847
                                janus_sdp_free(parsed_sdp);
1848
                                error_code = JANUS_SIP_ERROR_IO_ERROR;
1849
                                g_snprintf(error_cause, 512, "Could not allocate RTP/RTCP ports");
1850
                                goto error;
1851
                        }
1852
                        char *sdp = janus_sip_sdp_manipulate(session, parsed_sdp, FALSE);
1853
                        if(sdp == NULL) {
1854
                                JANUS_LOG(LOG_ERR, "Could not allocate RTP/RTCP ports\n");
1855
                                janus_sdp_free(parsed_sdp);
1856
                                error_code = JANUS_SIP_ERROR_IO_ERROR;
1857
                                g_snprintf(error_cause, 512, "Could not allocate RTP/RTCP ports");
1858
                                goto error;
1859
                        }
1860
                        /* Take note of the SDP (may be useful for UPDATEs or re-INVITEs) */
1861
                        janus_sdp_free(session->sdp);
1862
                        session->sdp = parsed_sdp;
1863
                        JANUS_LOG(LOG_VERB, "Prepared SDP for INVITE:\n%s", sdp);
1864
                        /* Prepare the From header */
1865
                        char from_hdr[1024];
1866
                        if (session->account.display_name) {
1867
                                g_snprintf(from_hdr, sizeof(from_hdr), "\"%s\" <%s>", session->account.display_name, session->account.identity);
1868
                        } else {
1869
                                g_snprintf(from_hdr, sizeof(from_hdr), "%s", session->account.identity);
1870
                        }
1871
                        /* Prepare the stack */
1872
                        if(session->stack->s_nh_i != NULL)
1873
                                nua_handle_destroy(session->stack->s_nh_i);
1874
                        session->stack->s_nh_i = nua_handle(session->stack->s_nua, session, TAG_END());
1875
                        if(session->stack->s_nh_i == NULL) {
1876
                                JANUS_LOG(LOG_WARN, "NUA Handle for INVITE still null??\n");
1877
                                g_free(sdp);
1878
                                session->sdp = NULL;
1879
                                janus_sdp_free(parsed_sdp);
1880
                                error_code = JANUS_SIP_ERROR_LIBSOFIA_ERROR;
1881
                                g_snprintf(error_cause, 512, "Invalid NUA Handle");
1882
                                goto error;
1883
                        }
1884
                        g_atomic_int_set(&session->hangingup, 0);
1885
                        session->status = janus_sip_call_status_inviting;
1886
                        /* Create a random call-id */
1887
                        char callid[24];
1888
                        janus_sip_random_string(24, (char *)&callid);
1889
                        /* Also notify event handlers */
1890
                        if(notify_events && gateway->events_is_enabled()) {
1891
                                json_t *info = json_object();
1892
                                json_object_set_new(info, "event", json_string("calling"));
1893
                                json_object_set_new(info, "callee", json_string(uri_text));
1894
                                json_object_set_new(info, "call-id", json_string(callid));
1895
                                json_object_set_new(info, "sdp", json_string(sdp));
1896
                                gateway->notify_event(&janus_sip_plugin, session->handle, info);
1897
                        }
1898
                        /* Send INVITE */
1899
                        session->callee = g_strdup(uri_text);
1900
                        session->callid = g_strdup(callid);
1901
                        g_hash_table_insert(callids, session->callid, session);
1902
                        session->media.autoack = do_autoack;
1903
                        nua_invite(session->stack->s_nh_i,
1904
                                SIPTAG_FROM_STR(from_hdr),
1905
                                SIPTAG_TO_STR(uri_text),
1906
                                SIPTAG_CALL_ID_STR(callid),
1907
                                SOATAG_USER_SDP_STR(sdp),
1908
                                NUTAG_PROXY(session->account.outbound_proxy),
1909
                                TAG_IF(strlen(custom_headers) > 0, SIPTAG_HEADER_STR(custom_headers)),
1910
                                NUTAG_AUTOANSWER(0),
1911
                                NUTAG_AUTOACK(do_autoack),
1912
                                TAG_END());
1913
                        g_free(sdp);
1914
                        if(session->transaction)
1915
                                g_free(session->transaction);
1916
                        session->transaction = msg->transaction ? g_strdup(msg->transaction) : NULL;
1917
                        /* Send an ack back */
1918
                        result = json_object();
1919
                        json_object_set_new(result, "event", json_string("calling"));
1920
                } else if(!strcasecmp(request_text, "accept")) {
1921
                        if(session->status != janus_sip_call_status_invited) {
1922
                                JANUS_LOG(LOG_ERR, "Wrong state (not invited? status=%s)\n", janus_sip_call_status_string(session->status));
1923
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1924
                                g_snprintf(error_cause, 512, "Wrong state (not invited? status=%s)", janus_sip_call_status_string(session->status));
1925
                                goto error;
1926
                        }
1927
                        if(session->callee == NULL) {
1928
                                JANUS_LOG(LOG_ERR, "Wrong state (no caller?)\n");
1929
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
1930
                                g_snprintf(error_cause, 512, "Wrong state (no caller?)");
1931
                                goto error;
1932
                        }
1933
                        JANUS_VALIDATE_JSON_OBJECT(root, accept_parameters,
1934
                                error_code, error_cause, TRUE,
1935
                                JANUS_SIP_ERROR_MISSING_ELEMENT, JANUS_SIP_ERROR_INVALID_ELEMENT);
1936
                        if(error_code != 0)
1937
                                goto error;
1938
                        json_t *srtp = json_object_get(root, "srtp");
1939
                        gboolean answer_srtp = FALSE;
1940
                        if(srtp) {
1941
                                const char *srtp_text = json_string_value(srtp);
1942
                                if(!strcasecmp(srtp_text, "sdes_optional")) {
1943
                                        /* Negotiate SDES, but make it optional */
1944
                                        answer_srtp = TRUE;
1945
                                } else if(!strcasecmp(srtp_text, "sdes_mandatory")) {
1946
                                        /* Negotiate SDES, and require it */
1947
                                        answer_srtp = TRUE;
1948
                                        session->media.require_srtp = TRUE;
1949
                                } else {
1950
                                        JANUS_LOG(LOG_ERR, "Invalid element (srtp can only be sdes_optional or sdes_mandatory)\n");
1951
                                        error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
1952
                                        g_snprintf(error_cause, 512, "Invalid element (srtp can only be sdes_optional or sdes_mandatory)");
1953
                                        goto error;
1954
                                }
1955
                        }
1956
                        if(session->media.require_srtp && !session->media.has_srtp_remote) {
1957
                                JANUS_LOG(LOG_ERR, "Can't accept the call: SDES-SRTP required, but caller didn't offer it\n");
1958
                                error_code = JANUS_SIP_ERROR_TOO_STRICT;
1959
                                g_snprintf(error_cause, 512, "Can't accept the call: SDES-SRTP required, but caller didn't offer it");
1960
                                goto error;
1961
                        }
1962
                        answer_srtp = answer_srtp || session->media.has_srtp_remote;
1963
                        /* Any SDP to handle? if not, something's wrong */
1964
                        const char *msg_sdp_type = json_string_value(json_object_get(msg->jsep, "type"));
1965
                        const char *msg_sdp = json_string_value(json_object_get(msg->jsep, "sdp"));
1966
                        if(!msg_sdp) {
1967
                                JANUS_LOG(LOG_ERR, "Missing SDP\n");
1968
                                error_code = JANUS_SIP_ERROR_MISSING_SDP;
1969
                                g_snprintf(error_cause, 512, "Missing SDP");
1970
                                goto error;
1971
                        }
1972
                        /* Accept a call from another peer */
1973
                        JANUS_LOG(LOG_VERB, "We're accepting the call from %s\n", session->callee);
1974
                        gboolean answer = !strcasecmp(msg_sdp_type, "answer");
1975
                        if(!answer) {
1976
                                JANUS_LOG(LOG_VERB, "This is a response to an offerless INVITE\n");
1977
                        }
1978
                        JANUS_LOG(LOG_VERB, "This is involving a negotiation (%s) as well:\n%s\n", msg_sdp_type, msg_sdp);
1979
                        session->media.has_srtp_local = answer_srtp;
1980
                        if(answer_srtp) {
1981
                                JANUS_LOG(LOG_VERB, "Going to negotiate SDES-SRTP (%s)...\n", session->media.require_srtp ? "mandatory" : "optional");
1982
                        }
1983
                        /* Parse the SDP we got, manipulate some things, and generate a new one */
1984
                        char sdperror[100];
1985
                        janus_sdp *parsed_sdp = janus_sdp_parse(msg_sdp, sdperror, sizeof(sdperror));
1986
                        if(!parsed_sdp) {
1987
                                JANUS_LOG(LOG_ERR, "Error parsing SDP: %s\n", sdperror);
1988
                                error_code = JANUS_SIP_ERROR_MISSING_SDP;
1989
                                g_snprintf(error_cause, 512, "Error parsing SDP: %s", sdperror);
1990
                                goto error;
1991
                        }
1992
                        /* Allocate RTP ports and merge them with the anonymized SDP */
1993
                        if(strstr(msg_sdp, "m=audio") && !strstr(msg_sdp, "m=audio 0")) {
1994
                                JANUS_LOG(LOG_VERB, "Going to negotiate audio...\n");
1995
                                session->media.has_audio = TRUE;        /* FIXME Maybe we need a better way to signal this */
1996
                        }
1997
                        if(strstr(msg_sdp, "m=video") && !strstr(msg_sdp, "m=video 0")) {
1998
                                JANUS_LOG(LOG_VERB, "Going to negotiate video...\n");
1999
                                session->media.has_video = TRUE;        /* FIXME Maybe we need a better way to signal this */
2000
                        }
2001
                        if(janus_sip_allocate_local_ports(session) < 0) {
2002
                                JANUS_LOG(LOG_ERR, "Could not allocate RTP/RTCP ports\n");
2003
                                janus_sdp_free(parsed_sdp);
2004
                                error_code = JANUS_SIP_ERROR_IO_ERROR;
2005
                                g_snprintf(error_cause, 512, "Could not allocate RTP/RTCP ports");
2006
                                goto error;
2007
                        }
2008
                        char *sdp = janus_sip_sdp_manipulate(session, parsed_sdp, TRUE);
2009
                        if(sdp == NULL) {
2010
                                JANUS_LOG(LOG_ERR, "Could not allocate RTP/RTCP ports\n");
2011
                                janus_sdp_free(parsed_sdp);
2012
                                error_code = JANUS_SIP_ERROR_IO_ERROR;
2013
                                g_snprintf(error_cause, 512, "Could not allocate RTP/RTCP ports");
2014
                                goto error;
2015
                        }
2016
                        if(session->media.audio_pt > -1) {
2017
                                session->media.audio_pt_name = janus_get_codec_from_pt(sdp, session->media.audio_pt);
2018
                                JANUS_LOG(LOG_VERB, "Detected audio codec: %d (%s)\n", session->media.audio_pt, session->media.audio_pt_name);
2019
                        }
2020
                        if(session->media.video_pt > -1) {
2021
                                session->media.video_pt_name = janus_get_codec_from_pt(sdp, session->media.video_pt);
2022
                                JANUS_LOG(LOG_VERB, "Detected video codec: %d (%s)\n", session->media.video_pt, session->media.video_pt_name);
2023
                        }
2024
                        /* Take note of the SDP (may be useful for UPDATEs or re-INVITEs) */
2025
                        janus_sdp_free(session->sdp);
2026
                        session->sdp = parsed_sdp;
2027
                        JANUS_LOG(LOG_VERB, "Prepared SDP for 200 OK:\n%s", sdp);
2028
                        /* Also notify event handlers */
2029
                        if(notify_events && gateway->events_is_enabled()) {
2030
                                json_t *info = json_object();
2031
                                json_object_set_new(info, "event", json_string(answer ? "accepted" : "accepting"));
2032
                                if(session->callid)
2033
                                        json_object_set_new(info, "call-id", json_string(session->callid));
2034
                                gateway->notify_event(&janus_sip_plugin, session->handle, info);
2035
                        }
2036
                        /* Send 200 OK */
2037
                        if(!answer) {
2038
                                if(session->transaction)
2039
                                        g_free(session->transaction);
2040
                                session->transaction = msg->transaction ? g_strdup(msg->transaction) : NULL;
2041
                        }
2042
                        g_atomic_int_set(&session->hangingup, 0);
2043
                        session->status = janus_sip_call_status_incall;
2044
                        if(session->stack->s_nh_i == NULL) {
2045
                                JANUS_LOG(LOG_WARN, "NUA Handle for 200 OK still null??\n");
2046
                        }
2047
                        nua_respond(session->stack->s_nh_i,
2048
                                200, sip_status_phrase(200),
2049
                                SOATAG_USER_SDP_STR(sdp),
2050
                                NUTAG_AUTOANSWER(0),
2051
                                TAG_END());
2052
                        g_free(sdp);
2053
                        /* Send an ack back */
2054
                        result = json_object();
2055
                        json_object_set_new(result, "event", json_string(answer ? "accepted" : "accepting"));
2056
                        if(answer) {
2057
                                /* Start the media */
2058
                                session->media.ready = TRUE;        /* FIXME Maybe we need a better way to signal this */
2059
                                GError *error = NULL;
2060
                                char tname[16];
2061
                                g_snprintf(tname, sizeof(tname), "siprtp %s", session->account.username);
2062
                                g_thread_try_new(tname, janus_sip_relay_thread, session, &error);
2063
                                if(error != NULL) {
2064
                                        JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the RTP/RTCP thread...\n", error->code, error->message ? error->message : "??");
2065
                                }
2066
                        }
2067
                } else if(!strcasecmp(request_text, "decline")) {
2068
                        /* Reject an incoming call */
2069
                        if(session->status != janus_sip_call_status_invited) {
2070
                                JANUS_LOG(LOG_ERR, "Wrong state (not invited? status=%s)\n", janus_sip_call_status_string(session->status));
2071
                                /* Ignore */
2072
                                janus_sip_message_free(msg);
2073
                                continue;
2074
                                //~ g_snprintf(error_cause, 512, "Wrong state (not in a call?)");
2075
                                //~ goto error;
2076
                        }
2077
                        if(session->callee == NULL) {
2078
                                JANUS_LOG(LOG_ERR, "Wrong state (no callee?)\n");
2079
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
2080
                                g_snprintf(error_cause, 512, "Wrong state (no callee?)");
2081
                                goto error;
2082
                        }
2083
                        session->media.earlymedia = FALSE;
2084
                        session->media.ready = FALSE;
2085
                        session->media.on_hold = FALSE;
2086
                        session->status = janus_sip_call_status_closing;
2087
                        if(session->stack->s_nh_i == NULL) {
2088
                                JANUS_LOG(LOG_WARN, "NUA Handle for 200 OK still null??\n");
2089
                        }
2090
                        int response_code = 486;
2091
                        json_t *code_json = json_object_get(root, "code");
2092
                        if (code_json && json_is_integer(code_json))
2093
                                response_code = json_integer_value(code_json);
2094
                        if (response_code <= 399) {
2095
                                JANUS_LOG(LOG_WARN, "Invalid SIP response code specified, using 486 to decline call\n");
2096
                                response_code = 486;
2097
                        }
2098
                        nua_respond(session->stack->s_nh_i, response_code, sip_status_phrase(response_code), TAG_END());
2099
                        /* Also notify event handlers */
2100
                        if(notify_events && gateway->events_is_enabled()) {
2101
                                json_t *info = json_object();
2102
                                json_object_set_new(info, "event", json_string("declined"));
2103
                                json_object_set_new(info, "callee", json_string(session->callee));
2104
                                if(session->callid)
2105
                                        json_object_set_new(info, "call-id", json_string(session->callid));
2106
                                json_object_set_new(info, "code", json_integer(response_code));
2107
                                gateway->notify_event(&janus_sip_plugin, session->handle, info);
2108
                        }
2109
                        g_free(session->callee);
2110
                        session->callee = NULL;
2111
                        /* Notify the operation */
2112
                        result = json_object();
2113
                        json_object_set_new(result, "event", json_string("declining"));
2114
                        json_object_set_new(result, "code", json_integer(response_code));
2115
                } else if(!strcasecmp(request_text, "hold") || !strcasecmp(request_text, "unhold")) {
2116
                        /* We either need to put the call on-hold, or resume it */
2117
                        if(!(session->status == janus_sip_call_status_inviting || session->status == janus_sip_call_status_incall)) {
2118
                                JANUS_LOG(LOG_ERR, "Wrong state (not in a call? status=%s)\n", janus_sip_call_status_string(session->status));
2119
                                /* Ignore */
2120
                                janus_sip_message_free(msg);
2121
                                continue;
2122
                                //~ g_snprintf(error_cause, 512, "Wrong state (not in a call?)");
2123
                                //~ goto error;
2124
                        }
2125
                        if(session->callee == NULL) {
2126
                                JANUS_LOG(LOG_ERR, "Wrong state (no callee?)\n");
2127
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
2128
                                g_snprintf(error_cause, 512, "Wrong state (no callee?)");
2129
                                goto error;
2130
                        }
2131
                        if(session->sdp == NULL) {
2132
                                JANUS_LOG(LOG_ERR, "Wrong state (no SDP?)\n");
2133
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
2134
                                g_snprintf(error_cause, 512, "Wrong state (no SDP?)");
2135
                                goto error;
2136
                        }
2137
                        gboolean hold = !strcasecmp(request_text, "hold");
2138
                        if(hold != session->media.on_hold) {
2139
                                /* To put the call on-hold, we need to set the direction to recvonly:
2140
                                 * resuming it means resuming the direction we had before */
2141
                                session->media.on_hold = hold;
2142
                                janus_sdp_mline *m = janus_sdp_mline_find(session->sdp, JANUS_SDP_AUDIO);
2143
                                if(m) {
2144
                                        if(hold) {
2145
                                                /* Take note of the original media direction */
2146
                                                session->media.pre_hold_audio_dir = m->direction;
2147
                                                /* Update the media direction */
2148
                                                switch(m->direction) {
2149
                                                        case JANUS_SDP_DEFAULT:
2150
                                                        case JANUS_SDP_SENDRECV:
2151
                                                                m->direction = JANUS_SDP_SENDONLY;
2152
                                                                break;
2153
                                                        default:
2154
                                                                m->direction = JANUS_SDP_INACTIVE;
2155
                                                                break;
2156
                                                }
2157
                                        } else {
2158
                                                m->direction = session->media.pre_hold_audio_dir;
2159
                                        }
2160
                                }
2161
                                m = janus_sdp_mline_find(session->sdp, JANUS_SDP_VIDEO);
2162
                                if(m) {
2163
                                        if(hold) {
2164
                                                /* Take note of the original media direction */
2165
                                                session->media.pre_hold_video_dir = m->direction;
2166
                                                /* Update the media direction */
2167
                                                switch(m->direction) {
2168
                                                        case JANUS_SDP_DEFAULT:
2169
                                                        case JANUS_SDP_SENDRECV:
2170
                                                                m->direction = JANUS_SDP_SENDONLY;
2171
                                                                break;
2172
                                                        default:
2173
                                                                m->direction = JANUS_SDP_INACTIVE;
2174
                                                                break;
2175
                                                }
2176
                                        } else {
2177
                                                m->direction = session->media.pre_hold_video_dir;
2178
                                        }
2179
                                }
2180
                                /* Send the re-INVITE */
2181
                                char *sdp = janus_sdp_write(session->sdp);
2182
                                nua_invite(session->stack->s_nh_i,
2183
                                        SOATAG_USER_SDP_STR(sdp),
2184
                                        TAG_END());
2185
                                g_free(sdp);
2186
                        }
2187
                        /* Send an ack back */
2188
                        result = json_object();
2189
                        json_object_set_new(result, "event", json_string(hold ? "holding" : "resuming"));
2190
                } else if(!strcasecmp(request_text, "hangup")) {
2191
                        /* Hangup an ongoing call */
2192
                        if(!(session->status == janus_sip_call_status_inviting || session->status == janus_sip_call_status_incall)) {
2193
                                JANUS_LOG(LOG_ERR, "Wrong state (not in a call? status=%s)\n", janus_sip_call_status_string(session->status));
2194
                                /* Ignore */
2195
                                janus_sip_message_free(msg);
2196
                                continue;
2197
                                //~ g_snprintf(error_cause, 512, "Wrong state (not in a call?)");
2198
                                //~ goto error;
2199
                        }
2200
                        if(session->callee == NULL) {
2201
                                JANUS_LOG(LOG_ERR, "Wrong state (no callee?)\n");
2202
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
2203
                                g_snprintf(error_cause, 512, "Wrong state (no callee?)");
2204
                                goto error;
2205
                        }
2206
                        session->media.earlymedia = FALSE;
2207
                        session->media.ready = FALSE;
2208
                        session->media.on_hold = FALSE;
2209
                        session->status = janus_sip_call_status_closing;
2210
                        nua_bye(session->stack->s_nh_i, TAG_END());
2211
                        g_free(session->callee);
2212
                        session->callee = NULL;
2213
                        /* Notify the operation */
2214
                        result = json_object();
2215
                        json_object_set_new(result, "event", json_string("hangingup"));
2216
                } else if(!strcasecmp(request_text, "recording")) {
2217
                        /* Start or stop recording */
2218
                        if(!(session->status == janus_sip_call_status_inviting || session->status == janus_sip_call_status_incall)) {
2219
                                JANUS_LOG(LOG_ERR, "Wrong state (not in a call? status=%s)\n", janus_sip_call_status_string(session->status));
2220
                                g_snprintf(error_cause, 512, "Wrong state (not in a call?)");
2221
                                goto error;
2222
                        }
2223
                        if(session->callee == NULL) {
2224
                                JANUS_LOG(LOG_ERR, "Wrong state (no callee?)\n");
2225
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
2226
                                g_snprintf(error_cause, 512, "Wrong state (no callee?)");
2227
                                goto error;
2228
                        }
2229
                        JANUS_VALIDATE_JSON_OBJECT(root, recording_parameters,
2230
                                error_code, error_cause, TRUE,
2231
                                JANUS_SIP_ERROR_MISSING_ELEMENT, JANUS_SIP_ERROR_INVALID_ELEMENT);
2232
                        if(error_code != 0)
2233
                                goto error;
2234
                        json_t *action = json_object_get(root, "action");
2235
                        const char *action_text = json_string_value(action);
2236
                        if(strcasecmp(action_text, "start") && strcasecmp(action_text, "stop")) {
2237
                                JANUS_LOG(LOG_ERR, "Invalid action (should be start|stop)\n");
2238
                                error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
2239
                                g_snprintf(error_cause, 512, "Invalid action (should be start|stop)");
2240
                                goto error;
2241
                        }
2242
                        gboolean record_audio = FALSE, record_video = FALSE,        /* No media is recorded by default */
2243
                                record_peer_audio = FALSE, record_peer_video = FALSE;
2244
                        json_t *audio = json_object_get(root, "audio");
2245
                        record_audio = audio ? json_is_true(audio) : FALSE;
2246
                        json_t *video = json_object_get(root, "video");
2247
                        record_video = video ? json_is_true(video) : FALSE;
2248
                        json_t *peer_audio = json_object_get(root, "peer_audio");
2249
                        record_peer_audio = peer_audio ? json_is_true(peer_audio) : FALSE;
2250
                        json_t *peer_video = json_object_get(root, "peer_video");
2251
                        record_peer_video = peer_video ? json_is_true(peer_video) : FALSE;
2252
                        if(!record_audio && !record_video && !record_peer_audio && !record_peer_video) {
2253
                                JANUS_LOG(LOG_ERR, "Invalid request (at least one of audio, video, peer_audio and peer_video should be true)\n");
2254
                                error_code = JANUS_SIP_ERROR_RECORDING_ERROR;
2255
                                g_snprintf(error_cause, 512, "Invalid request (at least one of audio, video, peer_audio and peer_video should be true)");
2256
                                goto error;
2257
                        }
2258
                        json_t *recfile = json_object_get(root, "filename");
2259
                        const char *recording_base = json_string_value(recfile);
2260
                        janus_mutex_lock(&session->rec_mutex);
2261
                        if(!strcasecmp(action_text, "start")) {
2262
                                /* Start recording something */
2263
                                char filename[255];
2264
                                gint64 now = janus_get_real_time();
2265
                                if(record_peer_audio || record_peer_video) {
2266
                                        JANUS_LOG(LOG_INFO, "Starting recording of peer's %s (user %s, call %s)\n",
2267
                                                (record_peer_audio && record_peer_video ? "audio and video" : (record_peer_audio ? "audio" : "video")),
2268
                                                session->account.username, session->transaction);
2269
                                        /* Start recording this peer's audio and/or video */
2270
                                        if(record_peer_audio) {
2271
                                                memset(filename, 0, 255);
2272
                                                if(recording_base) {
2273
                                                        /* Use the filename and path we have been provided */
2274
                                                        g_snprintf(filename, 255, "%s-peer-audio", recording_base);
2275
                                                        /* FIXME This only works if offer/answer happened */
2276
                                                        session->arc_peer = janus_recorder_create(NULL, session->media.audio_pt_name, filename);
2277
                                                        if(session->arc_peer == NULL) {
2278
                                                                /* FIXME We should notify the fact the recorder could not be created */
2279
                                                                JANUS_LOG(LOG_ERR, "Couldn't open an audio recording file for this peer!\n");
2280
                                                        }
2281
                                                } else {
2282
                                                        /* Build a filename */
2283
                                                        g_snprintf(filename, 255, "sip-%s-%s-%"SCNi64"-peer-audio",
2284
                                                                session->account.username ? session->account.username : "unknown",
2285
                                                                session->transaction ? session->transaction : "unknown",
2286
                                                                now);
2287
                                                        /* FIXME This only works if offer/answer happened */
2288
                                                        session->arc_peer = janus_recorder_create(NULL, session->media.audio_pt_name, filename);
2289
                                                        if(session->arc_peer == NULL) {
2290
                                                                /* FIXME We should notify the fact the recorder could not be created */
2291
                                                                JANUS_LOG(LOG_ERR, "Couldn't open an audio recording file for this peer!\n");
2292
                                                        }
2293
                                                }
2294
                                        }
2295
                                        if(record_peer_video) {
2296
                                                memset(filename, 0, 255);
2297
                                                if(recording_base) {
2298
                                                        /* Use the filename and path we have been provided */
2299
                                                        g_snprintf(filename, 255, "%s-peer-video", recording_base);
2300
                                                        /* FIXME This only works if offer/answer happened */
2301
                                                        session->vrc_peer = janus_recorder_create(NULL, session->media.video_pt_name, filename);
2302
                                                        if(session->vrc_peer == NULL) {
2303
                                                                /* FIXME We should notify the fact the recorder could not be created */
2304
                                                                JANUS_LOG(LOG_ERR, "Couldn't open an video recording file for this peer!\n");
2305
                                                        }
2306
                                                } else {
2307
                                                        /* Build a filename */
2308
                                                        g_snprintf(filename, 255, "sip-%s-%s-%"SCNi64"-peer-video",
2309
                                                                session->account.username ? session->account.username : "unknown",
2310
                                                                session->transaction ? session->transaction : "unknown",
2311
                                                                now);
2312
                                                        /* FIXME This only works if offer/answer happened */
2313
                                                        session->vrc_peer = janus_recorder_create(NULL, session->media.video_pt_name, filename);
2314
                                                        if(session->vrc_peer == NULL) {
2315
                                                                /* FIXME We should notify the fact the recorder could not be created */
2316
                                                                JANUS_LOG(LOG_ERR, "Couldn't open an video recording file for this peer!\n");
2317
                                                        }
2318
                                                }
2319
                                                /* TODO We should send a FIR/PLI to this peer... */
2320
                                        }
2321
                                }
2322
                                if(record_audio || record_video) {
2323
                                        /* Start recording the user's audio and/or video */
2324
                                        JANUS_LOG(LOG_INFO, "Starting recording of user's %s (user %s, call %s)\n",
2325
                                                (record_audio && record_video ? "audio and video" : (record_audio ? "audio" : "video")),
2326
                                                session->account.username, session->transaction);
2327
                                        if(record_audio) {
2328
                                                memset(filename, 0, 255);
2329
                                                if(recording_base) {
2330
                                                        /* Use the filename and path we have been provided */
2331
                                                        g_snprintf(filename, 255, "%s-user-audio", recording_base);
2332
                                                        /* FIXME This only works if offer/answer happened */
2333
                                                        session->arc = janus_recorder_create(NULL, session->media.audio_pt_name, filename);
2334
                                                        if(session->arc == NULL) {
2335
                                                                /* FIXME We should notify the fact the recorder could not be created */
2336
                                                                JANUS_LOG(LOG_ERR, "Couldn't open an audio recording file for this peer!\n");
2337
                                                        }
2338
                                                } else {
2339
                                                        /* Build a filename */
2340
                                                        g_snprintf(filename, 255, "sip-%s-%s-%"SCNi64"-own-audio",
2341
                                                                session->account.username ? session->account.username : "unknown",
2342
                                                                session->transaction ? session->transaction : "unknown",
2343
                                                                now);
2344
                                                        /* FIXME This only works if offer/answer happened */
2345
                                                        session->arc = janus_recorder_create(NULL, session->media.audio_pt_name, filename);
2346
                                                        if(session->arc == NULL) {
2347
                                                                /* FIXME We should notify the fact the recorder could not be created */
2348
                                                                JANUS_LOG(LOG_ERR, "Couldn't open an audio recording file for this peer!\n");
2349
                                                        }
2350
                                                }
2351
                                        }
2352
                                        if(record_video) {
2353
                                                memset(filename, 0, 255);
2354
                                                if(recording_base) {
2355
                                                        /* Use the filename and path we have been provided */
2356
                                                        g_snprintf(filename, 255, "%s-user-video", recording_base);
2357
                                                        /* FIXME This only works if offer/answer happened */
2358
                                                        session->vrc = janus_recorder_create(NULL, session->media.video_pt_name, filename);
2359
                                                        if(session->vrc == NULL) {
2360
                                                                /* FIXME We should notify the fact the recorder could not be created */
2361
                                                                JANUS_LOG(LOG_ERR, "Couldn't open an video recording file for this user!\n");
2362
                                                        }
2363
                                                } else {
2364
                                                        /* Build a filename */
2365
                                                        g_snprintf(filename, 255, "sip-%s-%s-%"SCNi64"-own-video",
2366
                                                                session->account.username ? session->account.username : "unknown",
2367
                                                                session->transaction ? session->transaction : "unknown",
2368
                                                                now);
2369
                                                        /* FIXME This only works if offer/answer happened */
2370
                                                        session->vrc = janus_recorder_create(NULL, session->media.video_pt_name, filename);
2371
                                                        if(session->vrc == NULL) {
2372
                                                                /* FIXME We should notify the fact the recorder could not be created */
2373
                                                                JANUS_LOG(LOG_ERR, "Couldn't open an video recording file for this user!\n");
2374
                                                        }
2375
                                                }
2376
                                                /* Send a PLI */
2377
                                                JANUS_LOG(LOG_VERB, "Recording video, sending a PLI to kickstart it\n");
2378
                                                char buf[12];
2379
                                                janus_rtcp_pli((char *)&buf, 12);
2380
                                                gateway->relay_rtcp(session->handle, 1, buf, 12);
2381
                                        }
2382
                                }
2383
                        } else {
2384
                                /* Stop recording something: notice that this never returns an error, even when we were not recording anything */
2385
                                if(record_audio) {
2386
                                        if(session->arc) {
2387
                                                janus_recorder_close(session->arc);
2388
                                                JANUS_LOG(LOG_INFO, "Closed user's audio recording %s\n", session->arc->filename ? session->arc->filename : "??");
2389
                                                janus_recorder_free(session->arc);
2390
                                        }
2391
                                        session->arc = NULL;
2392
                                }
2393
                                if(record_video) {
2394
                                        if(session->vrc) {
2395
                                                janus_recorder_close(session->vrc);
2396
                                                JANUS_LOG(LOG_INFO, "Closed user's video recording %s\n", session->vrc->filename ? session->vrc->filename : "??");
2397
                                                janus_recorder_free(session->vrc);
2398
                                        }
2399
                                        session->vrc = NULL;
2400
                                }
2401
                                if(record_peer_audio) {
2402
                                        if(session->arc_peer) {
2403
                                                janus_recorder_close(session->arc_peer);
2404
                                                JANUS_LOG(LOG_INFO, "Closed peer's audio recording %s\n", session->arc_peer->filename ? session->arc_peer->filename : "??");
2405
                                                janus_recorder_free(session->arc_peer);
2406
                                        }
2407
                                        session->arc_peer = NULL;
2408
                                }
2409
                                if(record_peer_video) {
2410
                                        if(session->vrc_peer) {
2411
                                                janus_recorder_close(session->vrc_peer);
2412
                                                JANUS_LOG(LOG_INFO, "Closed peer's video recording %s\n", session->vrc_peer->filename ? session->vrc_peer->filename : "??");
2413
                                                janus_recorder_free(session->vrc_peer);
2414
                                        }
2415
                                        session->vrc_peer = NULL;
2416
                                }
2417
                        }
2418
                        janus_mutex_unlock(&session->rec_mutex);
2419
                        /* Notify the result */
2420
                        result = json_object();
2421
                        json_object_set_new(result, "event", json_string("recordingupdated"));
2422
                } else if(!strcasecmp(request_text, "info")) {
2423
                        /* Send a SIP INFO request: we'll need the payload type and content */
2424
                        if(!(session->status == janus_sip_call_status_inviting || session->status == janus_sip_call_status_incall)) {
2425
                                JANUS_LOG(LOG_ERR, "Wrong state (not in a call? status=%s)\n", janus_sip_call_status_string(session->status));
2426
                                g_snprintf(error_cause, 512, "Wrong state (not in a call?)");
2427
                                goto error;
2428
                        }
2429
                        if(session->callee == NULL) {
2430
                                JANUS_LOG(LOG_ERR, "Wrong state (no callee?)\n");
2431
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
2432
                                g_snprintf(error_cause, 512, "Wrong state (no callee?)");
2433
                                goto error;
2434
                        }
2435
                        JANUS_VALIDATE_JSON_OBJECT(root, info_parameters,
2436
                                error_code, error_cause, TRUE,
2437
                                JANUS_SIP_ERROR_MISSING_ELEMENT, JANUS_SIP_ERROR_INVALID_ELEMENT);
2438
                        if(error_code != 0)
2439
                                goto error;
2440
                        const char *info_type = json_string_value(json_object_get(root, "type"));
2441
                        const char *info_content = json_string_value(json_object_get(root, "content"));
2442
                        nua_info(session->stack->s_nh_i,
2443
                                SIPTAG_CONTENT_TYPE_STR(info_type),
2444
                                SIPTAG_PAYLOAD_STR(info_content),
2445
                                TAG_END());
2446
                        /* Notify the operation */
2447
                        result = json_object();
2448
                        json_object_set_new(result, "event", json_string("infosent"));
2449
                } else if(!strcasecmp(request_text, "message")) {
2450
                        /* Send a SIP MESSAGE request: we'll only need the content */
2451
                        if(!(session->status == janus_sip_call_status_inviting || session->status == janus_sip_call_status_incall)) {
2452
                                JANUS_LOG(LOG_ERR, "Wrong state (not in a call? status=%s)\n", janus_sip_call_status_string(session->status));
2453
                                g_snprintf(error_cause, 512, "Wrong state (not in a call?)");
2454
                                goto error;
2455
                        }
2456
                        if(session->callee == NULL) {
2457
                                JANUS_LOG(LOG_ERR, "Wrong state (no callee?)\n");
2458
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
2459
                                g_snprintf(error_cause, 512, "Wrong state (no callee?)");
2460
                                goto error;
2461
                        }
2462
                        JANUS_VALIDATE_JSON_OBJECT(root, sipmessage_parameters,
2463
                                error_code, error_cause, TRUE,
2464
                                JANUS_SIP_ERROR_MISSING_ELEMENT, JANUS_SIP_ERROR_INVALID_ELEMENT);
2465
                        if(error_code != 0)
2466
                                goto error;
2467
                        const char *msg_content = json_string_value(json_object_get(root, "content"));
2468
                        nua_message(session->stack->s_nh_i,
2469
                                NUTAG_URL(session->callee),
2470
                                SIPTAG_PAYLOAD_STR(msg_content),
2471
                                TAG_END());
2472
                        /* Notify the operation */
2473
                        result = json_object();
2474
                        json_object_set_new(result, "event", json_string("messagesent"));
2475
                } else if(!strcasecmp(request_text, "dtmf_info")) {
2476
                        /* Send DMTF tones using SIP INFO
2477
                         * (https://tools.ietf.org/html/draft-kaplan-dispatch-info-dtmf-package-00)
2478
                         */
2479
                        if(!(session->status == janus_sip_call_status_inviting || session->status == janus_sip_call_status_incall)) {
2480
                                JANUS_LOG(LOG_ERR, "Wrong state (not in a call? status=%s)\n", janus_sip_call_status_string(session->status));
2481
                                g_snprintf(error_cause, 512, "Wrong state (not in a call?)");
2482
                                goto error;
2483
                        }
2484
                        if(session->callee == NULL) {
2485
                                JANUS_LOG(LOG_ERR, "Wrong state (no callee?)\n");
2486
                                error_code = JANUS_SIP_ERROR_WRONG_STATE;
2487
                                g_snprintf(error_cause, 512, "Wrong state (no callee?)");
2488
                                goto error;
2489
                        }
2490
                        JANUS_VALIDATE_JSON_OBJECT(root, dtmf_info_parameters,
2491
                                error_code, error_cause, TRUE,
2492
                                JANUS_SIP_ERROR_MISSING_ELEMENT, JANUS_SIP_ERROR_INVALID_ELEMENT);
2493
                        if(error_code != 0)
2494
                                goto error;
2495
                        json_t *digit = json_object_get(root, "digit");
2496
                        const char *digit_text = json_string_value(digit);
2497
                        if(strlen(digit_text) != 1) {
2498
                                JANUS_LOG(LOG_ERR, "Invalid element (digit should be one character))\n");
2499
                                error_code = JANUS_SIP_ERROR_INVALID_ELEMENT;
2500
                                g_snprintf(error_cause, 512, "Invalid element (digit should be one character)");
2501
                                goto error;
2502
                        }
2503
                        int duration_ms = 0;
2504
                        json_t *duration = json_object_get(root, "duration");
2505
                        duration_ms = duration ? json_integer_value(duration) : 0;
2506
                        if (duration_ms <= 0 || duration_ms > 5000) {
2507
                                duration_ms = 160; /* default value */
2508
                        }
2509
                        char payload[64];
2510
                        g_snprintf(payload, sizeof(payload), "Signal=%s\r\nDuration=%d", digit_text, duration_ms);
2511
                        nua_info(session->stack->s_nh_i,
2512
                                SIPTAG_CONTENT_TYPE_STR("application/dtmf-relay"),
2513
                                SIPTAG_PAYLOAD_STR(payload),
2514
                                TAG_END());
2515
                        /* Notify the result */
2516
                        result = json_object();
2517
                        json_object_set_new(result, "event", json_string("dtmfsent"));
2518
                } else {
2519
                        JANUS_LOG(LOG_ERR, "Unknown request (%s)\n", request_text);
2520
                        error_code = JANUS_SIP_ERROR_INVALID_REQUEST;
2521
                        g_snprintf(error_cause, 512, "Unknown request (%s)", request_text);
2522
                        goto error;
2523
                }
2524

    
2525
                /* Prepare JSON event */
2526
                json_t *event = json_object();
2527
                json_object_set_new(event, "sip", json_string("event"));
2528
                if(result != NULL)
2529
                        json_object_set_new(event, "result", result);
2530
                int ret = gateway->push_event(msg->handle, &janus_sip_plugin, msg->transaction, event, NULL);
2531
                JANUS_LOG(LOG_VERB, "  >> Pushing event: %d (%s)\n", ret, janus_get_api_error(ret));
2532
                json_decref(event);
2533
                janus_sip_message_free(msg);
2534
                continue;
2535

    
2536
error:
2537
                {
2538
                        /* Prepare JSON error event */
2539
                        json_t *event = json_object();
2540
                        json_object_set_new(event, "sip", json_string("event"));
2541
                        json_object_set_new(event, "error_code", json_integer(error_code));
2542
                        json_object_set_new(event, "error", json_string(error_cause));
2543
                        int ret = gateway->push_event(msg->handle, &janus_sip_plugin, msg->transaction, event, NULL);
2544
                        JANUS_LOG(LOG_VERB, "  >> Pushing event: %d (%s)\n", ret, janus_get_api_error(ret));
2545
                        json_decref(event);
2546
                        janus_sip_message_free(msg);
2547
                }
2548
        }
2549
        JANUS_LOG(LOG_VERB, "Leaving SIP handler thread\n");
2550
        return NULL;
2551
}
2552

    
2553

    
2554
/* Sofia callbacks */
2555
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[])
2556
{
2557
        janus_sip_session *session = (janus_sip_session *)magic;
2558
        ssip_t *ssip = session->stack;
2559

    
2560
        /* Notify event handlers about the content of the whole incoming SIP message, if any */
2561
        if(gateway->events_is_enabled() && ssip) {
2562
                /* Print the incoming message */
2563
                size_t msg_size = 0;
2564
                msg_t* msg = nua_current_request(nua);
2565
                if(msg) {
2566
                        char *msg_str = msg_as_string(ssip->s_home, msg, NULL, 0, &msg_size);
2567
                        json_t *info = json_object();
2568
                        json_object_set_new(info, "event", json_string("sip-in"));
2569
                        json_object_set_new(info, "sip", json_string(msg_str));
2570
                        gateway->notify_event(&janus_sip_plugin, session->handle, info);
2571
                }
2572
        }
2573

    
2574
        switch (event) {
2575
        /* Status or Error Indications */
2576
                case nua_i_active:
2577
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2578
                        break;
2579
                case nua_i_error:
2580
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2581
                        break;
2582
                case nua_i_fork:
2583
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2584
                        break;
2585
                case nua_i_media_error:
2586
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2587
                        break;
2588
                case nua_i_subscription:
2589
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2590
                        break;
2591
                case nua_i_state:
2592
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2593
                        tagi_t const *ti = tl_find(tags, nutag_callstate);
2594
                        enum nua_callstate callstate = ti ? ti->t_value : -1;
2595
                        /* There are several call states, but we care about the terminated state in order to send the 'hangup' event
2596
                         * and the proceeding state in order to send the 'proceeding' event so the client can play a ringback tone for
2597
                         * the user since we don't send early media. (assuming this is the right session, of course).
2598
                         * http://sofia-sip.sourceforge.net/refdocs/nua/nua__tag_8h.html#a516dc237722dc8ca4f4aa3524b2b444b
2599
                         */
2600
                        if (callstate == nua_callstate_proceeding &&
2601
                                    (session->stack->s_nh_i == nh || session->stack->s_nh_i == NULL)) {
2602
                                json_t *call = json_object();
2603
                                json_object_set_new(call, "sip", json_string("event"));
2604
                                json_t *calling = json_object();
2605
                                json_object_set_new(calling, "event", json_string("proceeding"));
2606
                                json_object_set_new(calling, "code", json_integer(status));
2607
                                json_object_set_new(call, "result", calling);
2608
                                int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call, NULL);
2609
                                JANUS_LOG(LOG_VERB, "  >> Pushing event: %d (%s)\n", ret, janus_get_api_error(ret));
2610
                                json_decref(call);
2611
                                /* Also notify event handlers */
2612
                                if(notify_events && gateway->events_is_enabled()) {
2613
                                        json_t *info = json_object();
2614
                                        json_object_set_new(info, "event", json_string("proceeding"));
2615
                                        if(session->callid)
2616
                                                json_object_set_new(info, "call-id", json_string(session->callid));
2617
                                        json_object_set_new(info, "code", json_integer(status));
2618
                                        gateway->notify_event(&janus_sip_plugin, session->handle, info);
2619
                                }
2620
                        } else if(callstate == nua_callstate_terminated &&
2621
                                        (session->stack->s_nh_i == nh || session->stack->s_nh_i == NULL)) {
2622
                                session->media.earlymedia = FALSE;
2623
                                session->media.ready = FALSE;
2624
                                session->media.on_hold = FALSE;
2625
                                session->status = janus_sip_call_status_idle;
2626
                                session->stack->s_nh_i = NULL;
2627
                                json_t *call = json_object();
2628
                                json_object_set_new(call, "sip", json_string("event"));
2629
                                json_t *calling = json_object();
2630
                                json_object_set_new(calling, "event", json_string("hangup"));
2631
                                json_object_set_new(calling, "code", json_integer(status));
2632
                                json_object_set_new(calling, "reason", json_string(phrase ? phrase : ""));
2633
                                json_object_set_new(call, "result", calling);
2634
                                int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call, NULL);
2635
                                JANUS_LOG(LOG_VERB, "  >> Pushing event: %d (%s)\n", ret, janus_get_api_error(ret));
2636
                                json_decref(call);
2637
                                /* Also notify event handlers */
2638
                                if(notify_events && gateway->events_is_enabled()) {
2639
                                        json_t *info = json_object();
2640
                                        json_object_set_new(info, "event", json_string("hangup"));
2641
                                        if(session->callid)
2642
                                                json_object_set_new(info, "call-id", json_string(session->callid));
2643
                                        json_object_set_new(info, "code", json_integer(status));
2644
                                        if(phrase)
2645
                                                json_object_set_new(info, "reason", json_string(phrase));
2646
                                        gateway->notify_event(&janus_sip_plugin, session->handle, info);
2647
                                }
2648
                                /* Get rid of any PeerConnection that may have been set up */
2649
                                if(session->callid)
2650
                                        g_hash_table_remove(callids, session->callid);
2651
                                g_free(session->callid);
2652
                                session->callid = NULL;
2653
                                g_free(session->transaction);
2654
                                session->transaction = NULL;
2655
                                gateway->close_pc(session->handle);
2656
                        }
2657
                        break;
2658
                case nua_i_terminated:
2659
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2660
                        break;
2661
        /* SIP requests */
2662
                case nua_i_ack: {
2663
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2664
                        /* We're only interested in this when there's been an offerless INVITE, as here's where we'd get our answer */
2665
                        if(sip->sip_payload && sip->sip_payload->pl_data) {
2666
                                JANUS_LOG(LOG_VERB, "This ACK contains a payload, probably as a result of an offerless INVITE: simulating 200 OK...\n");
2667
                                janus_sip_sofia_callback(nua_r_invite, 700, "ACK", nua, magic, nh, hmagic, sip, tags);
2668
                        }
2669
                        break;
2670
                }
2671
                case nua_i_outbound:
2672
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2673
                        break;
2674
                case nua_i_bye: {
2675
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2676
                        break;
2677
                }
2678
                case nua_i_cancel: {
2679
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2680
                        break;
2681
                }
2682
                case nua_i_invite: {
2683
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2684
                        if(ssip == NULL) {
2685
                                JANUS_LOG(LOG_ERR, "\tInvalid SIP stack\n");
2686
                                nua_respond(nh, 500, sip_status_phrase(500), TAG_END());
2687
                                break;
2688
                        }
2689
                        gboolean reinvite = FALSE;
2690
                        if(session->stack->s_nh_i != NULL) {
2691
                                if(session->stack->s_nh_i == nh) {
2692
                                        /* re-INVITE, we'll check what changed later */
2693
                                        reinvite = TRUE;
2694
                                        JANUS_LOG(LOG_VERB, "Got a re-INVITE...\n");
2695
                                } else if(session->status >= janus_sip_call_status_inviting) {
2696
                                        /* Busy with another call */
2697
                                        JANUS_LOG(LOG_VERB, "\tAlready in a call (busy, status=%s)\n", janus_sip_call_status_string(session->status));
2698
                                        nua_respond(nh, 486, sip_status_phrase(486), TAG_END());
2699
                                        /* Notify the web app about the missed invite */
2700
                                        json_t *missed = json_object();
2701
                                        json_object_set_new(missed, "sip", json_string("event"));
2702
                                        json_t *result = json_object();
2703
                                        json_object_set_new(result, "event", json_string("missed_call"));
2704
                                        char *caller_text = url_as_string(session->stack->s_home, sip->sip_from->a_url);
2705
                                        json_object_set_new(result, "caller", json_string(caller_text));
2706
                                        su_free(session->stack->s_home, caller_text);
2707
                                        if (sip->sip_from && sip->sip_from->a_display) {
2708
                                                json_object_set_new(result, "displayname", json_string(sip->sip_from->a_display));
2709
                                        }
2710
                                        json_object_set_new(missed, "result", result);
2711
                                        int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, missed, NULL);
2712
                                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
2713
                                        json_decref(missed);
2714
                                        /* Also notify event handlers */
2715
                                        if(notify_events && gateway->events_is_enabled()) {
2716
                                                json_t *info = json_object();
2717
                                                json_object_set_new(info, "event", json_string("missed_call"));
2718
                                                json_object_set_new(info, "caller", json_string(caller_text));
2719
                                                gateway->notify_event(&janus_sip_plugin, session->handle, info);
2720
                                        }
2721
                                        break;
2722
                                }
2723
                        }
2724
                        /* Check if there's an SDP to process */
2725
                        janus_sdp *sdp = NULL;
2726
                        if(!sip->sip_payload) {
2727
                                JANUS_LOG(LOG_VERB,"Received offerless %s\n", reinvite ? "re-INVITE" : "INVITE");
2728
                        } else {
2729
                                char sdperror[100];
2730
                                sdp = janus_sdp_parse(sip->sip_payload->pl_data, sdperror, sizeof(sdperror));
2731
                                if(!sdp) {
2732
                                        JANUS_LOG(LOG_ERR, "\tError parsing SDP! %s\n", sdperror);
2733
                                        nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
2734
                                        break;
2735
                                }
2736
                        }
2737
                        if(!reinvite) {
2738
                                /* New incoming call */
2739
                                session->callee = g_strdup(url_as_string(session->stack->s_home, sip->sip_from->a_url));
2740
                                session->callid = sip && sip->sip_call_id ? g_strdup(sip->sip_call_id->i_id) : NULL;
2741
                                if(session->callid)
2742
                                        g_hash_table_insert(callids, session->callid, session);
2743
                                session->status = janus_sip_call_status_invited;
2744
                                /* Clean up SRTP stuff from before first, in case it's still needed */
2745
                                janus_sip_srtp_cleanup(session);
2746
                        }
2747
                        /* Parse SDP */
2748
                        JANUS_LOG(LOG_VERB, "Someone is %s a call:\n%s",
2749
                                reinvite ? "updating" : "inviting us in",
2750
                                sip->sip_payload->pl_data);
2751
                        gboolean changed = FALSE;
2752
                        if(sdp) {
2753
                                janus_sip_sdp_process(session, sdp, FALSE, reinvite, &changed);
2754
                                /* Check if offer has neither audio nor video, fail with 488 */
2755
                                if(!session->media.has_audio && !session->media.has_video) {
2756
                                        nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
2757
                                        janus_sdp_free(sdp);
2758
                                        break;
2759
                                }
2760
                                /* Also fail with 488 if there's no remote IP address that can be used for RTP */
2761
                                if(!session->media.remote_ip) {
2762
                                        nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
2763
                                        janus_sdp_free(sdp);
2764
                                        break;
2765
                                }
2766
                        }
2767
                        if(reinvite) {
2768
                                /* No need to involve the browser: we reply ourselves */
2769
                                nua_respond(nh, 200, sip_status_phrase(200), TAG_END());
2770
                                janus_sdp_free(sdp);
2771
                                break;
2772
                        }
2773
                        /* Notify the browser about the call */
2774
                        json_t *jsep = NULL;
2775
                        if(sdp)
2776
                                jsep = json_pack("{ssss}", "type", "offer", "sdp", sip->sip_payload->pl_data);
2777
                        json_t *call = json_object();
2778
                        json_object_set_new(call, "sip", json_string("event"));
2779
                        json_t *calling = json_object();
2780
                        json_object_set_new(calling, "event", json_string("incomingcall"));
2781
                        json_object_set_new(calling, "username", json_string(session->callee));
2782
                        if(sip->sip_from && sip->sip_from->a_display) {
2783
                                json_object_set_new(calling, "displayname", json_string(sip->sip_from->a_display));
2784
                        }
2785
                        if(sdp && session->media.has_srtp_remote) {
2786
                                /* FIXME Maybe a true/false instead? */
2787
                                json_object_set_new(calling, "srtp", json_string(session->media.require_srtp ? "sdes_mandatory" : "sdes_optional"));
2788
                        }
2789
                        json_object_set_new(call, "result", calling);
2790
                        int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call, jsep);
2791
                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
2792
                        json_decref(call);
2793
                        if(jsep)
2794
                                json_decref(jsep);
2795
                        janus_sdp_free(sdp);
2796
                        /* Also notify event handlers */
2797
                        if(notify_events && gateway->events_is_enabled()) {
2798
                                json_t *info = json_object();
2799
                                json_object_set_new(info, "event", json_string("incomingcall"));
2800
                                if(session->callid)
2801
                                        json_object_set_new(info, "call-id", json_string(session->callid));
2802
                                json_object_set_new(info, "username", json_string(session->callee));
2803
                                if(sip->sip_from && sip->sip_from->a_display)
2804
                                        json_object_set_new(info, "displayname", json_string(sip->sip_from->a_display));
2805
                                gateway->notify_event(&janus_sip_plugin, session->handle, info);
2806
                        }
2807
                        /* Send a Ringing back */
2808
                        nua_respond(nh, 180, sip_status_phrase(180), TAG_END());
2809
                        session->stack->s_nh_i = nh;
2810
                        break;
2811
                }
2812
                case nua_i_info: {
2813
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2814
                        /* We expect a payload */
2815
                        if(!sip->sip_content_type || !sip->sip_content_type->c_type || !sip->sip_payload || !sip->sip_payload->pl_data) {
2816
                                nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
2817
                                return;
2818
                        }
2819
                        const char *type = sip->sip_content_type->c_type;
2820
                        char *payload = sip->sip_payload->pl_data;
2821
                        /* Notify the application */
2822
                        json_t *info = json_object();
2823
                        json_object_set_new(info, "sip", json_string("event"));
2824
                        json_t *result = json_object();
2825
                        json_object_set_new(result, "event", json_string("info"));
2826
                        char *caller_text = url_as_string(session->stack->s_home, sip->sip_from->a_url);
2827
                        json_object_set_new(result, "sender", json_string(caller_text));
2828
                        su_free(session->stack->s_home, caller_text);
2829
                        if(sip->sip_from && sip->sip_from->a_display && strlen(sip->sip_from->a_display) > 0) {
2830
                                json_object_set_new(result, "displayname", json_string(sip->sip_from->a_display));
2831
                        }
2832
                        json_object_set_new(result, "type", json_string(type));
2833
                        json_object_set_new(result, "content", json_string(payload));
2834
                        json_object_set_new(info, "result", result);
2835
                        int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, info, NULL);
2836
                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
2837
                        json_decref(info);
2838
                        /* Send a 200 back */
2839
                        nua_respond(nh, 200, sip_status_phrase(200), TAG_END());
2840
                        break;
2841
                }
2842
                case nua_i_message: {
2843
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2844
                        /* We expect a payload */
2845
                        if(!sip->sip_payload || !sip->sip_payload->pl_data) {
2846
                                nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
2847
                                return;
2848
                        }
2849
                        char *payload = sip->sip_payload->pl_data;
2850
                        /* Notify the application */
2851
                        json_t *message = json_object();
2852
                        json_object_set_new(message, "sip", json_string("event"));
2853
                        json_t *result = json_object();
2854
                        json_object_set_new(result, "event", json_string("message"));
2855
                        char *caller_text = url_as_string(session->stack->s_home, sip->sip_from->a_url);
2856
                        json_object_set_new(result, "sender", json_string(caller_text));
2857
                        su_free(session->stack->s_home, caller_text);
2858
                        if(sip->sip_from && sip->sip_from->a_display && strlen(sip->sip_from->a_display) > 0) {
2859
                                json_object_set_new(result, "displayname", json_string(sip->sip_from->a_display));
2860
                        }
2861
                        json_object_set_new(result, "content", json_string(payload));
2862
                        json_object_set_new(message, "result", result);
2863
                        int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, message, NULL);
2864
                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
2865
                        json_decref(message);
2866
                        /* Send a 200 back */
2867
                        nua_respond(nh, 200, sip_status_phrase(200), TAG_END());
2868
                        break;
2869
                }
2870
                case nua_i_options:
2871
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2872
                        /* FIXME Should we handle this message? for now we reply with a 405 Method Not Implemented */
2873
                        nua_respond(nh, 405, sip_status_phrase(405), TAG_END());
2874
                        break;
2875
        /* Responses */
2876
                case nua_r_get_params:
2877
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2878
                        break;
2879
                case nua_r_set_params:
2880
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2881
                        break;
2882
                case nua_r_notifier:
2883
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2884
                        break;
2885
                case nua_r_shutdown:
2886
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2887
                        if(status < 200 && !g_atomic_int_get(&stopping)) {
2888
                                /* shutdown in progress -> return */
2889
                                break;
2890
                        }
2891
                        if(ssip != NULL) {
2892
                                /* end the event loop. su_root_run() will return */
2893
                                su_root_break(ssip->s_root);
2894
                        }
2895
                        break;
2896
                case nua_r_terminate:
2897
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2898
                        break;
2899
        /* SIP responses */
2900
                case nua_r_bye:
2901
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2902
                        break;
2903
                case nua_r_cancel:
2904
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2905
                        break;
2906
                case nua_r_info:
2907
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2908
                        /* FIXME Should we notify the user, in case the SIP INFO returned an error? */
2909
                        break;
2910
                case nua_r_message:
2911
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2912
                        /* FIXME Should we notify the user, in case the SIP MESSAGE returned an error? */
2913
                        break;
2914
                case nua_r_invite: {
2915
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
2916

    
2917
                        gboolean in_progress = FALSE;
2918
                        if(status < 200) {
2919
                                /* Not ready yet, either notify the user (e.g., "ringing") or handle early media (if it's a 183) */
2920
                                if(status == 180) {
2921
                                        /* Ringing, notify the application */
2922
                                        json_t *ringing = json_object();
2923
                                        json_object_set_new(ringing, "sip", json_string("event"));
2924
                                        json_t *result = json_object();
2925
                                        json_object_set_new(result, "event", json_string("ringing"));
2926
                                        json_object_set_new(ringing, "result", result);
2927
                                        int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, ringing, NULL);
2928
                                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
2929
                                        json_decref(ringing);
2930
                                        break;
2931
                                } else if(status == 183) {
2932
                                        /* If's a Session Progress: check if there's an SDP, and if so, treat it like a 200 */
2933
                                        if(!sip->sip_payload->pl_data)
2934
                                                break;
2935
                                        in_progress = TRUE;
2936
                                } else {
2937
                                        /* Nothing to do, let's wait for a 200 OK */
2938
                                        break;
2939
                                }
2940
                        } else if(status == 401 || status == 407) {
2941
                                char auth[256];
2942
                                const char* scheme;
2943
                                const char* realm;
2944
                                if(status == 401) {
2945
                                         /* Get scheme/realm from 401 error */
2946
                                        sip_www_authenticate_t const* www_auth = sip->sip_www_authenticate;
2947
                                        scheme = www_auth->au_scheme;
2948
                                        realm = msg_params_find(www_auth->au_params, "realm=");
2949
                                } else {
2950
                                         /* Get scheme/realm from 407 error, proxy-auth */
2951
                                        sip_proxy_authenticate_t const* proxy_auth = sip->sip_proxy_authenticate;
2952
                                        scheme = proxy_auth->au_scheme;
2953
                                        realm = msg_params_find(proxy_auth->au_params, "realm=");
2954
                                }
2955
                                memset(auth, 0, sizeof(auth));
2956
                                g_snprintf(auth, sizeof(auth), "%s%s:%s:%s:%s%s",
2957
                                        session->account.secret_type == janus_sip_secret_type_hashed ? "HA1+" : "",
2958
                                        scheme,
2959
                                        realm,
2960
                                        session->account.authuser ? session->account.authuser : "null",
2961
                                        session->account.secret_type == janus_sip_secret_type_hashed ? "HA1+" : "",
2962
                                        session->account.secret ? session->account.secret : "null");
2963
                                JANUS_LOG(LOG_VERB, "\t%s\n", auth);
2964
                                /* Authenticate */
2965
                                nua_authenticate(nh,
2966
                                        NUTAG_AUTH(auth),
2967
                                        TAG_END());
2968
                                break;
2969
                        } else if(status == 700) {
2970
                                JANUS_LOG(LOG_VERB, "Handling SDP answer in ACK\n");
2971
                        } else if(status >= 400 && status != 700) {
2972
                                break;
2973
                        }
2974
                        if(ssip == NULL) {
2975
                                JANUS_LOG(LOG_ERR, "\tInvalid SIP stack\n");
2976
                                nua_respond(nh, 500, sip_status_phrase(500), TAG_END());
2977
                                break;
2978
                        }
2979
                        char sdperror[100];
2980
                        janus_sdp *sdp = janus_sdp_parse(sip->sip_payload->pl_data, sdperror, sizeof(sdperror));
2981
                        if(!sdp) {
2982
                                JANUS_LOG(LOG_ERR, "\tError parsing SDP! %s\n", sdperror);
2983
                                nua_respond(nh, 488, sip_status_phrase(488), TAG_END());
2984
                                break;
2985
                        }
2986
                        /* Send an ACK, if needed */
2987
                        if(!in_progress && !session->media.autoack) {
2988
                                char *route = sip->sip_record_route ? url_as_string(session->stack->s_home, sip->sip_record_route->r_url) : NULL;
2989
                                JANUS_LOG(LOG_INFO, "Sending ACK (route=%s)\n", route ? route : "none");
2990
                                nua_ack(nh,
2991
                                        TAG_IF(route, NTATAG_DEFAULT_PROXY(route)),
2992
                                        TAG_END());
2993
                        }
2994
                        /* Parse SDP */
2995
                        JANUS_LOG(LOG_VERB, "Peer accepted our call:\n%s", sip->sip_payload->pl_data);
2996
                        session->status = janus_sip_call_status_incall;
2997
                        char *fixed_sdp = sip->sip_payload->pl_data;
2998
                        gboolean changed = FALSE;
2999
                        gboolean update = session->media.ready;
3000
                        janus_sip_sdp_process(session, sdp, TRUE, update, &changed);
3001
                        /* If we asked for SRTP and are not getting it, fail */
3002
                        if(session->media.require_srtp && !session->media.has_srtp_remote) {
3003
                                JANUS_LOG(LOG_ERR, "\tWe asked for mandatory SRTP but didn't get any in the reply!\n");
3004
                                janus_sdp_free(sdp);
3005
                                /* Hangup immediately */
3006
                                session->media.earlymedia = FALSE;
3007
                                session->media.ready = FALSE;
3008
                                session->media.on_hold = FALSE;
3009
                                session->status = janus_sip_call_status_closing;
3010
                                nua_bye(nh, TAG_END());
3011
                                g_free(session->callee);
3012
                                session->callee = NULL;
3013
                                break;
3014
                        }
3015
                        if(!session->media.remote_ip) {
3016
                                /* No remote address parsed? Give up */
3017
                                JANUS_LOG(LOG_ERR, "\tNo remote IP address found for RTP, something's wrong with the SDP!\n");
3018
                                janus_sdp_free(sdp);
3019
                                /* Hangup immediately */
3020
                                session->media.earlymedia = FALSE;
3021
                                session->media.ready = FALSE;
3022
                                session->media.on_hold = FALSE;
3023
                                session->status = janus_sip_call_status_closing;
3024
                                nua_bye(nh, TAG_END());
3025
                                g_free(session->callee);
3026
                                session->callee = NULL;
3027
                                break;
3028
                        }
3029
                        if(session->media.audio_pt > -1) {
3030
                                session->media.audio_pt_name = janus_get_codec_from_pt(fixed_sdp, session->media.audio_pt);
3031
                                JANUS_LOG(LOG_VERB, "Detected audio codec: %d (%s)\n", session->media.audio_pt, session->media.audio_pt_name);
3032
                        }
3033
                        if(session->media.video_pt > -1) {
3034
                                session->media.video_pt_name = janus_get_codec_from_pt(fixed_sdp, session->media.video_pt);
3035
                                JANUS_LOG(LOG_VERB, "Detected video codec: %d (%s)\n", session->media.video_pt, session->media.video_pt_name);
3036
                        }
3037
                        session->media.ready = TRUE;        /* FIXME Maybe we need a better way to signal this */
3038
                        if(update && !session->media.earlymedia) {
3039
                                /* Don't push to the browser if this is in response to a hold/unhold we sent ourselves */
3040
                                JANUS_LOG(LOG_VERB, "This is an update to an existing call (possibly in response to hold/unhold)\n");
3041
                                break;
3042
                        }
3043
                        if(!session->media.earlymedia) {
3044
                                GError *error = NULL;
3045
                                char tname[16];
3046
                                g_snprintf(tname, sizeof(tname), "siprtp %s", session->account.username);
3047
                                g_thread_try_new(tname, janus_sip_relay_thread, session, &error);
3048
                                if(error != NULL) {
3049
                                        JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the RTP/RTCP thread...\n", error->code, error->message ? error->message : "??");
3050
                                }
3051
                        }
3052
                        /* Send event back to the browser */
3053
                        json_t *jsep = NULL;
3054
                        if(!session->media.earlymedia) {
3055
                                jsep = json_pack("{ssss}", "type", "answer", "sdp", fixed_sdp);
3056
                        } else {
3057
                                /* We've received the 200 OK after the 183, we can remove the flag now */
3058
                                session->media.earlymedia = FALSE;
3059
                        }
3060
                        if(in_progress) {
3061
                                /* If we just received the 183, set the flag instead so that we can handle the 200 OK differently */
3062
                                session->media.earlymedia = TRUE;
3063
                        }
3064
                        json_t *call = json_object();
3065
                        json_object_set_new(call, "sip", json_string("event"));
3066
                        json_t *calling = json_object();
3067
                        json_object_set_new(calling, "event", json_string(in_progress ? "progress" : "accepted"));
3068
                        json_object_set_new(calling, "username", json_string(session->callee));
3069
                        json_object_set_new(call, "result", calling);
3070
                        int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, call, jsep);
3071
                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3072
                        json_decref(call);
3073
                        json_decref(jsep);
3074
                        janus_sdp_free(sdp);
3075
                        /* Also notify event handlers */
3076
                        if(notify_events && gateway->events_is_enabled()) {
3077
                                json_t *info = json_object();
3078
                                json_object_set_new(info, "event", json_string(in_progress ? "progress" : "accepted"));
3079
                                if(session->callid)
3080
                                        json_object_set_new(info, "call-id", json_string(session->callid));
3081
                                json_object_set_new(info, "username", json_string(session->callee));
3082
                                gateway->notify_event(&janus_sip_plugin, session->handle, info);
3083
                        }
3084
                        break;
3085
                }
3086
                case nua_r_register:
3087
                case nua_r_unregister: {
3088
                        JANUS_LOG(LOG_VERB, "[%s][%s]: %d %s\n", session->account.username, nua_event_name(event), status, phrase ? phrase : "??");
3089
                        if(status == 200) {
3090
                                if(event == nua_r_register) {
3091
                                        if(session->account.registration_status < janus_sip_registration_status_registered)
3092
                                                session->account.registration_status = janus_sip_registration_status_registered;
3093
                                } else {
3094
                                        session->account.registration_status = janus_sip_registration_status_unregistered;
3095
                                }
3096
                                const char *event_name = (event == nua_r_register ? "registered" : "unregistered");
3097
                                JANUS_LOG(LOG_VERB, "Successfully %s\n", event_name);
3098
                                /* Notify the browser */
3099
                                json_t *reg = json_object();
3100
                                json_object_set_new(reg, "sip", json_string("event"));
3101
                                json_t *reging = json_object();
3102
                                json_object_set_new(reging, "event", json_string(event_name));
3103
                                json_object_set_new(reging, "username", json_string(session->account.username));
3104
                                if(event == nua_r_register)
3105
                                        json_object_set_new(reging, "register_sent", json_true());
3106
                                json_object_set_new(reg, "result", reging);
3107
                                int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, reg, NULL);
3108
                                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3109
                                json_decref(reg);
3110
                                /* Also notify event handlers */
3111
                                if(notify_events && gateway->events_is_enabled()) {
3112
                                        json_t *info = json_object();
3113
                                        json_object_set_new(info, "event", json_string(event_name));
3114
                                        json_object_set_new(info, "identity", json_string(session->account.identity));
3115
                                        if(session->account.proxy)
3116
                                                json_object_set_new(info, "proxy", json_string(session->account.proxy));
3117
                                        gateway->notify_event(&janus_sip_plugin, session->handle, info);
3118
                                }
3119
                        } else if(status == 401) {
3120
                                /* Get scheme/realm from 401 error */
3121
                                sip_www_authenticate_t const* www_auth = sip->sip_www_authenticate;
3122
                                char const* scheme = www_auth->au_scheme;
3123
                                const char* realm = msg_params_find(www_auth->au_params, "realm=");
3124
                                char auth[256];
3125
                                memset(auth, 0, sizeof(auth));
3126
                                g_snprintf(auth, sizeof(auth), "%s%s:%s:%s:%s%s",
3127
                                        session->account.secret_type == janus_sip_secret_type_hashed ? "HA1+" : "",
3128
                                        scheme,
3129
                                        realm,
3130
                                        session->account.authuser ? session->account.authuser : "null",
3131
                                        session->account.secret_type == janus_sip_secret_type_hashed ? "HA1+" : "",
3132
                                        session->account.secret);
3133
                                JANUS_LOG(LOG_VERB, "\t%s\n", auth);
3134
                                /* Authenticate */
3135
                                nua_authenticate(nh,
3136
                                        NUTAG_AUTH(auth),
3137
                                        TAG_END());
3138
                        } else if(status >= 400) {
3139
                                /* Authentication failed? */
3140
                                session->account.registration_status = janus_sip_registration_status_failed;
3141
                                /* Tell the browser... */
3142
                                json_t *event = json_object();
3143
                                json_object_set_new(event, "sip", json_string("event"));
3144
                                json_t *result = json_object();
3145
                                json_object_set_new(result, "event", json_string("registration_failed"));
3146
                                json_object_set_new(result, "code", json_integer(status));
3147
                                json_object_set_new(result, "reason", json_string(phrase ? phrase : ""));
3148
                                json_object_set_new(event, "result", result);
3149
                                int ret = gateway->push_event(session->handle, &janus_sip_plugin, session->transaction, event, NULL);
3150
                                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3151
                                json_decref(event);
3152
                                /* Also notify event handlers */
3153
                                if(notify_events && gateway->events_is_enabled()) {
3154
                                        json_t *info = json_object();
3155
                                        json_object_set_new(info, "event", json_string("registration_failed"));
3156
                                        json_object_set_new(info, "code", json_integer(status));
3157
                                        if(phrase)
3158
                                                json_object_set_new(info, "reason", json_string(phrase ? phrase : ""));
3159
                                        gateway->notify_event(&janus_sip_plugin, session->handle, info);
3160
                                }
3161
                        }
3162
                        break;
3163
                }
3164
                default:
3165
                        /* unknown event -> print out error message */
3166
                        JANUS_LOG(LOG_ERR, "Unknown event %d (%s)\n", event, nua_event_name(event));
3167
                        break;
3168
        }
3169
}
3170

    
3171
void janus_sip_sdp_process(janus_sip_session *session, janus_sdp *sdp, gboolean answer, gboolean update, gboolean *changed) {
3172
        if(!session || !sdp)
3173
                return;
3174
        /* c= */
3175
        if(sdp->c_addr) {
3176
                if(update && strcmp(sdp->c_addr, session->media.remote_ip)) {
3177
                        /* This is an update and an address changed */
3178
                        if(changed)
3179
                                *changed = TRUE;
3180
                }
3181
                g_free(session->media.remote_ip);
3182
                session->media.remote_ip = g_strdup(sdp->c_addr);
3183
        }
3184
        GList *temp = sdp->m_lines;
3185
        while(temp) {
3186
                janus_sdp_mline *m = (janus_sdp_mline *)temp->data;
3187
                session->media.require_srtp = session->media.require_srtp || (m->proto && !strcasecmp(m->proto, "RTP/SAVP"));
3188
                if(m->type == JANUS_SDP_AUDIO) {
3189
                        if(m->port) {
3190
                                if(m->port != session->media.remote_audio_rtp_port) {
3191
                                        /* This is an update and an address changed */
3192
                                        if(changed)
3193
                                                *changed = TRUE;
3194
                                }
3195
                                session->media.has_audio = TRUE;
3196
                                session->media.remote_audio_rtp_port = m->port;
3197
                                session->media.remote_audio_rtcp_port = m->port+1;        /* FIXME We're assuming RTCP is on the next port */
3198
                                if(m->direction == JANUS_SDP_SENDONLY || m->direction == JANUS_SDP_INACTIVE)
3199
                                        session->media.audio_send = FALSE;
3200
                                else
3201
                                        session->media.audio_send = TRUE;
3202
                        } else {
3203
                                session->media.audio_send = FALSE;
3204
                        }
3205
                } else if(m->type == JANUS_SDP_VIDEO) {
3206
                        if(m->port) {
3207
                                if(m->port != session->media.remote_video_rtp_port) {
3208
                                        /* This is an update and an address changed */
3209
                                        if(changed)
3210
                                                *changed = TRUE;
3211
                                }
3212
                                session->media.has_video = TRUE;
3213
                                session->media.remote_video_rtp_port = m->port;
3214
                                session->media.remote_video_rtcp_port = m->port+1;        /* FIXME We're assuming RTCP is on the next port */
3215
                                if(m->direction == JANUS_SDP_SENDONLY || m->direction == JANUS_SDP_INACTIVE)
3216
                                        session->media.video_send = FALSE;
3217
                                else
3218
                                        session->media.video_send = TRUE;
3219
                        } else {
3220
                                session->media.video_send = FALSE;
3221
                        }
3222
                } else {
3223
                        JANUS_LOG(LOG_WARN, "Unsupported media line (not audio/video)\n");
3224
                        temp = temp->next;
3225
                        continue;
3226
                }
3227
                if(m->c_addr) {
3228
                        if(update && strcmp(m->c_addr, session->media.remote_ip)) {
3229
                                /* This is an update and an address changed */
3230
                                if(changed)
3231
                                        *changed = TRUE;
3232
                        }
3233
                        g_free(session->media.remote_ip);
3234
                        session->media.remote_ip = g_strdup(m->c_addr);
3235
                }
3236
                if(update) {
3237
                        /* FIXME This is a session update, we only accept changes in IP/ports */
3238
                        temp = temp->next;
3239
                        continue;
3240
                }
3241
                GList *tempA = m->attributes;
3242
                while(tempA) {
3243
                        janus_sdp_attribute *a = (janus_sdp_attribute *)tempA->data;
3244
                        if(a->name) {
3245
                                if(!strcasecmp(a->name, "crypto")) {
3246
                                        if(m->type == JANUS_SDP_AUDIO || m->type == JANUS_SDP_VIDEO) {
3247
                                                gint32 tag = 0;
3248
                                                int suite;
3249
                                                char crypto[81];
3250
                                                /* FIXME inline can be more complex than that, and we're currently only offering SHA1_80 */
3251
                                                int res = sscanf(a->value, "%"SCNi32" AES_CM_128_HMAC_SHA1_%2d inline:%80s",
3252
                                                        &tag, &suite, crypto);
3253
                                                if(res != 3) {
3254
                                                        JANUS_LOG(LOG_WARN, "Failed to parse crypto line, ignoring... %s\n", a->value);
3255
                                                } else {
3256
                                                        gboolean video = (m->type == JANUS_SDP_VIDEO);
3257
                                                        int current_suite = video ? session->media.video_srtp_suite_in : session->media.audio_srtp_suite_in;
3258
                                                        if(current_suite == 0) {
3259
                                                                if(video)
3260
                                                                        session->media.video_srtp_suite_in = suite;
3261
                                                                else
3262
                                                                        session->media.audio_srtp_suite_in = suite;
3263
                                                                janus_sip_srtp_set_remote(session, video, crypto, suite);
3264
                                                                session->media.has_srtp_remote = TRUE;
3265
                                                        } else {
3266
                                                                JANUS_LOG(LOG_WARN, "We already configured a %s crypto context (AES_CM_128_HMAC_SHA1_%d), skipping additional crypto line\n",
3267
                                                                        video ? "video" : "audio", current_suite);
3268
                                                        }
3269
                                                }
3270
                                        }
3271
                                }
3272
                        }
3273
                        tempA = tempA->next;
3274
                }
3275
                if(answer && (m->type == JANUS_SDP_AUDIO || m->type == JANUS_SDP_VIDEO)) {
3276
                        /* Check which codec was negotiated eventually */
3277
                        int pt = -1;
3278
                        if(m->ptypes)
3279
                                pt = GPOINTER_TO_INT(m->ptypes->data);
3280
                        if(pt > -1) {
3281
                                if(m->type == JANUS_SDP_AUDIO) {
3282
                                        session->media.audio_pt = pt;
3283
                                } else {
3284
                                        session->media.video_pt = pt;
3285
                                }
3286
                        }
3287
                }
3288
                temp = temp->next;
3289
        }
3290
        if(update && changed && *changed) {
3291
                /* Something changed: mark this on the session, so that the thread can update the sockets */
3292
                session->media.updated = TRUE;
3293
                if(session->media.pipefd[1] > 0) {
3294
                        int code = 1;
3295
                        ssize_t res = 0;
3296
                        do {
3297
                                res = write(session->media.pipefd[1], &code, sizeof(int));
3298
                        } while(res == -1 && errno == EINTR);
3299
                }
3300
        }
3301
}
3302

    
3303
char *janus_sip_sdp_manipulate(janus_sip_session *session, janus_sdp *sdp, gboolean answer) {
3304
        if(!session || !session->stack || !sdp)
3305
                return NULL;
3306
        /* Start replacing stuff */
3307
        JANUS_LOG(LOG_VERB, "Setting protocol to %s\n", session->media.require_srtp ? "RTP/SAVP" : "RTP/AVP");
3308
        GList *temp = sdp->m_lines;
3309
        while(temp) {
3310
                janus_sdp_mline *m = (janus_sdp_mline *)temp->data;
3311
                g_free(m->proto);
3312
                m->proto = g_strdup(session->media.require_srtp ? "RTP/SAVP" : "RTP/AVP");
3313
                if(m->type == JANUS_SDP_AUDIO) {
3314
                        m->port = session->media.local_audio_rtp_port;
3315
                        if(session->media.has_srtp_local) {
3316
                                char *crypto = NULL;
3317
                                session->media.audio_srtp_suite_out = 80;
3318
                                janus_sip_srtp_set_local(session, FALSE, &crypto);
3319
                                /* FIXME 32? 80? Both? */
3320
                                janus_sdp_attribute *a = janus_sdp_attribute_create("crypto", "1 AES_CM_128_HMAC_SHA1_80 inline:%s", crypto);
3321
                                g_free(crypto);
3322
                                m->attributes = g_list_append(m->attributes, a);
3323
                        }
3324
                } else if(m->type == JANUS_SDP_VIDEO) {
3325
                        m->port = session->media.local_video_rtp_port;
3326
                        if(session->media.has_srtp_local) {
3327
                                char *crypto = NULL;
3328
                                session->media.audio_srtp_suite_out = 80;
3329
                                janus_sip_srtp_set_local(session, TRUE, &crypto);
3330
                                /* FIXME 32? 80? Both? */
3331
                                janus_sdp_attribute *a = janus_sdp_attribute_create("crypto", "1 AES_CM_128_HMAC_SHA1_80 inline:%s", crypto);
3332
                                g_free(crypto);
3333
                                m->attributes = g_list_append(m->attributes, a);
3334
                        }
3335
                }
3336
                g_free(m->c_addr);
3337
                m->c_addr = g_strdup(local_ip);
3338
                if(answer && (m->type == JANUS_SDP_AUDIO || m->type == JANUS_SDP_VIDEO)) {
3339
                        /* Check which codec was negotiated eventually */
3340
                        int pt = -1;
3341
                        if(m->ptypes)
3342
                                pt = GPOINTER_TO_INT(m->ptypes->data);
3343
                        if(pt > -1) {
3344
                                if(m->type == JANUS_SDP_AUDIO) {
3345
                                        session->media.audio_pt = pt;
3346
                                } else {
3347
                                        session->media.video_pt = pt;
3348
                                }
3349
                        }
3350
                }
3351
                temp = temp->next;
3352
        }
3353
        /* Generate a SDP string out of our changes */
3354
        return janus_sdp_write(sdp);
3355
}
3356

    
3357
/* Bind local RTP/RTCP sockets */
3358
static int janus_sip_allocate_local_ports(janus_sip_session *session) {
3359
        if(session == NULL) {
3360
                JANUS_LOG(LOG_ERR, "Invalid session\n");
3361
                return -1;
3362
        }
3363
        /* Reset status */
3364
        if(session->media.audio_rtp_fd != -1) {
3365
                close(session->media.audio_rtp_fd);
3366
                session->media.audio_rtp_fd = -1;
3367
        }
3368
        if(session->media.audio_rtcp_fd != -1) {
3369
                close(session->media.audio_rtcp_fd);
3370
                session->media.audio_rtcp_fd = -1;
3371
        }
3372
        session->media.local_audio_rtp_port = 0;
3373
        session->media.local_audio_rtcp_port = 0;
3374
        session->media.audio_ssrc = 0;
3375
        if(session->media.video_rtp_fd != -1) {
3376
                close(session->media.video_rtp_fd);
3377
                session->media.video_rtp_fd = -1;
3378
        }
3379
        if(session->media.video_rtcp_fd != -1) {
3380
                close(session->media.video_rtcp_fd);
3381
                session->media.video_rtcp_fd = -1;
3382
        }
3383
        session->media.local_video_rtp_port = 0;
3384
        session->media.local_video_rtcp_port = 0;
3385
        session->media.video_ssrc = 0;
3386
        if(session->media.pipefd[0] > 0) {
3387
                close(session->media.pipefd[0]);
3388
                session->media.pipefd[0] = -1;
3389
        }
3390
        if(session->media.pipefd[1] > 0) {
3391
                close(session->media.pipefd[1]);
3392
                session->media.pipefd[1] = -1;
3393
        }
3394
        /* Start */
3395
        int attempts = 100;        /* FIXME Don't retry forever */
3396
        if(session->media.has_audio) {
3397
                JANUS_LOG(LOG_VERB, "Allocating audio ports:\n");
3398
                struct sockaddr_in audio_rtp_address, audio_rtcp_address;
3399
                while(session->media.local_audio_rtp_port == 0 || session->media.local_audio_rtcp_port == 0) {
3400
                        if(attempts == 0)        /* Too many failures */
3401
                                return -1;
3402
                        if(session->media.audio_rtp_fd == -1) {
3403
                                session->media.audio_rtp_fd = socket(AF_INET, SOCK_DGRAM, 0);
3404
                        }
3405
                        if(session->media.audio_rtcp_fd == -1) {
3406
                                session->media.audio_rtcp_fd = socket(AF_INET, SOCK_DGRAM, 0);
3407
                        }
3408
                        int rtp_port = g_random_int_range(10000, 60000);        /* FIXME Should this be configurable? */
3409
                        if(rtp_port % 2)
3410
                                rtp_port++;        /* Pick an even port for RTP */
3411
                        audio_rtp_address.sin_family = AF_INET;
3412
                        audio_rtp_address.sin_port = htons(rtp_port);
3413
                        inet_pton(AF_INET, local_ip, &audio_rtp_address.sin_addr.s_addr);
3414
                        if(bind(session->media.audio_rtp_fd, (struct sockaddr *)(&audio_rtp_address), sizeof(struct sockaddr)) < 0) {
3415
                                JANUS_LOG(LOG_ERR, "Bind failed for audio RTP (port %d), trying a different one...\n", rtp_port);
3416
                                attempts--;
3417
                                continue;
3418
                        }
3419
                        JANUS_LOG(LOG_VERB, "Audio RTP listener bound to port %d\n", rtp_port);
3420
                        int rtcp_port = rtp_port+1;
3421
                        audio_rtcp_address.sin_family = AF_INET;
3422
                        audio_rtcp_address.sin_port = htons(rtcp_port);
3423
                        inet_pton(AF_INET, local_ip, &audio_rtcp_address.sin_addr.s_addr);
3424
                        if(bind(session->media.audio_rtcp_fd, (struct sockaddr *)(&audio_rtcp_address), sizeof(struct sockaddr)) < 0) {
3425
                                JANUS_LOG(LOG_ERR, "Bind failed for audio RTCP (port %d), trying a different one...\n", rtcp_port);
3426
                                /* RTP socket is not valid anymore, reset it */
3427
                                close(session->media.audio_rtp_fd);
3428
                                session->media.audio_rtp_fd = -1;
3429
                                attempts--;
3430
                                continue;
3431
                        }
3432
                        JANUS_LOG(LOG_VERB, "Audio RTCP listener bound to port %d\n", rtcp_port);
3433
                        session->media.local_audio_rtp_port = rtp_port;
3434
                        session->media.local_audio_rtcp_port = rtcp_port;
3435
                }
3436
        }
3437
        if(session->media.has_video) {
3438
                JANUS_LOG(LOG_VERB, "Allocating video ports:\n");
3439
                struct sockaddr_in video_rtp_address, video_rtcp_address;
3440
                while(session->media.local_video_rtp_port == 0 || session->media.local_video_rtcp_port == 0) {
3441
                        if(attempts == 0)        /* Too many failures */
3442
                                return -1;
3443
                        if(session->media.video_rtp_fd == -1) {
3444
                                session->media.video_rtp_fd = socket(AF_INET, SOCK_DGRAM, 0);
3445
                        }
3446
                        if(session->media.video_rtcp_fd == -1) {
3447
                                session->media.video_rtcp_fd = socket(AF_INET, SOCK_DGRAM, 0);
3448
                        }
3449
                        int rtp_port = g_random_int_range(10000, 60000);        /* FIXME Should this be configurable? */
3450
                        if(rtp_port % 2)
3451
                                rtp_port++;        /* Pick an even port for RTP */
3452
                        video_rtp_address.sin_family = AF_INET;
3453
                        video_rtp_address.sin_port = htons(rtp_port);
3454
                        inet_pton(AF_INET, local_ip, &video_rtp_address.sin_addr.s_addr);
3455
                        if(bind(session->media.video_rtp_fd, (struct sockaddr *)(&video_rtp_address), sizeof(struct sockaddr)) < 0) {
3456
                                JANUS_LOG(LOG_ERR, "Bind failed for video RTP (port %d), trying a different one...\n", rtp_port);
3457
                                attempts--;
3458
                                continue;
3459
                        }
3460
                        JANUS_LOG(LOG_VERB, "Video RTP listener bound to port %d\n", rtp_port);
3461
                        int rtcp_port = rtp_port+1;
3462
                        video_rtcp_address.sin_family = AF_INET;
3463
                        video_rtcp_address.sin_port = htons(rtcp_port);
3464
                        inet_pton(AF_INET, local_ip, &video_rtcp_address.sin_addr.s_addr);
3465
                        if(bind(session->media.video_rtcp_fd, (struct sockaddr *)(&video_rtcp_address), sizeof(struct sockaddr)) < 0) {
3466
                                JANUS_LOG(LOG_ERR, "Bind failed for video RTCP (port %d), trying a different one...\n", rtcp_port);
3467
                                /* RTP socket is not valid anymore, reset it */
3468
                                close(session->media.video_rtp_fd);
3469
                                session->media.video_rtp_fd = -1;
3470
                                attempts--;
3471
                                continue;
3472
                        }
3473
                        JANUS_LOG(LOG_VERB, "Video RTCP listener bound to port %d\n", rtcp_port);
3474
                        session->media.local_video_rtp_port = rtp_port;
3475
                        session->media.local_video_rtcp_port = rtcp_port;
3476
                }
3477
        }
3478
        /* We need this to quickly interrupt the poll when it's time to update a session or wrap up */
3479
        pipe(session->media.pipefd);
3480
        return 0;
3481
}
3482

    
3483
/* Helper method to (re)connect RTP/RTCP sockets */
3484
static void janus_sip_connect_sockets(janus_sip_session *session, struct sockaddr_in *server_addr) {
3485
        if(!session || !server_addr)
3486
                return;
3487

    
3488
        if(session->media.updated) {
3489
                JANUS_LOG(LOG_VERB, "Updating session sockets\n");
3490
        }
3491

    
3492
        /* Connect peers (FIXME This pretty much sucks right now) */
3493
        if(session->media.remote_audio_rtp_port) {
3494
                server_addr->sin_port = htons(session->media.remote_audio_rtp_port);
3495
                if(connect(session->media.audio_rtp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
3496
                        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);
3497
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
3498
                }
3499
        }
3500
        if(session->media.remote_audio_rtcp_port) {
3501
                server_addr->sin_port = htons(session->media.remote_audio_rtcp_port);
3502
                if(connect(session->media.audio_rtcp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
3503
                        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);
3504
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
3505
                }
3506
        }
3507
        if(session->media.remote_video_rtp_port) {
3508
                server_addr->sin_port = htons(session->media.remote_video_rtp_port);
3509
                if(connect(session->media.video_rtp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
3510
                        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);
3511
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
3512
                }
3513
        }
3514
        if(session->media.remote_video_rtcp_port) {
3515
                server_addr->sin_port = htons(session->media.remote_video_rtcp_port);
3516
                if(connect(session->media.video_rtcp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
3517
                        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);
3518
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
3519
                }
3520
        }
3521

    
3522
}
3523

    
3524
/* Thread to relay RTP/RTCP frames coming from the SIP peer */
3525
static void *janus_sip_relay_thread(void *data) {
3526
        janus_sip_session *session = (janus_sip_session *)data;
3527
        if(!session || !session->account.username || !session->callee) {
3528
                g_thread_unref(g_thread_self());
3529
                return NULL;
3530
        }
3531
        JANUS_LOG(LOG_VERB, "Starting relay thread (%s <--> %s)\n", session->account.username, session->callee);
3532

    
3533
        gboolean have_server_ip = TRUE;
3534
        struct sockaddr_in server_addr;
3535
        memset(&server_addr, 0, sizeof(server_addr));
3536
        server_addr.sin_family = AF_INET;
3537
        if(inet_aton(session->media.remote_ip, &server_addr.sin_addr) == 0) {        /* Not a numeric IP... */
3538
                struct hostent *host = gethostbyname(session->media.remote_ip);        /* ...resolve name */
3539
                if(!host) {
3540
                        JANUS_LOG(LOG_ERR, "[SIP-%s] Couldn't get host (%s)\n", session->account.username, session->media.remote_ip);
3541
                        have_server_ip = FALSE;
3542
                } else {
3543
                        server_addr.sin_addr = *(struct in_addr *)host->h_addr_list;
3544
                }
3545
        }
3546
        if(have_server_ip)
3547
                janus_sip_connect_sockets(session, &server_addr);
3548

    
3549
        if(!session->callee) {
3550
                JANUS_LOG(LOG_VERB, "[SIP-%s] Leaving thread, no callee...\n", session->account.username);
3551
                g_thread_unref(g_thread_self());
3552
                return NULL;
3553
        }
3554
        /* File descriptors */
3555
        socklen_t addrlen;
3556
        struct sockaddr_in remote;
3557
        int resfd = 0, bytes = 0;
3558
        struct pollfd fds[5];
3559
        int pipe_fd = session->media.pipefd[0];
3560
        char buffer[1500];
3561
        memset(buffer, 0, 1500);
3562
        /* Loop */
3563
        int num = 0;
3564
        gboolean goon = TRUE;
3565
        int astep = 0, vstep = 0;
3566
        guint32 ats = 0, vts = 0;
3567
        while(goon && session != NULL && !session->destroyed &&
3568
                        session->status > janus_sip_call_status_idle &&
3569
                        session->status < janus_sip_call_status_closing) {        /* FIXME We need a per-call watchdog as well */
3570

    
3571
                if(session->media.updated) {
3572
                        /* Apparently there was a session update */
3573
                        if(session->media.remote_ip != NULL && (inet_aton(session->media.remote_ip, &server_addr.sin_addr) != 0)) {
3574
                                janus_sip_connect_sockets(session, &server_addr);
3575
                        } else {
3576
                                JANUS_LOG(LOG_ERR, "[SIP-%p] Couldn't update session details: missing or invalid remote IP address? (%s)\n",
3577
                                        session->account.username, session->media.remote_ip);
3578
                        }
3579
                        session->media.updated = FALSE;
3580
                }
3581

    
3582
                /* Prepare poll */
3583
                num = 0;
3584
                if(session->media.audio_rtp_fd != -1) {
3585
                        fds[num].fd = session->media.audio_rtp_fd;
3586
                        fds[num].events = POLLIN;
3587
                        fds[num].revents = 0;
3588
                        num++;
3589
                }
3590
                if(session->media.audio_rtcp_fd != -1) {
3591
                        fds[num].fd = session->media.audio_rtcp_fd;
3592
                        fds[num].events = POLLIN;
3593
                        fds[num].revents = 0;
3594
                        num++;
3595
                }
3596
                if(session->media.video_rtp_fd != -1) {
3597
                        fds[num].fd = session->media.video_rtp_fd;
3598
                        fds[num].events = POLLIN;
3599
                        fds[num].revents = 0;
3600
                        num++;
3601
                }
3602
                if(session->media.video_rtcp_fd != -1) {
3603
                        fds[num].fd = session->media.video_rtcp_fd;
3604
                        fds[num].events = POLLIN;
3605
                        fds[num].revents = 0;
3606
                        num++;
3607
                }
3608
                if(pipe_fd != -1) {
3609
                        fds[num].fd = pipe_fd;
3610
                        fds[num].events = POLLIN;
3611
                        fds[num].revents = 0;
3612
                        num++;
3613
                }
3614
                /* Wait for some data */
3615
                resfd = poll(fds, num, 1000);
3616
                if(resfd < 0) {
3617
                        JANUS_LOG(LOG_ERR, "[SIP-%s] Error polling...\n", session->account.username);
3618
                        JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
3619
                        break;
3620
                } else if(resfd == 0) {
3621
                        /* No data, keep going */
3622
                        continue;
3623
                }
3624
                if(session == NULL || session->destroyed ||
3625
                                session->status <= janus_sip_call_status_idle ||
3626
                                session->status >= janus_sip_call_status_closing)
3627
                        break;
3628
                int i = 0;
3629
                for(i=0; i<num; i++) {
3630
                        if(fds[i].revents & (POLLERR | POLLHUP)) {
3631
                                /* If we just updated the session, let's wait until things have calmed down */
3632
                                if(session->media.updated)
3633
                                        break;
3634
                                /* Check the socket error */
3635
                                int error = 0;
3636
                                socklen_t errlen = sizeof(error);
3637
                                getsockopt(fds[i].fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
3638
                                if(error == 0) {
3639
                                        /* Maybe not a breaking error after all? */
3640
                                        continue;
3641
                                } else if(error == 111) {
3642
                                        /* ICMP error? If it's related to RTCP, let's just close the RTCP socket and move on */
3643
                                        if(fds[i].fd == session->media.audio_rtcp_fd) {
3644
                                                JANUS_LOG(LOG_WARN, "[SIP-%s] Got a '%s' on the audio RTCP socket, closing it\n",
3645
                                                        session->account.username, strerror(error));
3646
                                                close(session->media.audio_rtcp_fd);
3647
                                                session->media.audio_rtcp_fd = -1;
3648
                                        } else if(fds[i].fd == session->media.video_rtcp_fd) {
3649
                                                JANUS_LOG(LOG_WARN, "[SIP-%s] Got a '%s' on the video RTCP socket, closing it\n",
3650
                                                        session->account.username, strerror(error));
3651
                                                close(session->media.video_rtcp_fd);
3652
                                                session->media.video_rtcp_fd = -1;
3653
                                        }
3654
                                        /* FIXME Should we do the same with the RTP sockets as well? We may risk overreacting, there... */
3655
                                        continue;
3656
                                }
3657
                                JANUS_LOG(LOG_ERR, "[SIP-%s] Error polling %d (socket #%d): %s...\n", session->account.username,
3658
                                        fds[i].fd, i, fds[i].revents & POLLERR ? "POLLERR" : "POLLHUP");
3659
                                JANUS_LOG(LOG_ERR, "[SIP-%s]   -- %d (%s)\n", session->account.username, error, strerror(error));
3660
                                goon = FALSE;        /* Can we assume it's pretty much over, after a POLLERR? */
3661
                                /* FIXME Simulate a "hangup" coming from the browser */
3662
                                janus_sip_message *msg = g_malloc0(sizeof(janus_sip_message));
3663
                                msg->handle = session->handle;
3664
                                msg->message = json_pack("{ss}", "request", "hangup");
3665
                                msg->transaction = NULL;
3666
                                msg->jsep = NULL;
3667
                                g_async_queue_push(messages, msg);
3668
                                break;
3669
                        } else if(fds[i].revents & POLLIN) {
3670
                                if(pipe_fd != -1 && fds[i].fd == pipe_fd) {
3671
                                        /* Poll interrupted for a reason, go on */
3672
                                        int code = 0;
3673
                                        bytes = read(pipe_fd, &code, sizeof(int));
3674
                                        break;
3675
                                }
3676
                                /* Got an RTP/RTCP packet */
3677
                                if(session->media.audio_rtp_fd != -1 && fds[i].fd == session->media.audio_rtp_fd) {
3678
                                        /* Got something audio (RTP) */
3679
                                        addrlen = sizeof(remote);
3680
                                        bytes = recvfrom(session->media.audio_rtp_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
3681
                                        rtp_header *header = (rtp_header *)buffer;
3682
                                        if(session->media.audio_ssrc_peer != ntohl(header->ssrc)) {
3683
                                                session->media.audio_ssrc_peer = ntohl(header->ssrc);
3684
                                                JANUS_LOG(LOG_VERB, "Got SIP peer audio SSRC: %"SCNu32"\n", session->media.audio_ssrc_peer);
3685
                                        }
3686
                                        /* Is this SRTP? */
3687
                                        if(session->media.has_srtp_remote) {
3688
                                                int buflen = bytes;
3689
                                                srtp_err_status_t res = srtp_unprotect(session->media.audio_srtp_in, buffer, &buflen);
3690
                                                if(res != srtp_err_status_ok && res != srtp_err_status_replay_fail && res != srtp_err_status_replay_old) {
3691
                                                        guint32 timestamp = ntohl(header->timestamp);
3692
                                                        guint16 seq = ntohs(header->seq_number);
3693
                                                        JANUS_LOG(LOG_ERR, "[SIP-%s] Audio SRTP unprotect error: %s (len=%d-->%d, ts=%"SCNu32", seq=%"SCNu16")\n",
3694
                                                                session->account.username, janus_srtp_error_str(res), bytes, buflen, timestamp, seq);
3695
                                                        continue;
3696
                                                }
3697
                                                bytes = buflen;
3698
                                        }
3699
                                        /* Check if the SSRC changed (e.g., after a re-INVITE or UPDATE) */
3700
                                        guint32 timestamp = ntohl(header->timestamp);
3701
                                        janus_rtp_header_update(header, &session->media.context, FALSE, astep ? astep : 960);
3702
                                        if(ats == 0) {
3703
                                                ats = timestamp;
3704
                                        } else if(astep == 0) {
3705
                                                astep = timestamp-ats;
3706
                                                if(astep < 0)
3707
                                                        astep = 0;
3708
                                        }
3709
                                        /* Save the frame if we're recording */
3710
                                        janus_recorder_save_frame(session->arc_peer, buffer, bytes);
3711
                                        /* Relay to browser */
3712
                                        gateway->relay_rtp(session->handle, 0, buffer, bytes);
3713
                                        continue;
3714
                                } else if(session->media.audio_rtcp_fd != -1 && fds[i].fd == session->media.audio_rtcp_fd) {
3715
                                        /* Got something audio (RTCP) */
3716
                                        addrlen = sizeof(remote);
3717
                                        bytes = recvfrom(session->media.audio_rtcp_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
3718
                                        //~ JANUS_LOG(LOG_VERB, "************************\nGot %d bytes on the audio RTCP channel...\n", bytes);
3719
                                        /* Is this SRTCP? */
3720
                                        if(session->media.has_srtp_remote) {
3721
                                                int buflen = bytes;
3722
                                                srtp_err_status_t res = srtp_unprotect_rtcp(session->media.audio_srtp_in, buffer, &buflen);
3723
                                                if(res != srtp_err_status_ok && res != srtp_err_status_replay_fail && res != srtp_err_status_replay_old) {
3724
                                                        JANUS_LOG(LOG_ERR, "[SIP-%s] Audio SRTCP unprotect error: %s (len=%d-->%d)\n",
3725
                                                                session->account.username, janus_srtp_error_str(res), bytes, buflen);
3726
                                                        continue;
3727
                                                }
3728
                                                bytes = buflen;
3729
                                        }
3730
                                        /* Relay to browser */
3731
                                        gateway->relay_rtcp(session->handle, 0, buffer, bytes);
3732
                                        continue;
3733
                                } else if(session->media.video_rtp_fd != -1 && fds[i].fd == session->media.video_rtp_fd) {
3734
                                        /* Got something video (RTP) */
3735
                                        addrlen = sizeof(remote);
3736
                                        bytes = recvfrom(session->media.video_rtp_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
3737
                                        //~ JANUS_LOG(LOG_VERB, "************************\nGot %d bytes on the video RTP channel...\n", bytes);
3738
                                        //~ rtp_header_t *rtp = (rtp_header_t *)buffer;
3739
                                        //~ JANUS_LOG(LOG_VERB, " ... parsed RTP packet (ssrc=%u, pt=%u, seq=%u, ts=%u)...\n",
3740
                                                //~ ntohl(rtp->ssrc), rtp->type, ntohs(rtp->seq_number), ntohl(rtp->timestamp));
3741
                                        rtp_header *header = (rtp_header *)buffer;
3742
                                        if(session->media.video_ssrc_peer != ntohl(header->ssrc)) {
3743
                                                session->media.video_ssrc_peer = ntohl(header->ssrc);
3744
                                                JANUS_LOG(LOG_VERB, "Got SIP peer video SSRC: %"SCNu32"\n", session->media.video_ssrc_peer);
3745
                                        }
3746
                                        /* Is this SRTP? */
3747
                                        if(session->media.has_srtp_remote) {
3748
                                                int buflen = bytes;
3749
                                                srtp_err_status_t res = srtp_unprotect(session->media.video_srtp_in, buffer, &buflen);
3750
                                                if(res != srtp_err_status_ok && res != srtp_err_status_replay_fail && res != srtp_err_status_replay_old) {
3751
                                                        guint32 timestamp = ntohl(header->timestamp);
3752
                                                        guint16 seq = ntohs(header->seq_number);
3753
                                                        JANUS_LOG(LOG_ERR, "[SIP-%s] Video SRTP unprotect error: %s (len=%d-->%d, ts=%"SCNu32", seq=%"SCNu16")\n",
3754
                                                                session->account.username, janus_srtp_error_str(res), bytes, buflen, timestamp, seq);
3755
                                                        continue;
3756
                                                }
3757
                                                bytes = buflen;
3758
                                        }
3759
                                        /* Check if the SSRC changed (e.g., after a re-INVITE or UPDATE) */
3760
                                        janus_rtp_header_update(header, &session->media.context, TRUE, vstep ? vstep : 4500);
3761
                                        guint32 timestamp = ntohl(header->timestamp);
3762
                                        if(vts == 0) {
3763
                                                vts = timestamp;
3764
                                        } else if(vstep == 0) {
3765
                                                vstep = timestamp-vts;
3766
                                                if(vstep < 0)
3767
                                                        vstep = 0;
3768
                                        }
3769
                                        /* Save the frame if we're recording */
3770
                                        janus_recorder_save_frame(session->vrc_peer, buffer, bytes);
3771
                                        /* Relay to browser */
3772
                                        gateway->relay_rtp(session->handle, 1, buffer, bytes);
3773
                                        continue;
3774
                                } else if(session->media.video_rtcp_fd != -1 && fds[i].fd == session->media.video_rtcp_fd) {
3775
                                        /* Got something video (RTCP) */
3776
                                        addrlen = sizeof(remote);
3777
                                        bytes = recvfrom(session->media.video_rtcp_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
3778
                                        //~ JANUS_LOG(LOG_VERB, "************************\nGot %d bytes on the video RTCP channel...\n", bytes);
3779
                                        /* Is this SRTCP? */
3780
                                        if(session->media.has_srtp_remote) {
3781
                                                int buflen = bytes;
3782
                                                srtp_err_status_t res = srtp_unprotect_rtcp(session->media.video_srtp_in, buffer, &buflen);
3783
                                                if(res != srtp_err_status_ok && res != srtp_err_status_replay_fail && res != srtp_err_status_replay_old) {
3784
                                                        JANUS_LOG(LOG_ERR, "[SIP-%s] Video SRTP unprotect error: %s (len=%d-->%d)\n",
3785
                                                                session->account.username, janus_srtp_error_str(res), bytes, buflen);
3786
                                                        continue;
3787
                                                }
3788
                                                bytes = buflen;
3789
                                        }
3790
                                        /* Relay to browser */
3791
                                        gateway->relay_rtcp(session->handle, 1, buffer, bytes);
3792
                                        continue;
3793
                                }
3794
                        }
3795
                }
3796
        }
3797
        if(session->media.audio_rtp_fd != -1) {
3798
                close(session->media.audio_rtp_fd);
3799
                session->media.audio_rtp_fd = -1;
3800
        }
3801
        if(session->media.audio_rtcp_fd != -1) {
3802
                close(session->media.audio_rtcp_fd);
3803
                session->media.audio_rtcp_fd = -1;
3804
        }
3805
        session->media.local_audio_rtp_port = 0;
3806
        session->media.local_audio_rtcp_port = 0;
3807
        session->media.audio_ssrc = 0;
3808
        if(session->media.video_rtp_fd != -1) {
3809
                close(session->media.video_rtp_fd);
3810
                session->media.video_rtp_fd = -1;
3811
        }
3812
        if(session->media.video_rtcp_fd != -1) {
3813
                close(session->media.video_rtcp_fd);
3814
                session->media.video_rtcp_fd = -1;
3815
        }
3816
        session->media.local_video_rtp_port = 0;
3817
        session->media.local_video_rtcp_port = 0;
3818
        session->media.video_ssrc = 0;
3819
        if(session->media.pipefd[0] > 0) {
3820
                close(session->media.pipefd[0]);
3821
                session->media.pipefd[0] = -1;
3822
        }
3823
        if(session->media.pipefd[1] > 0) {
3824
                close(session->media.pipefd[1]);
3825
                session->media.pipefd[1] = -1;
3826
        }
3827
        /* Clean up SRTP stuff, if needed */
3828
        janus_sip_srtp_cleanup(session);
3829
        /* Done */
3830
        JANUS_LOG(LOG_VERB, "Leaving SIP relay thread\n");
3831
        g_thread_unref(g_thread_self());
3832
        return NULL;
3833
}
3834

    
3835

    
3836
/* Sofia Event thread */
3837
gpointer janus_sip_sofia_thread(gpointer user_data) {
3838
        janus_sip_session *session = (janus_sip_session *)user_data;
3839
        if(session == NULL || session->account.username == NULL) {
3840
                g_thread_unref(g_thread_self());
3841
                return NULL;
3842
        }
3843
        JANUS_LOG(LOG_VERB, "Joining sofia loop thread (%s)...\n", session->account.username);
3844
        session->stack = g_malloc0(sizeof(ssip_t));
3845
        session->stack->session = session;
3846
        session->stack->s_nua = NULL;
3847
        session->stack->s_nh_r = NULL;
3848
        session->stack->s_nh_i = NULL;
3849
        session->stack->s_root = su_root_create(session->stack);
3850
        su_home_init(session->stack->s_home);
3851
        JANUS_LOG(LOG_VERB, "Setting up sofia stack (sip:%s@%s)\n", session->account.username, local_ip);
3852
        char sip_url[128];
3853
        char sips_url[128];
3854
        char *ipv6;
3855
        ipv6 = strstr(local_ip, ":");
3856
        g_snprintf(sip_url, sizeof(sip_url), "sip:%s%s%s:*", ipv6 ? "[" : "", local_ip, ipv6 ? "]" : "");
3857
        g_snprintf(sips_url, sizeof(sips_url), "sips:%s%s%s:*", ipv6 ? "[" : "", local_ip, ipv6 ? "]" : "");
3858
        char outbound_options[256] = "use-rport no-validate";
3859
        if(keepalive_interval > 0)
3860
                g_strlcat(outbound_options, " options-keepalive", sizeof(outbound_options));
3861
        if(!behind_nat)
3862
                g_strlcat(outbound_options, " no-natify", sizeof(outbound_options));
3863
        session->stack->s_nua = nua_create(session->stack->s_root,
3864
                                janus_sip_sofia_callback,
3865
                                session,
3866
                                SIPTAG_ALLOW_STR("INVITE, ACK, BYE, CANCEL, OPTIONS, UPDATE, MESSAGE, INFO"),
3867
                                NUTAG_M_USERNAME(session->account.username),
3868
                                NUTAG_URL(sip_url),
3869
                                TAG_IF(session->account.sips, NUTAG_SIPS_URL(sips_url)),
3870
                                SIPTAG_USER_AGENT_STR(session->account.user_agent ? session->account.user_agent : user_agent),
3871
                                NUTAG_KEEPALIVE(keepalive_interval * 1000),        /* Sofia expects it in milliseconds */
3872
                                NUTAG_OUTBOUND(outbound_options),
3873
                                SIPTAG_SUPPORTED(NULL),
3874
                                TAG_NULL());
3875
        su_root_run(session->stack->s_root);
3876
        /* When we get here, we're done */
3877
        nua_destroy(session->stack->s_nua);
3878
        su_root_destroy(session->stack->s_root);
3879
        session->stack->s_root = NULL;
3880
        su_home_deinit(session->stack->s_home);
3881
        su_home_unref(session->stack->s_home);
3882
        if (session->stack) {
3883
                g_free(session->stack);
3884
                session->stack = NULL;
3885
        }
3886
        //~ stop = 1;
3887
        JANUS_LOG(LOG_VERB, "Leaving sofia loop thread...\n");
3888
        g_thread_unref(g_thread_self());
3889
        /* Cleaning up and removing the session is done in a lazy way */
3890
        janus_mutex_lock(&sessions_mutex);
3891
        old_sessions = g_list_append(old_sessions, session);
3892
        janus_mutex_unlock(&sessions_mutex);
3893
        return NULL;
3894
}