Statistics
| Branch: | Revision:

janus-gateway / plugins / janus_sipre.c @ 38109c95

History | View | Annotate | Download (165 KB)

1
/*! \file   janus_sipre.c
2
 * \author Lorenzo Miniero <lorenzo@meetecho.com>
3
 * \copyright GNU General Public License v3
4
 * \brief  Janus SIPre plugin (libre)
5
 * \details  This is basically a clone of the SIPre plugin, with the key
6
 * difference being that it uses \c libre (http://creytiv.com/re.html)
7
 * instead of Sofia SIP for its internal stack. As such, it provides an
8
 * alternative for those who don't want to, or can't, use the Sofia-based
9
 * SIP plugin. The API it exposes is exactly the same, meaning it should
10
 * be pretty straightforward to switch from one plugin to another on the
11
 * client side. The configuration file looks exactly the same as well.
12
 *
13
 * \section sipapi SIPre Plugin API
14
 *
15
 * All requests you can send in the SIPre Plugin API are asynchronous,
16
 * which means all responses (successes and errors) will be delivered
17
 * as events with the same transaction.
18
 *
19
 * The supported requests are \c register , \c unregister , \c call ,
20
 * \c accept, \c info , \c message , \c dtmf_info , \c recording ,
21
 * \c hold , \c unhold and \c hangup . \c register can be used,
22
 * as the name suggests, to register a username at a SIP registrar to
23
 * call and be called, while \c unregister unregisters it; \c call is used
24
 * to send an INVITE to a different SIP URI through the plugin, while
25
 * \c accept is used to accept the call in case one is invited instead
26
 * of inviting; \c hold and \c unhold can be used respectively to put a
27
 * call on-hold and to resume it; \c info allows you to send a generic
28
 * SIP INFO request, while \c dtmf_info is focused on using INFO for DTMF
29
 * instead; \c message is the method you use to send a SIP message
30
 * to the other peer; \c recording is used, instead, to record the
31
 * conversation to one or more .mjr files (depending on the direction you
32
 * want to record); finally, \c hangup can be used to terminate the
33
 * communication at any time, either to hangup (BYE) an ongoing call or
34
 * to cancel/decline (CANCEL/BYE) a call that hasn't started yet.
35
 *
36
 * Actual API docs: TBD.
37
 *
38
 * \ingroup plugins
39
 * \ref plugins
40
 */
41

    
42
#include "plugin.h"
43

    
44
#include <arpa/inet.h>
45
#include <net/if.h>
46
#include <sys/socket.h>
47
#include <netdb.h>
48
#include <poll.h>
49

    
50
#include <jansson.h>
51

    
52
#include <re_types.h>
53
#include <re_fmt.h>
54
#include <re_mbuf.h>
55
#include <re_msg.h>
56
#include <re_list.h>
57
#include <re_sa.h>
58
#include <re_main.h>
59
#include <re_mem.h>
60
#include <re_mqueue.h>
61
#include <re_sdp.h>
62
#include <re_uri.h>
63
#include <re_sip.h>
64
#include <re_sipreg.h>
65
#include <re_sipsess.h>
66
#include <re_srtp.h>
67
#include <re_tmr.h>
68
#include <re_tls.h>
69
#include <re_dns.h>
70

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

    
82

    
83
/* Plugin information */
84
#define JANUS_SIPRE_VERSION                        1
85
#define JANUS_SIPRE_VERSION_STRING        "0.0.1"
86
#define JANUS_SIPRE_DESCRIPTION                "This is a simple SIP plugin for Janus (based on libre instead of Sofia), allowing WebRTC peers to register at a SIP server and call SIP user agents through the gateway."
87
#define JANUS_SIPRE_NAME                        "JANUS SIPre plugin"
88
#define JANUS_SIPRE_AUTHOR                        "Meetecho s.r.l."
89
#define JANUS_SIPRE_PACKAGE                        "janus.plugin.sipre"
90

    
91
/* Plugin methods */
92
janus_plugin *create(void);
93
int janus_sipre_init(janus_callbacks *callback, const char *config_path);
94
void janus_sipre_destroy(void);
95
int janus_sipre_get_api_compatibility(void);
96
int janus_sipre_get_version(void);
97
const char *janus_sipre_get_version_string(void);
98
const char *janus_sipre_get_description(void);
99
const char *janus_sipre_get_name(void);
100
const char *janus_sipre_get_author(void);
101
const char *janus_sipre_get_package(void);
102
void janus_sipre_create_session(janus_plugin_session *handle, int *error);
103
struct janus_plugin_result *janus_sipre_handle_message(janus_plugin_session *handle, char *transaction, json_t *message, json_t *jsep);
104
void janus_sipre_setup_media(janus_plugin_session *handle);
105
void janus_sipre_incoming_rtp(janus_plugin_session *handle, int video, char *buf, int len);
106
void janus_sipre_incoming_rtcp(janus_plugin_session *handle, int video, char *buf, int len);
107
void janus_sipre_hangup_media(janus_plugin_session *handle);
108
void janus_sipre_destroy_session(janus_plugin_session *handle, int *error);
109
json_t *janus_sipre_query_session(janus_plugin_session *handle);
110

    
111
/* Plugin setup */
112
static janus_plugin janus_sipre_plugin =
113
        JANUS_PLUGIN_INIT (
114
                .init = janus_sipre_init,
115
                .destroy = janus_sipre_destroy,
116

    
117
                .get_api_compatibility = janus_sipre_get_api_compatibility,
118
                .get_version = janus_sipre_get_version,
119
                .get_version_string = janus_sipre_get_version_string,
120
                .get_description = janus_sipre_get_description,
121
                .get_name = janus_sipre_get_name,
122
                .get_author = janus_sipre_get_author,
123
                .get_package = janus_sipre_get_package,
124

    
125
                .create_session = janus_sipre_create_session,
126
                .handle_message = janus_sipre_handle_message,
127
                .setup_media = janus_sipre_setup_media,
128
                .incoming_rtp = janus_sipre_incoming_rtp,
129
                .incoming_rtcp = janus_sipre_incoming_rtcp,
130
                .hangup_media = janus_sipre_hangup_media,
131
                .destroy_session = janus_sipre_destroy_session,
132
                .query_session = janus_sipre_query_session,
133
        );
134

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

    
141
/* Parameter validation */
142
static struct janus_json_parameter request_parameters[] = {
143
        {"request", JANUS_JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
144
};
145
static struct janus_json_parameter register_parameters[] = {
146
        {"type", JANUS_JSON_STRING, 0},
147
        {"send_register", JANUS_JSON_BOOL, 0},
148
        {"sips", JANUS_JSON_BOOL, 0},
149
        {"username", JANUS_JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
150
        {"secret", JANUS_JSON_STRING, 0},
151
        {"authuser", JANUS_JSON_STRING, 0},
152
        {"headers", JANUS_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", JANUS_JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
161
        {"autoack", JANUS_JSON_BOOL, 0},
162
        {"headers", JANUS_JSON_OBJECT, 0},
163
        {"srtp", JANUS_JSON_STRING, 0}
164
};
165
static struct janus_json_parameter accept_parameters[] = {
166
        {"srtp", JANUS_JSON_STRING, 0}
167
};
168
static struct janus_json_parameter recording_parameters[] = {
169
        {"action", JANUS_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", JANUS_JSON_STRING, 0}
175
};
176
static struct janus_json_parameter dtmf_info_parameters[] = {
177
        {"digit", JANUS_JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
178
        {"duration", JANUS_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 gboolean behind_nat = FALSE;
195
static char *user_agent;
196
#define JANUS_DEFAULT_REGISTER_TTL        3600
197
static uint32_t register_ttl = JANUS_DEFAULT_REGISTER_TTL;
198

    
199
static GThread *handler_thread;
200
static GThread *watchdog;
201
static void *janus_sipre_handler(void *data);
202

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

    
212
static void janus_sipre_message_free(janus_sipre_message *msg) {
213
        if(!msg || msg == &exit_message)
214
                return;
215

    
216
        msg->handle = NULL;
217

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

    
227
        g_free(msg);
228
}
229

    
230
/* libre SIP stack */
231
static volatile int libre_inited = 0;
232
GThread *sipstack_thread = NULL;
233

    
234
/* Message queue */
235
static struct mqueue *mq = NULL;
236
void janus_sipre_mqueue_handler(int id, void *data, void *arg);
237
typedef enum janus_sipre_mqueue_event {
238
        janus_sipre_mqueue_event_do_init,
239
        janus_sipre_mqueue_event_do_register,
240
        janus_sipre_mqueue_event_do_unregister,
241
        janus_sipre_mqueue_event_do_call,
242
        janus_sipre_mqueue_event_do_accept,
243
        janus_sipre_mqueue_event_do_rcode,
244
        janus_sipre_mqueue_event_do_update,
245
        janus_sipre_mqueue_event_do_info,
246
        janus_sipre_mqueue_event_do_message,
247
        janus_sipre_mqueue_event_do_bye,
248
        janus_sipre_mqueue_event_do_destroy,
249
        /* TODO Add other events here */
250
        janus_sipre_mqueue_event_do_exit
251
} janus_sipre_mqueue_event;
252
static const char *janus_sipre_mqueue_event_string(janus_sipre_mqueue_event event) {
253
        switch(event) {
254
                case janus_sipre_mqueue_event_do_init:
255
                        return "init";
256
                case janus_sipre_mqueue_event_do_register:
257
                        return "register";
258
                case janus_sipre_mqueue_event_do_unregister:
259
                        return "unregister";
260
                case janus_sipre_mqueue_event_do_call:
261
                        return "call";
262
                case janus_sipre_mqueue_event_do_accept:
263
                        return "accept";
264
                case janus_sipre_mqueue_event_do_rcode:
265
                        return "rcode";
266
                case janus_sipre_mqueue_event_do_update:
267
                        return "update";
268
                case janus_sipre_mqueue_event_do_info:
269
                        return "info";
270
                case janus_sipre_mqueue_event_do_message:
271
                        return "message";
272
                case janus_sipre_mqueue_event_do_bye:
273
                        return "bye";
274
                case janus_sipre_mqueue_event_do_destroy:
275
                        return "destroy";
276
                case janus_sipre_mqueue_event_do_exit:
277
                        return "exit";
278
                default:
279
                        return "unknown";
280
        }
281
}
282
typedef struct janus_sipre_mqueue_payload {
283
        void *session;                                /* The session this event refers to */
284
        const struct sip_msg *msg;        /* The SIP message this refers to, if any */
285
        int rcode;                                        /* The error code to send back, if any */
286
        void *data;                                        /* Payload specific data */
287
} janus_sipre_mqueue_payload;
288
static janus_sipre_mqueue_payload *janus_sipre_mqueue_payload_create(void *session, const struct sip_msg *msg, int rcode, void *data) {
289
        janus_sipre_mqueue_payload *payload = g_malloc0(sizeof(janus_sipre_mqueue_payload));
290
        payload->session = session;
291
        payload->msg = msg;
292
        payload->rcode = rcode;
293
        payload->data = data;
294
        return payload;
295
}
296

    
297
/* Helper to quickly get the reason associated to response codes */
298
static const char *janus_sipre_error_reason(int rcode) {
299
        switch(rcode) {
300
                case 100: return "Trying";
301
                case 180: return "Ringing";
302
                case 181: return "Call is Being Forwarded";
303
                case 182: return "Queued";
304
                case 183: return "Session in Progress";
305
                case 199: return "Early Dialog Terminated";
306
                case 200: return "OK";
307
                case 202: return "Accepted";
308
                case 204: return "No Notification";
309
                case 300: return "Multiple Choices";
310
                case 301: return "Moved Permanently";
311
                case 302: return "Moved Temporarily";
312
                case 305: return "Use Proxy";
313
                case 380: return "Alternative Service";
314
                case 400: return "Bad Request";
315
                case 401: return "Unauthorized";
316
                case 402: return "Payment Required";
317
                case 403: return "Forbidden";
318
                case 404: return "Not Found";
319
                case 405: return "Method Not Allowed";
320
                case 406: return "Not Acceptable";
321
                case 407: return "Proxy Authentication Required";
322
                case 408: return "Request Timeout";
323
                case 409: return "Conflict";
324
                case 410: return "Gone";
325
                case 411: return "Length Required";
326
                case 412: return "Conditional Request Failed";
327
                case 413: return "Request Entity Too Large";
328
                case 414: return "Request-URI Too Long";
329
                case 415: return "Unsupported Media Type";
330
                case 416: return "Unsupported URI Scheme";
331
                case 417: return "Unknown Resource-Priority";
332
                case 420: return "Bad Extension";
333
                case 421: return "Extension Required";
334
                case 422: return "Session Interval Too Small";
335
                case 423: return "Interval Too Brief";
336
                case 424: return "Bad Location Information";
337
                case 428: return "Use Identity Header";
338
                case 429: return "Provide Referrer Identity";
339
                case 430: return "Flow Failed";
340
                case 433: return "Anonymity Disallowed";
341
                case 436: return "Bad Identity-Info";
342
                case 437: return "Unsupported Certificate";
343
                case 438: return "Invalid Identity Header";
344
                case 439: return "First Hop Lacks Outbound Support";
345
                case 470: return "Consent Needed";
346
                case 480: return "Temporarily Unavailable";
347
                case 481: return "Call/Transaction Does Not Exist";
348
                case 482: return "Loop Detected.";
349
                case 483: return "Too Many Hops";
350
                case 484: return "Address Incomplete";
351
                case 485: return "Ambiguous";
352
                case 486: return "Busy Here";
353
                case 487: return "Request Terminated";
354
                case 488: return "Not Acceptable Here";
355
                case 489: return "Bad Event";
356
                case 491: return "Request Pending";
357
                case 493: return "Undecipherable";
358
                case 494: return "Security Agreement Required";
359
                case 500: return "Server Internal Error";
360
                case 501: return "Not Implemented";
361
                case 502: return "Bad Gateway";
362
                case 503: return "Service Unavailable";
363
                case 504: return "Server Time-out";
364
                case 505: return "Version Not Supported";
365
                case 513: return "Message Too Large";
366
                case 580: return "Precondition Failure";
367
                case 600: return "Busy Everywhere";
368
                case 603: return "Decline";
369
                case 604: return "Does Not Exist Anywhere";
370
                case 606: return "Not Acceptable";
371
                default: return "Unknown Error";
372
        }
373
}
374

    
375
/* Registration info */
376
typedef enum {
377
        janus_sipre_registration_status_disabled = -2,
378
        janus_sipre_registration_status_failed = -1,
379
        janus_sipre_registration_status_unregistered = 0,
380
        janus_sipre_registration_status_registering,
381
        janus_sipre_registration_status_registered,
382
        janus_sipre_registration_status_unregistering,
383
} janus_sipre_registration_status;
384

    
385
static const char *janus_sipre_registration_status_string(janus_sipre_registration_status status) {
386
        switch(status) {
387
                case janus_sipre_registration_status_disabled:
388
                        return "disabled";
389
                case janus_sipre_registration_status_failed:
390
                        return "failed";
391
                case janus_sipre_registration_status_unregistered:
392
                        return "unregistered";
393
                case janus_sipre_registration_status_registering:
394
                        return "registering";
395
                case janus_sipre_registration_status_registered:
396
                        return "registered";
397
                case janus_sipre_registration_status_unregistering:
398
                        return "unregistering";
399
                default:
400
                        return "unknown";
401
        }
402
}
403

    
404

    
405
typedef enum {
406
        janus_sipre_call_status_idle = 0,
407
        janus_sipre_call_status_inviting,
408
        janus_sipre_call_status_invited,
409
        janus_sipre_call_status_incall,
410
        janus_sipre_call_status_closing,
411
} janus_sipre_call_status;
412

    
413
static const char *janus_sipre_call_status_string(janus_sipre_call_status status) {
414
        switch(status) {
415
                case janus_sipre_call_status_idle:
416
                        return "idle";
417
                case janus_sipre_call_status_inviting:
418
                        return "inviting";
419
                case janus_sipre_call_status_invited:
420
                        return "invited";
421
                case janus_sipre_call_status_incall:
422
                        return "incall";
423
                case janus_sipre_call_status_closing:
424
                        return "closing";
425
                default:
426
                        return "unknown";
427
        }
428
}
429

    
430

    
431
typedef enum {
432
        janus_sipre_secret_type_plaintext = 1,
433
        janus_sipre_secret_type_hashed = 2,
434
        janus_sipre_secret_type_unknown
435
} janus_sipre_secret_type;
436

    
437
typedef struct janus_sipre_account {
438
        char *identity;
439
        gboolean sips;
440
        char *username;
441
        char *display_name;                /* Used for outgoing calls in the From header */
442
        char *authuser;                        /**< username to use for authentication */
443
        char *secret;
444
        janus_sipre_secret_type secret_type;
445
        int sip_port;
446
        char *proxy;
447
        char *outbound_proxy;
448
        janus_sipre_registration_status registration_status;
449
} janus_sipre_account;
450

    
451
typedef struct janus_sipre_stack {
452
        struct sip *sipstack;                                /* SIP stack */
453
        struct tls *tls;                                        /* TLS transport, if needed */
454
        struct sipsess *sess;                                /* SIP session */
455
        struct sipsess_sock *sess_sock;                /* SIP session socket */
456
        struct sipreg *reg;                                        /* SIP registration */
457
        struct dnsc *dns_client;                        /* DNS client */
458
        uint32_t expires;                                        /* Registration interval (seconds) */
459
        const struct sip_msg *invite;                /* Current INVITE */
460
        void *session;                                                /* Opaque pointer to the plugin session */
461
} janus_sipre_stack;
462

    
463
typedef struct janus_sipre_media {
464
        char *remote_ip;
465
        gboolean earlymedia;
466
        gboolean ready;
467
        gboolean autoack;
468
        gboolean require_srtp, has_srtp_local, has_srtp_remote;
469
        gboolean on_hold;
470
        gboolean has_audio;
471
        int audio_rtp_fd, audio_rtcp_fd;
472
        int local_audio_rtp_port, remote_audio_rtp_port;
473
        int local_audio_rtcp_port, remote_audio_rtcp_port;
474
        guint32 audio_ssrc, audio_ssrc_peer;
475
        int audio_pt;
476
        const char *audio_pt_name;
477
        srtp_t audio_srtp_in, audio_srtp_out;
478
        srtp_policy_t audio_remote_policy, audio_local_policy;
479
        int audio_srtp_suite_in, audio_srtp_suite_out;
480
        gboolean audio_send;
481
        janus_sdp_mdirection pre_hold_audio_dir;
482
        gboolean has_video;
483
        int video_rtp_fd, video_rtcp_fd;
484
        int local_video_rtp_port, remote_video_rtp_port;
485
        int local_video_rtcp_port, remote_video_rtcp_port;
486
        guint32 video_ssrc, video_ssrc_peer;
487
        int video_pt;
488
        const char *video_pt_name;
489
        srtp_t video_srtp_in, video_srtp_out;
490
        srtp_policy_t video_remote_policy, video_local_policy;
491
        int video_srtp_suite_in, video_srtp_suite_out;
492
        gboolean video_send;
493
        janus_sdp_mdirection pre_hold_video_dir;
494
        janus_rtp_switching_context context;
495
        int pipefd[2];
496
        gboolean updated;
497
} janus_sipre_media;
498

    
499
typedef struct janus_sipre_session {
500
        janus_plugin_session *handle;
501
        janus_sipre_stack stack;
502
        janus_sipre_account account;
503
        janus_sipre_call_status status;
504
        janus_sipre_media media;
505
        char *transaction;
506
        char *callee;
507
        char *callid;
508
        char *temp_sdp;
509
        janus_sdp *sdp;                                /* The SDP this user sent */
510
        janus_recorder *arc;                /* The Janus recorder instance for this user's audio, if enabled */
511
        janus_recorder *arc_peer;        /* The Janus recorder instance for the peer's audio, if enabled */
512
        janus_recorder *vrc;                /* The Janus recorder instance for this user's video, if enabled */
513
        janus_recorder *vrc_peer;        /* The Janus recorder instance for the peer's video, if enabled */
514
        janus_mutex rec_mutex;                /* Mutex to protect the recorders from race conditions */
515
        volatile gint hangingup;
516
        gint64 destroyed;        /* Time at which this session was marked as destroyed */
517
        janus_mutex mutex;
518
} janus_sipre_session;
519
static GHashTable *sessions;
520
static GList *old_sessions;
521
static GHashTable *identities;
522
static GHashTable *callids;
523
static janus_mutex sessions_mutex;
524

    
525

    
526
/* SRTP stuff (in case we need SDES) */
527
static int janus_sipre_srtp_set_local(janus_sipre_session *session, gboolean video, char **crypto) {
528
        if(session == NULL)
529
                return -1;
530
        /* Generate key/salt */
531
        uint8_t *key = g_malloc0(SRTP_MASTER_LENGTH);
532
        srtp_crypto_get_random(key, SRTP_MASTER_LENGTH);
533
        /* Set SRTP policies */
534
        srtp_policy_t *policy = video ? &session->media.video_local_policy : &session->media.audio_local_policy;
535
        srtp_crypto_policy_set_rtp_default(&(policy->rtp));
536
        srtp_crypto_policy_set_rtcp_default(&(policy->rtcp));
537
        policy->ssrc.type = ssrc_any_inbound;
538
        policy->key = key;
539
        policy->next = NULL;
540
        /* Create SRTP context */
541
        srtp_err_status_t res = srtp_create(video ? &session->media.video_srtp_out : &session->media.audio_srtp_out, policy);
542
        if(res != srtp_err_status_ok) {
543
                /* Something went wrong... */
544
                JANUS_LOG(LOG_ERR, "Oops, error creating outbound SRTP session: %d (%s)\n", res, janus_srtp_error_str(res));
545
                g_free(key);
546
                policy->key = NULL;
547
                return -2;
548
        }
549
        /* Base64 encode the salt */
550
        *crypto = g_base64_encode(key, SRTP_MASTER_LENGTH);
551
        if((video && session->media.video_srtp_out) || (!video && session->media.audio_srtp_out)) {
552
                JANUS_LOG(LOG_VERB, "%s outbound SRTP session created\n", video ? "Video" : "Audio");
553
        }
554
        return 0;
555
}
556
static int janus_sipre_srtp_set_remote(janus_sipre_session *session, gboolean video, const char *crypto, int suite) {
557
        if(session == NULL || crypto == NULL)
558
                return -1;
559
        /* Base64 decode the crypto string and set it as the remote SRTP context */
560
        gsize len = 0;
561
        guchar *decoded = g_base64_decode(crypto, &len);
562
        if(len < SRTP_MASTER_LENGTH) {
563
                /* FIXME Can this happen? */
564
                g_free(decoded);
565
                return -2;
566
        }
567
        /* Set SRTP policies */
568
        srtp_policy_t *policy = video ? &session->media.video_remote_policy : &session->media.audio_remote_policy;
569
        srtp_crypto_policy_set_rtp_default(&(policy->rtp));
570
        srtp_crypto_policy_set_rtcp_default(&(policy->rtcp));
571
        if(suite == 32) {
572
                srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&(policy->rtp));
573
                srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&(policy->rtcp));
574
        } else if(suite == 80) {
575
                srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&(policy->rtp));
576
                srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&(policy->rtcp));
577
        }
578
        policy->ssrc.type = ssrc_any_inbound;
579
        policy->key = decoded;
580
        policy->next = NULL;
581
        /* Create SRTP context */
582
        srtp_err_status_t res = srtp_create(video ? &session->media.video_srtp_in : &session->media.audio_srtp_in, policy);
583
        if(res != srtp_err_status_ok) {
584
                /* Something went wrong... */
585
                JANUS_LOG(LOG_ERR, "Oops, error creating inbound SRTP session: %d (%s)\n", res, janus_srtp_error_str(res));
586
                g_free(decoded);
587
                policy->key = NULL;
588
                return -2;
589
        }
590
        if((video && session->media.video_srtp_in) || (!video && session->media.audio_srtp_in)) {
591
                JANUS_LOG(LOG_VERB, "%s inbound SRTP session created\n", video ? "Video" : "Audio");
592
        }
593
        return 0;
594
}
595
static void janus_sipre_srtp_cleanup(janus_sipre_session *session) {
596
        if(session == NULL)
597
                return;
598
        session->media.autoack = TRUE;
599
        session->media.require_srtp = FALSE;
600
        session->media.has_srtp_local = FALSE;
601
        session->media.has_srtp_remote = FALSE;
602
        /* Audio */
603
        if(session->media.audio_srtp_out)
604
                srtp_dealloc(session->media.audio_srtp_out);
605
        session->media.audio_srtp_out = NULL;
606
        g_free(session->media.audio_local_policy.key);
607
        session->media.audio_local_policy.key = NULL;
608
        session->media.audio_srtp_suite_out = 0;
609
        if(session->media.audio_srtp_in)
610
                srtp_dealloc(session->media.audio_srtp_in);
611
        session->media.audio_srtp_in = NULL;
612
        g_free(session->media.audio_remote_policy.key);
613
        session->media.audio_remote_policy.key = NULL;
614
        session->media.audio_srtp_suite_in = 0;
615
        /* Video */
616
        if(session->media.video_srtp_out)
617
                srtp_dealloc(session->media.video_srtp_out);
618
        session->media.video_srtp_out = NULL;
619
        g_free(session->media.video_local_policy.key);
620
        session->media.video_local_policy.key = NULL;
621
        session->media.video_srtp_suite_out = 0;
622
        if(session->media.video_srtp_in)
623
                srtp_dealloc(session->media.video_srtp_in);
624
        session->media.video_srtp_in = NULL;
625
        g_free(session->media.video_remote_policy.key);
626
        session->media.video_remote_policy.key = NULL;
627
        session->media.video_srtp_suite_in = 0;
628
}
629

    
630

    
631
/* libre event thread */
632
gpointer janus_sipre_stack_thread(gpointer user_data);
633
/* libre callbacks */
634
int janus_sipre_cb_auth(char **user, char **pass, const char *realm, void *arg);
635
void janus_sipre_cb_register(int err, const struct sip_msg *msg, void *arg);
636
void janus_sipre_cb_progress(const struct sip_msg *msg, void *arg);
637
void janus_sipre_cb_incoming(const struct sip_msg *msg, void *arg);
638
int janus_sipre_cb_offer(struct mbuf **mbp, const struct sip_msg *msg, void *arg);
639
int janus_sipre_cb_answer(const struct sip_msg *msg, void *arg);
640
void janus_sipre_cb_established(const struct sip_msg *msg, void *arg);
641
void janus_sipre_cb_info(struct sip *sip, const struct sip_msg *msg, void *arg);
642
void janus_sipre_cb_closed(int err, const struct sip_msg *msg, void *arg);
643
void janus_sipre_cb_exit(void *arg);
644

    
645
/* URI parsing utilities */
646
static int janus_sipre_parse_uri(const char *uri) {
647
        if(uri == NULL)
648
                return -1;
649
        struct sip_addr addr;
650
        struct pl pluri;
651
        pl_set_str(&pluri, uri);
652
        if(sip_addr_decode(&addr, &pluri) != 0)
653
                return -1;
654
        return 0;
655
}
656
static char *janus_sipre_get_uri_username(const char *uri) {
657
        if(uri == NULL)
658
                return NULL;
659
        struct sip_addr addr;
660
        struct pl pluri;
661
        pl_set_str(&pluri, uri);
662
        if(sip_addr_decode(&addr, &pluri) != 0)
663
                return NULL;
664
        char *at = strchr(addr.uri.user.p, '@');
665
        if(at != NULL)
666
                *(at) = '\0';
667
        char *username = g_strdup(addr.uri.user.p);
668
        if(at != NULL)
669
                *(at) = '@';
670
        return username;
671
}
672
static char *janus_sipre_get_uri_host(const char *uri) {
673
        if(uri == NULL)
674
                return NULL;
675
        struct sip_addr addr;
676
        struct pl pluri;
677
        pl_set_str(&pluri, uri);
678
        if(sip_addr_decode(&addr, &pluri) != 0)
679
                return NULL;
680
        return g_strdup(addr.uri.host.p);
681
}
682
static uint16_t janus_sipre_get_uri_port(const char *uri) {
683
        if(uri == NULL)
684
                return 0;
685
        struct sip_addr addr;
686
        struct pl pluri;
687
        pl_set_str(&pluri, uri);
688
        if(sip_addr_decode(&addr, &pluri) != 0)
689
                return 0;
690
        return addr.uri.port;
691
}
692

    
693

    
694
/* SDP parsing and manipulation */
695
void janus_sipre_sdp_process(janus_sipre_session *session, janus_sdp *sdp, gboolean answer, gboolean update, gboolean *changed);
696
char *janus_sipre_sdp_manipulate(janus_sipre_session *session, janus_sdp *sdp, gboolean answer);
697
/* Media */
698
static int janus_sipre_allocate_local_ports(janus_sipre_session *session);
699
static void *janus_sipre_relay_thread(void *data);
700

    
701

    
702
/* Error codes */
703
#define JANUS_SIPRE_ERROR_UNKNOWN_ERROR                499
704
#define JANUS_SIPRE_ERROR_NO_MESSAGE                        440
705
#define JANUS_SIPRE_ERROR_INVALID_JSON                441
706
#define JANUS_SIPRE_ERROR_INVALID_REQUEST                442
707
#define JANUS_SIPRE_ERROR_MISSING_ELEMENT                443
708
#define JANUS_SIPRE_ERROR_INVALID_ELEMENT                444
709
#define JANUS_SIPRE_ERROR_ALREADY_REGISTERED        445
710
#define JANUS_SIPRE_ERROR_INVALID_ADDRESS                446
711
#define JANUS_SIPRE_ERROR_WRONG_STATE                        447
712
#define JANUS_SIPRE_ERROR_MISSING_SDP                        448
713
#define JANUS_SIPRE_ERROR_LIBRE_ERROR                449
714
#define JANUS_SIPRE_ERROR_IO_ERROR                        450
715
#define JANUS_SIPRE_ERROR_RECORDING_ERROR                451
716
#define JANUS_SIPRE_ERROR_TOO_STRICT                        452
717

    
718

    
719
/* SIPre watchdog/garbage collector (sort of) */
720
static void *janus_sipre_watchdog(void *data) {
721
        JANUS_LOG(LOG_INFO, "SIPre watchdog started\n");
722
        gint64 now = 0;
723
        while(g_atomic_int_get(&initialized) && !g_atomic_int_get(&stopping)) {
724
                janus_mutex_lock(&sessions_mutex);
725
                /* Iterate on all the sessions */
726
                now = janus_get_monotonic_time();
727
                if(old_sessions != NULL) {
728
                        GList *sl = old_sessions;
729
                        JANUS_LOG(LOG_HUGE, "Checking %d old SIPre sessions...\n", g_list_length(old_sessions));
730
                        while(sl) {
731
                                janus_sipre_session *session = (janus_sipre_session *)sl->data;
732
                                if(!session) {
733
                                        sl = sl->next;
734
                                        continue;
735
                                }
736
                                if(now-session->destroyed >= 5*G_USEC_PER_SEC) {
737
                                        /* We're lazy and actually get rid of the stuff only after a few seconds */
738
                                        JANUS_LOG(LOG_VERB, "Freeing old SIPre session\n");
739
                                        GList *rm = sl->next;
740
                                        old_sessions = g_list_delete_link(old_sessions, sl);
741
                                        sl = rm;
742
                                        sipsess_close_all(session->stack.sess_sock);
743
                                        sip_close(session->stack.sipstack, FALSE);
744
                                        session->stack.sipstack = NULL;
745
                                        if(session->account.identity) {
746
                                            g_hash_table_remove(identities, session->account.identity);
747
                                            g_free(session->account.identity);
748
                                            session->account.identity = NULL;
749
                                        }
750
                                        session->account.sips = TRUE;
751
                                        if(session->account.proxy) {
752
                                            g_free(session->account.proxy);
753
                                            session->account.proxy = NULL;
754
                                        }
755
                                        if(session->account.outbound_proxy) {
756
                                            g_free(session->account.outbound_proxy);
757
                                            session->account.outbound_proxy = NULL;
758
                                        }
759
                                        if(session->account.secret) {
760
                                            g_free(session->account.secret);
761
                                            session->account.secret = NULL;
762
                                        }
763
                                        if(session->account.username) {
764
                                            g_free(session->account.username);
765
                                            session->account.username = NULL;
766
                                        }
767
                                        if(session->account.display_name) {
768
                                            g_free(session->account.display_name);
769
                                            session->account.display_name = NULL;
770
                                        }
771
                                        if(session->account.authuser) {
772
                                            g_free(session->account.authuser);
773
                                            session->account.authuser = NULL;
774
                                        }
775
                                        if(session->callee) {
776
                                            g_free(session->callee);
777
                                            session->callee = NULL;
778
                                        }
779
                                        if(session->callid) {
780
                                            g_hash_table_remove(callids, session->callid);
781
                                            g_free(session->callid);
782
                                            session->callid = NULL;
783
                                        }
784
                                        if(session->sdp) {
785
                                            janus_sdp_free(session->sdp);
786
                                            session->sdp = NULL;
787
                                        }
788
                                        if(session->transaction) {
789
                                            g_free(session->transaction);
790
                                            session->transaction = NULL;
791
                                        }
792
                                        if(session->media.remote_ip) {
793
                                            g_free(session->media.remote_ip);
794
                                            session->media.remote_ip = NULL;
795
                                        }
796
                                        janus_sipre_srtp_cleanup(session);
797
                                        session->handle = NULL;
798
                                        g_free(session);
799
                                        session = NULL;
800
                                        continue;
801
                                }
802
                                sl = sl->next;
803
                        }
804
                }
805
                janus_mutex_unlock(&sessions_mutex);
806
                g_usleep(500000);
807
        }
808
        JANUS_LOG(LOG_INFO, "SIPre watchdog stopped\n");
809
        return NULL;
810
}
811

    
812

    
813
/* Random string helper (for call-ids) */
814
static char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
815
static void janus_sipre_random_string(int length, char *buffer) {
816
        if(length > 0 && buffer) {
817
                int l = (int)(sizeof(charset)-1);
818
                int i=0;
819
                for(i=0; i<length; i++) {
820
                        int key = rand() % l;
821
                        buffer[i] = charset[key];
822
                }
823
                buffer[length-1] = '\0';
824
        }
825
}
826

    
827

    
828
#ifdef HAVE_LIBRE_SIPTRACE
829
/* libre SIP logger function: when the Event Handlers mechanism is enabled,
830
 * we use this to intercept SIP messages sent and received by the stack */
831
static void janus_sipre_msg_logger(bool tx, enum sip_transp tp, const struct sa *src, const struct sa *dst,
832
                const uint8_t *pkt, size_t len, void *arg) {
833
        /* Access the session this message refers to */
834
        janus_sipre_session *session = (janus_sipre_session *)arg;
835
        /* Print the SIP message */
836
        char sip_msg[2048];
837
        g_snprintf(sip_msg, sizeof(sip_msg), "%.*s", (int)len, (char *)pkt);
838
        /* Shoot the event */
839
        json_t *info = json_object();
840
        json_object_set_new(info, "event", json_string(tx ? "sip-out" : "sip-in"));
841
        json_object_set_new(info, "sip", json_string(sip_msg));
842
        gateway->notify_event(&janus_sipre_plugin, session->handle, info);
843
}
844
#endif
845

    
846

    
847
/* Plugin implementation */
848
int janus_sipre_init(janus_callbacks *callback, const char *config_path) {
849
        if(g_atomic_int_get(&stopping)) {
850
                /* Still stopping from before */
851
                return -1;
852
        }
853
        if(callback == NULL || config_path == NULL) {
854
                /* Invalid arguments */
855
                return -1;
856
        }
857

    
858
        /* Read configuration */
859
        char filename[255];
860
        g_snprintf(filename, 255, "%s/%s.cfg", config_path, JANUS_SIPRE_PACKAGE);
861
        JANUS_LOG(LOG_VERB, "Configuration file: %s\n", filename);
862
        janus_config *config = janus_config_parse(filename);
863
        if(config != NULL) {
864
                janus_config_print(config);
865

    
866
                janus_config_item *item = janus_config_get_item_drilldown(config, "general", "local_ip");
867
                if(item && item->value) {
868
                        /* Verify that the address is valid */
869
                        struct ifaddrs *ifas = NULL;
870
                        janus_network_address iface;
871
                        janus_network_address_string_buffer ibuf;
872
                        if(getifaddrs(&ifas) || ifas == NULL) {
873
                                JANUS_LOG(LOG_ERR, "Unable to acquire list of network devices/interfaces; some configurations may not work as expected...\n");
874
                        } else {
875
                                if(janus_network_lookup_interface(ifas, item->value, &iface) != 0) {
876
                                        JANUS_LOG(LOG_WARN, "Error setting local IP address to %s, falling back to detecting IP address...\n", item->value);
877
                                } else {
878
                                        if(janus_network_address_to_string_buffer(&iface, &ibuf) != 0 || janus_network_address_string_buffer_is_null(&ibuf)) {
879
                                                JANUS_LOG(LOG_WARN, "Error getting local IP address from %s, falling back to detecting IP address...\n", item->value);
880
                                        } else {
881
                                                local_ip = g_strdup(janus_network_address_string_from_buffer(&ibuf));
882
                                        }
883
                                }
884
                        }
885
                }
886

    
887
                item = janus_config_get_item_drilldown(config, "general", "register_ttl");
888
                if(item && item->value) {
889
                        register_ttl = atol(item->value);
890
                        if(register_ttl <= 0) {
891
                                JANUS_LOG(LOG_WARN, "Invalid value of register_ttl, using default instead\n");
892
                                register_ttl = JANUS_DEFAULT_REGISTER_TTL;
893
                        }
894
                }
895
                JANUS_LOG(LOG_VERB, "SIPre registration TTL set to %d seconds\n", register_ttl);
896

    
897
                item = janus_config_get_item_drilldown(config, "general", "behind_nat");
898
                if(item && item->value) {
899
                        behind_nat = janus_is_true(item->value);
900
                }
901

    
902
                item = janus_config_get_item_drilldown(config, "general", "user_agent");
903
                if(item && item->value) {
904
                        user_agent = g_strdup(item->value);
905
                } else {
906
                        user_agent = g_strdup("Janus WebRTC Gateway SIPre Plugin "JANUS_SIPRE_VERSION_STRING);
907
                }
908
                JANUS_LOG(LOG_VERB, "SIPre User-Agent set to %s\n", user_agent);
909

    
910
                item = janus_config_get_item_drilldown(config, "general", "events");
911
                if(item != NULL && item->value != NULL) {
912
                        notify_events = janus_is_true(item->value);
913
                }
914
                if(!notify_events && callback->events_is_enabled()) {
915
                        JANUS_LOG(LOG_WARN, "Notification of events to handlers disabled for %s\n", JANUS_SIPRE_NAME);
916
                }
917

    
918
                janus_config_destroy(config);
919
        }
920
        config = NULL;
921

    
922
        if(local_ip == NULL) {
923
                local_ip = janus_network_detect_local_ip_as_string(janus_network_query_options_any_ip);
924
                if(local_ip == NULL) {
925
                        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");
926
                        local_ip = g_strdup("127.0.0.1");
927
                }
928
        }
929
        JANUS_LOG(LOG_VERB, "Local IP set to %s\n", local_ip);
930

    
931
#ifdef HAVE_SRTP_2
932
        /* Init randomizer (for randum numbers in SRTP) */
933
        RAND_poll();
934
#endif
935

    
936
        sessions = g_hash_table_new(NULL, NULL);
937
        callids = g_hash_table_new(g_str_hash, g_str_equal);
938
        identities = g_hash_table_new(g_str_hash, g_str_equal);
939
        janus_mutex_init(&sessions_mutex);
940
        messages = g_async_queue_new_full((GDestroyNotify) janus_sipre_message_free);
941
        /* This is the callback we'll need to invoke to contact the gateway */
942
        gateway = callback;
943

    
944
        g_atomic_int_set(&initialized, 1);
945

    
946
        GError *error = NULL;
947
        /* Start the sessions watchdog */
948
        watchdog = g_thread_try_new("sipre watchdog", &janus_sipre_watchdog, NULL, &error);
949
        if(error != NULL) {
950
                g_atomic_int_set(&initialized, 0);
951
                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the SIPre watchdog thread...\n", error->code, error->message ? error->message : "??");
952
                return -1;
953
        }
954
        /* Launch the thread that will handle incoming API messages */
955
        handler_thread = g_thread_try_new("sipre handler", janus_sipre_handler, NULL, &error);
956
        if(error != NULL) {
957
                g_atomic_int_set(&initialized, 0);
958
                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the SIPre handler thread...\n", error->code, error->message ? error->message : "??");
959
                return -1;
960
        }
961
        /* Launch the thread that will handle the libre initialization and event loop */
962
        g_atomic_int_set(&libre_inited, 0);
963
        sipstack_thread = g_thread_try_new("sipre loop", janus_sipre_stack_thread, NULL, &error);
964
        if(error != NULL) {
965
                g_atomic_int_set(&initialized, 0);
966
                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the SIPre loop thread...\n", error->code, error->message ? error->message : "??");
967
                return -1;
968
        }
969
        /* Let's wait for the libre initialization to complete */
970
        while(g_atomic_int_get(&libre_inited) == 0)
971
                g_usleep(100000);
972
        if(g_atomic_int_get(&libre_inited) == -1) {
973
                g_atomic_int_set(&initialized, 0);
974
                JANUS_LOG(LOG_ERR, "Got error trying to initialize libre...\n");
975
                return -1;
976
        }
977

    
978
#ifndef HAVE_LIBRE_SIPTRACE
979
        JANUS_LOG(LOG_WARN, "sip_set_trace() was not found in libre... "
980
                "The tracing of SIP incoming/outgoing SIP messages when using the SIPre plugin will not be available to Event Handlers. "
981
                "In case you're interested in that, apply this patch on your libre installation and recompile the plugin: "
982
                "https://raw.githubusercontent.com/alfredh/patches/master/re-sip-trace.patch\n");
983
#endif
984

    
985
        JANUS_LOG(LOG_INFO, "%s initialized!\n", JANUS_SIPRE_NAME);
986
        return 0;
987
}
988

    
989
void janus_sipre_destroy(void) {
990
        if(!g_atomic_int_get(&initialized))
991
                return;
992
        g_atomic_int_set(&stopping, 1);
993

    
994
        g_async_queue_push(messages, &exit_message);
995
        if(handler_thread != NULL) {
996
                g_thread_join(handler_thread);
997
                handler_thread = NULL;
998
        }
999

    
1000
        /* Break the libre loop */
1001
        mqueue_push(mq, janus_sipre_mqueue_event_do_exit, NULL);
1002
        if(sipstack_thread != NULL) {
1003
                g_thread_join(sipstack_thread);
1004
                sipstack_thread = NULL;
1005
        }
1006
        if(watchdog != NULL) {
1007
                g_thread_join(watchdog);
1008
                watchdog = NULL;
1009
        }
1010
        /* FIXME We should destroy the sessions cleanly */
1011
        janus_mutex_lock(&sessions_mutex);
1012
        g_hash_table_destroy(sessions);
1013
        g_hash_table_destroy(callids);
1014
        g_hash_table_destroy(identities);
1015
        sessions = NULL;
1016
        callids = NULL;
1017
        identities = NULL;
1018
        janus_mutex_unlock(&sessions_mutex);
1019
        g_async_queue_unref(messages);
1020
        messages = NULL;
1021
        g_atomic_int_set(&initialized, 0);
1022
        g_atomic_int_set(&stopping, 0);
1023

    
1024
        g_free(local_ip);
1025

    
1026
        JANUS_LOG(LOG_INFO, "%s destroyed!\n", JANUS_SIPRE_NAME);
1027
}
1028

    
1029
int janus_sipre_get_api_compatibility(void) {
1030
        /* Important! This is what your plugin MUST always return: don't lie here or bad things will happen */
1031
        return JANUS_PLUGIN_API_VERSION;
1032
}
1033

    
1034
int janus_sipre_get_version(void) {
1035
        return JANUS_SIPRE_VERSION;
1036
}
1037

    
1038
const char *janus_sipre_get_version_string(void) {
1039
        return JANUS_SIPRE_VERSION_STRING;
1040
}
1041

    
1042
const char *janus_sipre_get_description(void) {
1043
        return JANUS_SIPRE_DESCRIPTION;
1044
}
1045

    
1046
const char *janus_sipre_get_name(void) {
1047
        return JANUS_SIPRE_NAME;
1048
}
1049

    
1050
const char *janus_sipre_get_author(void) {
1051
        return JANUS_SIPRE_AUTHOR;
1052
}
1053

    
1054
const char *janus_sipre_get_package(void) {
1055
        return JANUS_SIPRE_PACKAGE;
1056
}
1057

    
1058
void janus_sipre_create_session(janus_plugin_session *handle, int *error) {
1059
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
1060
                *error = -1;
1061
                return;
1062
        }
1063
        janus_sipre_session *session = g_malloc0(sizeof(janus_sipre_session));
1064
        session->handle = handle;
1065
        session->account.identity = NULL;
1066
        session->account.sips = TRUE;
1067
        session->account.username = NULL;
1068
        session->account.display_name = NULL;
1069
        session->account.authuser = NULL;
1070
        session->account.secret = NULL;
1071
        session->account.secret_type = janus_sipre_secret_type_unknown;
1072
        session->account.sip_port = 0;
1073
        session->account.proxy = NULL;
1074
        session->account.outbound_proxy = NULL;
1075
        session->account.registration_status = janus_sipre_registration_status_unregistered;
1076
        session->status = janus_sipre_call_status_idle;
1077
        memset(&session->stack, 0, sizeof(janus_sipre_stack));
1078
        session->transaction = NULL;
1079
        session->callee = NULL;
1080
        session->callid = NULL;
1081
        session->sdp = NULL;
1082
        session->media.remote_ip = NULL;
1083
        session->media.earlymedia = FALSE;
1084
        session->media.ready = FALSE;
1085
        session->media.autoack = TRUE;
1086
        session->media.require_srtp = FALSE;
1087
        session->media.has_srtp_local = FALSE;
1088
        session->media.has_srtp_remote = FALSE;
1089
        session->media.on_hold = FALSE;
1090
        session->media.has_audio = FALSE;
1091
        session->media.audio_rtp_fd = -1;
1092
        session->media.audio_rtcp_fd= -1;
1093
        session->media.local_audio_rtp_port = 0;
1094
        session->media.remote_audio_rtp_port = 0;
1095
        session->media.local_audio_rtcp_port = 0;
1096
        session->media.remote_audio_rtcp_port = 0;
1097
        session->media.audio_ssrc = 0;
1098
        session->media.audio_ssrc_peer = 0;
1099
        session->media.audio_pt = -1;
1100
        session->media.audio_pt_name = NULL;
1101
        session->media.audio_srtp_suite_in = 0;
1102
        session->media.audio_srtp_suite_out = 0;
1103
        session->media.audio_send = TRUE;
1104
        session->media.pre_hold_audio_dir = JANUS_SDP_DEFAULT;
1105
        session->media.has_video = FALSE;
1106
        session->media.video_rtp_fd = -1;
1107
        session->media.video_rtcp_fd= -1;
1108
        session->media.local_video_rtp_port = 0;
1109
        session->media.remote_video_rtp_port = 0;
1110
        session->media.local_video_rtcp_port = 0;
1111
        session->media.remote_video_rtcp_port = 0;
1112
        session->media.video_ssrc = 0;
1113
        session->media.video_ssrc_peer = 0;
1114
        session->media.video_pt = -1;
1115
        session->media.video_pt_name = NULL;
1116
        session->media.video_srtp_suite_in = 0;
1117
        session->media.video_srtp_suite_out = 0;
1118
        session->media.video_send = TRUE;
1119
        session->media.pre_hold_video_dir = JANUS_SDP_DEFAULT;
1120
        /* Initialize the RTP context */
1121
        janus_rtp_switching_context_reset(&session->media.context);
1122
        session->media.pipefd[0] = -1;
1123
        session->media.pipefd[1] = -1;
1124
        session->media.updated = FALSE;
1125
        janus_mutex_init(&session->rec_mutex);
1126
        session->destroyed = 0;
1127
        g_atomic_int_set(&session->hangingup, 0);
1128
        janus_mutex_init(&session->mutex);
1129
        handle->plugin_handle = session;
1130

    
1131
        mqueue_push(mq, janus_sipre_mqueue_event_do_init, janus_sipre_mqueue_payload_create(session, NULL, 0, NULL));
1132

    
1133
        janus_mutex_lock(&sessions_mutex);
1134
        g_hash_table_insert(sessions, handle, session);
1135
        janus_mutex_unlock(&sessions_mutex);
1136

    
1137

    
1138
        return;
1139
}
1140

    
1141
void janus_sipre_destroy_session(janus_plugin_session *handle, int *error) {
1142
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
1143
                *error = -1;
1144
                return;
1145
        }
1146
        janus_sipre_session *session = (janus_sipre_session *)handle->plugin_handle;
1147
        if(!session) {
1148
                JANUS_LOG(LOG_ERR, "No SIPre session associated with this handle...\n");
1149
                *error = -2;
1150
                return;
1151
        }
1152
        janus_mutex_lock(&sessions_mutex);
1153
        if(!session->destroyed) {
1154
                g_hash_table_remove(sessions, handle);
1155
                janus_sipre_hangup_media(handle);
1156
                session->destroyed = janus_get_monotonic_time();
1157
                JANUS_LOG(LOG_VERB, "Destroying SIPre session (%s)...\n", session->account.username ? session->account.username : "unregistered user");
1158
                /* Unregister */
1159
                mqueue_push(mq, janus_sipre_mqueue_event_do_unregister, janus_sipre_mqueue_payload_create(session, NULL, 0, NULL));
1160
                /* Destroy re-related stuff for this SIP session */
1161
                mqueue_push(mq, janus_sipre_mqueue_event_do_destroy, janus_sipre_mqueue_payload_create(session, NULL, 0, NULL));
1162
                /* Cleaning up and removing the session is done in a lazy way */
1163
                old_sessions = g_list_append(old_sessions, session);
1164
        }
1165
        janus_mutex_unlock(&sessions_mutex);
1166
        return;
1167
}
1168

    
1169
json_t *janus_sipre_query_session(janus_plugin_session *handle) {
1170
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized)) {
1171
                return NULL;
1172
        }
1173
        janus_sipre_session *session = (janus_sipre_session *)handle->plugin_handle;
1174
        if(!session) {
1175
                JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1176
                return NULL;
1177
        }
1178
        /* Provide some generic info, e.g., if we're in a call and with whom */
1179
        json_t *info = json_object();
1180
        json_object_set_new(info, "username", session->account.username ? json_string(session->account.username) : NULL);
1181
        json_object_set_new(info, "display_name", session->account.display_name ? json_string(session->account.display_name) : NULL);
1182
        json_object_set_new(info, "identity", session->account.identity ? json_string(session->account.identity) : NULL);
1183
        json_object_set_new(info, "registration_status", json_string(janus_sipre_registration_status_string(session->account.registration_status)));
1184
        json_object_set_new(info, "call_status", json_string(janus_sipre_call_status_string(session->status)));
1185
        if(session->callee) {
1186
                json_object_set_new(info, "callee", json_string(session->callee ? session->callee : "??"));
1187
                json_object_set_new(info, "auto-ack", json_string(session->media.autoack ? "yes" : "no"));
1188
                json_object_set_new(info, "srtp-required", json_string(session->media.require_srtp ? "yes" : "no"));
1189
                json_object_set_new(info, "sdes-local", json_string(session->media.has_srtp_local ? "yes" : "no"));
1190
                json_object_set_new(info, "sdes-remote", json_string(session->media.has_srtp_remote ? "yes" : "no"));
1191
        }
1192
        if(session->arc || session->vrc || session->arc_peer || session->vrc_peer) {
1193
                json_t *recording = json_object();
1194
                if(session->arc && session->arc->filename)
1195
                        json_object_set_new(recording, "audio", json_string(session->arc->filename));
1196
                if(session->vrc && session->vrc->filename)
1197
                        json_object_set_new(recording, "video", json_string(session->vrc->filename));
1198
                if(session->arc_peer && session->arc_peer->filename)
1199
                        json_object_set_new(recording, "audio-peer", json_string(session->arc_peer->filename));
1200
                if(session->vrc_peer && session->vrc_peer->filename)
1201
                        json_object_set_new(recording, "video-peer", json_string(session->vrc_peer->filename));
1202
                json_object_set_new(info, "recording", recording);
1203
        }
1204
        json_object_set_new(info, "destroyed", json_integer(session->destroyed));
1205
        return info;
1206
}
1207

    
1208
struct janus_plugin_result *janus_sipre_handle_message(janus_plugin_session *handle, char *transaction, json_t *message, json_t *jsep) {
1209
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
1210
                return janus_plugin_result_new(JANUS_PLUGIN_ERROR, g_atomic_int_get(&stopping) ? "Shutting down" : "Plugin not initialized", NULL);
1211
        janus_sipre_message *msg = g_malloc0(sizeof(janus_sipre_message));
1212
        msg->handle = handle;
1213
        msg->transaction = transaction;
1214
        msg->message = message;
1215
        msg->jsep = jsep;
1216
        g_async_queue_push(messages, msg);
1217

    
1218
        /* All the requests to this plugin are handled asynchronously */
1219
        return janus_plugin_result_new(JANUS_PLUGIN_OK_WAIT, NULL, NULL);
1220
}
1221

    
1222
void janus_sipre_setup_media(janus_plugin_session *handle) {
1223
        JANUS_LOG(LOG_INFO, "WebRTC media is now available\n");
1224
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
1225
                return;
1226
        janus_sipre_session *session = (janus_sipre_session *)handle->plugin_handle;
1227
        if(!session) {
1228
                JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1229
                return;
1230
        }
1231
        if(session->destroyed)
1232
                return;
1233
        g_atomic_int_set(&session->hangingup, 0);
1234
        /* TODO Only relay RTP/RTCP when we get this event */
1235
}
1236

    
1237
void janus_sipre_incoming_rtp(janus_plugin_session *handle, int video, char *buf, int len) {
1238
        if(handle == NULL || handle->stopped || g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
1239
                return;
1240
        if(gateway) {
1241
                /* Honour the audio/video active flags */
1242
                janus_sipre_session *session = (janus_sipre_session *)handle->plugin_handle;
1243
                if(!session || session->destroyed) {
1244
                        JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1245
                        return;
1246
                }
1247
                /* Forward to our SIPre peer */
1248
                if((video && !session->media.video_send) || (!video && !session->media.audio_send)) {
1249
                        /* Dropping packet, peer doesn't want to receive it */
1250
                        return;
1251
                }
1252
                if((video && session->media.video_ssrc == 0) || (!video && session->media.audio_ssrc == 0)) {
1253
                        rtp_header *header = (rtp_header *)buf;
1254
                        if(video) {
1255
                                session->media.video_ssrc = ntohl(header->ssrc);
1256
                        } else {
1257
                                session->media.audio_ssrc = ntohl(header->ssrc);
1258
                        }
1259
                        JANUS_LOG(LOG_VERB, "[SIPre-%s] Got SIPre %s SSRC: %"SCNu32"\n",
1260
                                session->account.username ? session->account.username : "unknown",
1261
                                video ? "video" : "audio",
1262
                                video ? session->media.video_ssrc : session->media.audio_ssrc);
1263
                }
1264
                if((video && session->media.has_video && session->media.video_rtp_fd != -1) ||
1265
                                (!video && session->media.has_audio && session->media.audio_rtp_fd != -1)) {
1266
                        /* Save the frame if we're recording */
1267
                        janus_recorder_save_frame(video ? session->vrc : session->arc, buf, len);
1268
                        /* Is SRTP involved? */
1269
                        if(session->media.has_srtp_local) {
1270
                                char sbuf[2048];
1271
                                memcpy(&sbuf, buf, len);
1272
                                int protected = len;
1273
                                int res = srtp_protect(
1274
                                        (video ? session->media.video_srtp_out : session->media.audio_srtp_out),
1275
                                        &sbuf, &protected);
1276
                                if(res != srtp_err_status_ok) {
1277
                                        rtp_header *header = (rtp_header *)&sbuf;
1278
                                        guint32 timestamp = ntohl(header->timestamp);
1279
                                        guint16 seq = ntohs(header->seq_number);
1280
                                        JANUS_LOG(LOG_ERR, "[SIPre-%s] %s SRTP protect error... %s (len=%d-->%d, ts=%"SCNu32", seq=%"SCNu16")...\n",
1281
                                                session->account.username ? session->account.username : "unknown",
1282
                                                video ? "Video" : "Audio", janus_srtp_error_str(res), len, protected, timestamp, seq);
1283
                                } else {
1284
                                        /* Forward the frame to the peer */
1285
                                        send((video ? session->media.video_rtp_fd : session->media.audio_rtp_fd), sbuf, protected, 0);
1286
                                }
1287
                        } else {
1288
                                /* Forward the frame to the peer */
1289
                                send((video ? session->media.video_rtp_fd : session->media.audio_rtp_fd), buf, len, 0);
1290
                        }
1291
                }
1292
        }
1293
}
1294

    
1295
void janus_sipre_incoming_rtcp(janus_plugin_session *handle, int video, char *buf, int len) {
1296
        if(handle == NULL || handle->stopped || g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
1297
                return;
1298
        if(gateway) {
1299
                janus_sipre_session *session = (janus_sipre_session *)handle->plugin_handle;
1300
                if(!session || session->destroyed) {
1301
                        JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1302
                        return;
1303
                }
1304
                /* Forward to our SIPre peer */
1305
                if((video && session->media.has_video && session->media.video_rtcp_fd != -1) ||
1306
                                (!video && session->media.has_audio && session->media.audio_rtcp_fd != -1)) {
1307
                        /* Fix SSRCs as the gateway does */
1308
                        JANUS_LOG(LOG_HUGE, "[SIPre-%s] Fixing %s SSRCs (local %u, peer %u)\n",
1309
                                session->account.username ? session->account.username : "unknown",
1310
                                video ? "video" : "audio",
1311
                                (video ? session->media.video_ssrc : session->media.audio_ssrc),
1312
                                (video ? session->media.video_ssrc_peer : session->media.audio_ssrc_peer));
1313
                        janus_rtcp_fix_ssrc(NULL, (char *)buf, len, video,
1314
                                (video ? session->media.video_ssrc : session->media.audio_ssrc),
1315
                                (video ? session->media.video_ssrc_peer : session->media.audio_ssrc_peer));
1316
                        /* Is SRTP involved? */
1317
                        if(session->media.has_srtp_local) {
1318
                                char sbuf[2048];
1319
                                memcpy(&sbuf, buf, len);
1320
                                int protected = len;
1321
                                int res = srtp_protect_rtcp(
1322
                                        (video ? session->media.video_srtp_out : session->media.audio_srtp_out),
1323
                                        &sbuf, &protected);
1324
                                if(res != srtp_err_status_ok) {
1325
                                        JANUS_LOG(LOG_ERR, "[SIPre-%s] %s SRTCP protect error... %s (len=%d-->%d)...\n",
1326
                                                session->account.username ? session->account.username : "unknown",
1327
                                                video ? "Video" : "Audio",
1328
                                                janus_srtp_error_str(res), len, protected);
1329
                                } else {
1330
                                        /* Forward the message to the peer */
1331
                                        send((video ? session->media.video_rtcp_fd : session->media.audio_rtcp_fd), sbuf, protected, 0);
1332
                                }
1333
                        } else {
1334
                                /* Forward the message to the peer */
1335
                                send((video ? session->media.video_rtcp_fd : session->media.audio_rtcp_fd), buf, len, 0);
1336
                        }
1337
                }
1338
        }
1339
}
1340

    
1341
void janus_sipre_hangup_media(janus_plugin_session *handle) {
1342
        JANUS_LOG(LOG_INFO, "No WebRTC media anymore\n");
1343
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
1344
                return;
1345
        janus_sipre_session *session = (janus_sipre_session *)handle->plugin_handle;
1346
        if(!session) {
1347
                JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1348
                return;
1349
        }
1350
        if(session->destroyed)
1351
                return;
1352
        if(g_atomic_int_add(&session->hangingup, 1))
1353
                return;
1354
        if(!(session->status == janus_sipre_call_status_inviting ||
1355
                 session->status == janus_sipre_call_status_invited ||
1356
                 session->status == janus_sipre_call_status_incall))
1357
                return;
1358
        session->media.ready = FALSE;
1359
        session->media.on_hold = FALSE;
1360
        session->status = janus_sipre_call_status_closing;
1361
        /* Enqueue the BYE */
1362
        mqueue_push(mq, janus_sipre_mqueue_event_do_bye, janus_sipre_mqueue_payload_create(session, NULL, 0, NULL));
1363
        /* Get rid of the recorders, if available */
1364
        janus_mutex_lock(&session->rec_mutex);
1365
        if(session->arc) {
1366
                janus_recorder_close(session->arc);
1367
                JANUS_LOG(LOG_INFO, "Closed user's audio recording %s\n", session->arc->filename ? session->arc->filename : "??");
1368
                janus_recorder_free(session->arc);
1369
        }
1370
        session->arc = NULL;
1371
        if(session->arc_peer) {
1372
                janus_recorder_close(session->arc_peer);
1373
                JANUS_LOG(LOG_INFO, "Closed peer's audio recording %s\n", session->arc_peer->filename ? session->arc_peer->filename : "??");
1374
                janus_recorder_free(session->arc_peer);
1375
        }
1376
        session->arc_peer = NULL;
1377
        if(session->vrc) {
1378
                janus_recorder_close(session->vrc);
1379
                JANUS_LOG(LOG_INFO, "Closed user's video recording %s\n", session->vrc->filename ? session->vrc->filename : "??");
1380
                janus_recorder_free(session->vrc);
1381
        }
1382
        session->vrc = NULL;
1383
        if(session->vrc_peer) {
1384
                janus_recorder_close(session->vrc_peer);
1385
                JANUS_LOG(LOG_INFO, "Closed peer's video recording %s\n", session->vrc_peer->filename ? session->vrc_peer->filename : "??");
1386
                janus_recorder_free(session->vrc_peer);
1387
        }
1388
        session->vrc_peer = NULL;
1389
        janus_mutex_unlock(&session->rec_mutex);
1390
}
1391

    
1392
/* Thread to handle incoming messages */
1393
static void *janus_sipre_handler(void *data) {
1394
        JANUS_LOG(LOG_VERB, "Joining SIPre handler thread\n");
1395
        janus_sipre_message *msg = NULL;
1396
        int error_code = 0;
1397
        char error_cause[512];
1398
        json_t *root = NULL;
1399
        while(g_atomic_int_get(&initialized) && !g_atomic_int_get(&stopping)) {
1400
                msg = g_async_queue_pop(messages);
1401
                if(msg == NULL)
1402
                        continue;
1403
                if(msg == &exit_message)
1404
                        break;
1405
                if(msg->handle == NULL) {
1406
                        janus_sipre_message_free(msg);
1407
                        continue;
1408
                }
1409
                janus_sipre_session *session = NULL;
1410
                janus_mutex_lock(&sessions_mutex);
1411
                if(g_hash_table_lookup(sessions, msg->handle) != NULL ) {
1412
                        session = (janus_sipre_session *)msg->handle->plugin_handle;
1413
                }
1414
                janus_mutex_unlock(&sessions_mutex);
1415
                if(!session) {
1416
                        JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1417
                        janus_sipre_message_free(msg);
1418
                        continue;
1419
                }
1420
                if(session->destroyed) {
1421
                        janus_sipre_message_free(msg);
1422
                        continue;
1423
                }
1424
                /* Handle request */
1425
                error_code = 0;
1426
                root = msg->message;
1427
                if(msg->message == NULL) {
1428
                        JANUS_LOG(LOG_ERR, "No message??\n");
1429
                        error_code = JANUS_SIPRE_ERROR_NO_MESSAGE;
1430
                        g_snprintf(error_cause, 512, "%s", "No message??");
1431
                        goto error;
1432
                }
1433
                if(!json_is_object(root)) {
1434
                        JANUS_LOG(LOG_ERR, "JSON error: not an object\n");
1435
                        error_code = JANUS_SIPRE_ERROR_INVALID_JSON;
1436
                        g_snprintf(error_cause, 512, "JSON error: not an object");
1437
                        goto error;
1438
                }
1439
                JANUS_VALIDATE_JSON_OBJECT(root, request_parameters,
1440
                        error_code, error_cause, TRUE,
1441
                        JANUS_SIPRE_ERROR_MISSING_ELEMENT, JANUS_SIPRE_ERROR_INVALID_ELEMENT);
1442
                if(error_code != 0)
1443
                        goto error;
1444
                json_t *request = json_object_get(root, "request");
1445
                const char *request_text = json_string_value(request);
1446
                json_t *result = NULL;
1447

    
1448
                if(!strcasecmp(request_text, "register")) {
1449
                        JANUS_VALIDATE_JSON_OBJECT(root, register_parameters,
1450
                                error_code, error_cause, TRUE,
1451
                                JANUS_SIPRE_ERROR_MISSING_ELEMENT, JANUS_SIPRE_ERROR_INVALID_ELEMENT);
1452
                        if(error_code != 0)
1453
                                goto error;
1454
                        gboolean refresh = json_is_true(json_object_get(root, "refresh"));
1455
                        if(session->account.registration_status > janus_sipre_registration_status_unregistered && !refresh) {
1456
                                JANUS_LOG(LOG_ERR, "Already registered (%s)\n", session->account.username);
1457
                                error_code = JANUS_SIPRE_ERROR_ALREADY_REGISTERED;
1458
                                g_snprintf(error_cause, 512, "Already registered (%s)", session->account.username);
1459
                                goto error;
1460
                        }
1461
                        /* Parse the request */
1462
                        gboolean guest = FALSE;
1463
                        json_t *type = json_object_get(root, "type");
1464
                        if(type != NULL) {
1465
                                const char *type_text = json_string_value(type);
1466
                                if(!strcmp(type_text, "guest")) {
1467
                                        JANUS_LOG(LOG_INFO, "Registering as a guest\n");
1468
                                        guest = TRUE;
1469
                                } else {
1470
                                        JANUS_LOG(LOG_WARN, "Unknown type '%s', ignoring...\n", type_text);
1471
                                }
1472
                        }
1473

    
1474
                        gboolean send_register = TRUE;
1475
                        json_t *do_register = json_object_get(root, "send_register");
1476
                        if(do_register != NULL) {
1477
                                if(guest) {
1478
                                        JANUS_LOG(LOG_ERR, "Conflicting elements: send_register cannot be true if guest is true\n");
1479
                                        error_code = JANUS_SIPRE_ERROR_INVALID_ELEMENT;
1480
                                        g_snprintf(error_cause, 512, "Conflicting elements: send_register cannot be true if guest is true");
1481
                                        goto error;
1482
                                }
1483
                                send_register = json_is_true(do_register);
1484
                        }
1485

    
1486
                        gboolean sips = TRUE;
1487
                        json_t *do_sipres = json_object_get(root, "sips");
1488
                        if(do_sipres != NULL) {
1489
                                sips = json_is_true(do_sipres);
1490
                        }
1491

    
1492
                        /* Parse address */
1493
                        json_t *proxy = json_object_get(root, "proxy");
1494
                        const char *proxy_text = NULL;
1495
                        if(proxy && !json_is_null(proxy)) {
1496
                                /* Has to be validated separately because it could be null */
1497
                                JANUS_VALIDATE_JSON_OBJECT(root, proxy_parameters,
1498
                                        error_code, error_cause, TRUE,
1499
                                        JANUS_SIPRE_ERROR_MISSING_ELEMENT, JANUS_SIPRE_ERROR_INVALID_ELEMENT);
1500
                                if(error_code != 0)
1501
                                        goto error;
1502
                                proxy_text = json_string_value(proxy);
1503
                                if(janus_sipre_parse_uri(proxy_text) < 0) {
1504
                                        JANUS_LOG(LOG_ERR, "Invalid proxy address %s\n", proxy_text);
1505
                                        error_code = JANUS_SIPRE_ERROR_INVALID_ADDRESS;
1506
                                        g_snprintf(error_cause, 512, "Invalid proxy address %s\n", proxy_text);
1507
                                        goto error;
1508
                                }
1509
                        }
1510
                        json_t *outbound_proxy = json_object_get(root, "outbound_proxy");
1511
                        const char *obproxy_text = NULL;
1512
                        if(outbound_proxy && !json_is_null(outbound_proxy)) {
1513
                                /* Has to be validated separately because it could be null */
1514
                                JANUS_VALIDATE_JSON_OBJECT(root, proxy_parameters,
1515
                                        error_code, error_cause, TRUE,
1516
                                        JANUS_SIPRE_ERROR_MISSING_ELEMENT, JANUS_SIPRE_ERROR_INVALID_ELEMENT);
1517
                                if(error_code != 0)
1518
                                        goto error;
1519
                                obproxy_text = json_string_value(outbound_proxy);
1520
                                if(janus_sipre_parse_uri(obproxy_text) < 0) {
1521
                                        JANUS_LOG(LOG_ERR, "Invalid outbound_proxy address %s\n", obproxy_text);
1522
                                        error_code = JANUS_SIPRE_ERROR_INVALID_ADDRESS;
1523
                                        g_snprintf(error_cause, 512, "Invalid outbound_proxy address %s\n", obproxy_text);
1524
                                        goto error;
1525
                                }
1526
                        }
1527

    
1528
                        /* Parse register TTL */
1529
                        int ttl = register_ttl;
1530
                        json_t *reg_ttl = json_object_get(root, "register_ttl");
1531
                        if(reg_ttl && json_is_integer(reg_ttl))
1532
                                ttl = json_integer_value(reg_ttl);
1533
                        if(ttl <= 0)
1534
                                ttl = register_ttl;
1535
                        session->stack.expires = ttl;
1536

    
1537
                        /* Parse display name */
1538
                        const char* display_name_text = NULL;
1539
                        json_t *display_name = json_object_get(root, "display_name");
1540
                        if(display_name && json_is_string(display_name))
1541
                                display_name_text = json_string_value(display_name);
1542

    
1543
                        /* Now the user part (always needed, even for the guest case) */
1544
                        json_t *username = json_object_get(root, "username");
1545
                        if(!username) {
1546
                                /* The username is mandatory even when registering as guests */
1547
                                JANUS_LOG(LOG_ERR, "Missing element (username)\n");
1548
                                error_code = JANUS_SIPRE_ERROR_MISSING_ELEMENT;
1549
                                g_snprintf(error_cause, 512, "Missing element (username)");
1550
                                goto error;
1551
                        }
1552
                        const char *username_text = NULL;
1553
                        const char *secret_text = NULL;
1554
                        const char *authuser_text = NULL;
1555
                        janus_sipre_secret_type secret_type = janus_sipre_secret_type_plaintext;
1556
                        char *user_id = NULL, *user_host = NULL;
1557
                        guint16 user_port = 0;
1558
                        /* Parse address */
1559
                        username_text = json_string_value(username);
1560
                        if(janus_sipre_parse_uri(username_text) < 0) {
1561
                                JANUS_LOG(LOG_ERR, "Invalid user address %s\n", username_text);
1562
                                error_code = JANUS_SIPRE_ERROR_INVALID_ADDRESS;
1563
                                g_snprintf(error_cause, 512, "Invalid user address %s\n", username_text);
1564
                                goto error;
1565
                        }
1566
                        user_id = janus_sipre_get_uri_username(username_text);
1567
                        user_host = janus_sipre_get_uri_host(username_text);
1568
                        user_port = janus_sipre_get_uri_port(username_text);
1569
                        if(guest) {
1570
                                /* Not needed, we can stop here: just say we're registered */
1571
                                JANUS_LOG(LOG_INFO, "Guest will have username %s\n", user_id);
1572
                                send_register = FALSE;
1573
                        } else {
1574
                                json_t *secret = json_object_get(root, "secret");
1575
                                json_t *authuser = json_object_get(root, "authuser");
1576
                                if(!secret) {
1577
                                        g_free(user_id);
1578
                                        g_free(user_host);
1579
                                        JANUS_LOG(LOG_ERR, "Missing element (secret)\n");
1580
                                        error_code = JANUS_SIPRE_ERROR_MISSING_ELEMENT;
1581
                                        g_snprintf(error_cause, 512, "Missing element (secret)");
1582
                                        goto error;
1583
                                }
1584
                                secret_text = json_string_value(secret);
1585
                                secret_type = janus_sipre_secret_type_plaintext;
1586
                                if(authuser) {
1587
                                        authuser_text = json_string_value(authuser);
1588
                                }
1589
                                /* Got the values, try registering now */
1590
                                JANUS_LOG(LOG_VERB, "Registering user %s (auth=%s, secret %s) @ %s through %s (outbound proxy: %s)\n",
1591
                                        user_id, secret_text, user_host,
1592
                                        authuser_text != NULL ? authuser_text : user_id,
1593
                                        proxy_text != NULL ? proxy_text : "(null)",
1594
                                        obproxy_text != NULL ? obproxy_text : "none");
1595
                        }
1596

    
1597
                        /* If this is a refresh, get rid of the old values */
1598
                        if(refresh) {
1599
                                /* Cleanup old values */
1600
                                if(session->account.identity != NULL) {
1601
                                        g_hash_table_remove(identities, session->account.identity);
1602
                                        g_free(session->account.identity);
1603
                                }
1604
                                session->account.identity = NULL;
1605
                                session->account.sips = TRUE;
1606
                                if(session->account.username != NULL)
1607
                                        g_free(session->account.username);
1608
                                session->account.username = NULL;
1609
                                if(session->account.display_name != NULL)
1610
                                        g_free(session->account.display_name);
1611
                                session->account.display_name = NULL;
1612
                                if(session->account.authuser != NULL)
1613
                                        g_free(session->account.authuser);
1614
                                session->account.authuser = NULL;
1615
                                if(session->account.secret != NULL)
1616
                                        g_free(session->account.secret);
1617
                                session->account.secret = NULL;
1618
                                session->account.secret_type = janus_sipre_secret_type_unknown;
1619
                                if(session->account.proxy != NULL)
1620
                                        g_free(session->account.proxy);
1621
                                session->account.proxy = NULL;
1622
                                if(session->account.outbound_proxy != NULL)
1623
                                        g_free(session->account.outbound_proxy);
1624
                                session->account.outbound_proxy = NULL;
1625
                                session->account.registration_status = janus_sipre_registration_status_unregistered;
1626
                        }
1627
                        session->account.identity = g_strdup(username_text);
1628
                        g_hash_table_insert(identities, session->account.identity, session);
1629
                        session->account.sips = sips;
1630
                        session->account.username = g_strdup(user_id);
1631
                        session->account.authuser = g_strdup(authuser_text ? authuser_text : user_id);
1632
                        session->account.secret = secret_text ? g_strdup(secret_text) : NULL;
1633
                        session->account.secret_type = secret_type;
1634
                        if(display_name_text) {
1635
                                session->account.display_name = g_strdup(display_name_text);
1636
                        }
1637
                        if(proxy_text) {
1638
                                session->account.proxy = g_strdup(proxy_text);
1639
                        } else {
1640
                                /* Build one from the user's identity */
1641
                                char uri[256];
1642
                                g_snprintf(uri, sizeof(uri), "sip:%s:%"SCNu16, user_host, (user_port ? user_port : 5060));
1643
                                session->account.proxy = g_strdup(uri);
1644
                        }
1645
                        if(obproxy_text) {
1646
                                session->account.outbound_proxy = g_strdup(obproxy_text);
1647
                        }
1648
                        g_free(user_host);
1649
                        g_free(user_id);
1650

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

    
2493
                /* Prepare JSON event */
2494
                json_t *event = json_object();
2495
                json_object_set_new(event, "sip", json_string("event"));
2496
                if(result != NULL)
2497
                        json_object_set_new(event, "result", result);
2498
                int ret = gateway->push_event(msg->handle, &janus_sipre_plugin, msg->transaction, event, NULL);
2499
                JANUS_LOG(LOG_VERB, "  >> Pushing event: %d (%s)\n", ret, janus_get_api_error(ret));
2500
                json_decref(event);
2501
                janus_sipre_message_free(msg);
2502
                continue;
2503

    
2504
error:
2505
                {
2506
                        /* Prepare JSON error event */
2507
                        json_t *event = json_object();
2508
                        json_object_set_new(event, "sip", json_string("event"));
2509
                        json_object_set_new(event, "error_code", json_integer(error_code));
2510
                        json_object_set_new(event, "error", json_string(error_cause));
2511
                        int ret = gateway->push_event(msg->handle, &janus_sipre_plugin, msg->transaction, event, NULL);
2512
                        JANUS_LOG(LOG_VERB, "  >> Pushing event: %d (%s)\n", ret, janus_get_api_error(ret));
2513
                        json_decref(event);
2514
                        janus_sipre_message_free(msg);
2515
                }
2516
        }
2517
        JANUS_LOG(LOG_VERB, "Leaving SIPre handler thread\n");
2518
        return NULL;
2519
}
2520

    
2521

    
2522
/* Process an incoming SDP */
2523
void janus_sipre_sdp_process(janus_sipre_session *session, janus_sdp *sdp, gboolean answer, gboolean update, gboolean *changed) {
2524
        if(!session || !sdp)
2525
                return;
2526
        /* c= */
2527
        if(sdp->c_addr) {
2528
                if(update && strcmp(sdp->c_addr, session->media.remote_ip)) {
2529
                        /* This is an update and an address changed */
2530
                        if(changed)
2531
                                *changed = TRUE;
2532
                }
2533
                g_free(session->media.remote_ip);
2534
                session->media.remote_ip = g_strdup(sdp->c_addr);
2535
        }
2536
        GList *temp = sdp->m_lines;
2537
        while(temp) {
2538
                janus_sdp_mline *m = (janus_sdp_mline *)temp->data;
2539
                session->media.require_srtp = session->media.require_srtp || (m->proto && !strcasecmp(m->proto, "RTP/SAVP"));
2540
                if(m->type == JANUS_SDP_AUDIO) {
2541
                        if(m->port) {
2542
                                if(m->port != session->media.remote_audio_rtp_port) {
2543
                                        /* This is an update and an address changed */
2544
                                        if(changed)
2545
                                                *changed = TRUE;
2546
                                }
2547
                                session->media.has_audio = TRUE;
2548
                                session->media.remote_audio_rtp_port = m->port;
2549
                                session->media.remote_audio_rtcp_port = m->port+1;        /* FIXME We're assuming RTCP is on the next port */
2550
                                if(m->direction == JANUS_SDP_SENDONLY || m->direction == JANUS_SDP_INACTIVE)
2551
                                        session->media.audio_send = FALSE;
2552
                                else
2553
                                        session->media.audio_send = TRUE;
2554
                        } else {
2555
                                session->media.audio_send = FALSE;
2556
                        }
2557
                } else if(m->type == JANUS_SDP_VIDEO) {
2558
                        if(m->port) {
2559
                                if(m->port != session->media.remote_video_rtp_port) {
2560
                                        /* This is an update and an address changed */
2561
                                        if(changed)
2562
                                                *changed = TRUE;
2563
                                }
2564
                                session->media.has_video = TRUE;
2565
                                session->media.remote_video_rtp_port = m->port;
2566
                                session->media.remote_video_rtcp_port = m->port+1;        /* FIXME We're assuming RTCP is on the next port */
2567
                                if(m->direction == JANUS_SDP_SENDONLY || m->direction == JANUS_SDP_INACTIVE)
2568
                                        session->media.video_send = FALSE;
2569
                                else
2570
                                        session->media.video_send = TRUE;
2571
                        } else {
2572
                                session->media.video_send = FALSE;
2573
                        }
2574
                } else {
2575
                        JANUS_LOG(LOG_WARN, "Unsupported media line (not audio/video)\n");
2576
                        temp = temp->next;
2577
                        continue;
2578
                }
2579
                if(m->c_addr) {
2580
                        if(update && strcmp(m->c_addr, session->media.remote_ip)) {
2581
                                /* This is an update and an address changed */
2582
                                if(changed)
2583
                                        *changed = TRUE;
2584
                        }
2585
                        g_free(session->media.remote_ip);
2586
                        session->media.remote_ip = g_strdup(m->c_addr);
2587
                }
2588
                if(update) {
2589
                        /* FIXME This is a session update, we only accept changes in IP/ports */
2590
                        temp = temp->next;
2591
                        continue;
2592
                }
2593
                GList *tempA = m->attributes;
2594
                while(tempA) {
2595
                        janus_sdp_attribute *a = (janus_sdp_attribute *)tempA->data;
2596
                        if(a->name) {
2597
                                if(!strcasecmp(a->name, "crypto")) {
2598
                                        if(m->type == JANUS_SDP_AUDIO || m->type == JANUS_SDP_VIDEO) {
2599
                                                gint32 tag = 0;
2600
                                                int suite;
2601
                                                char crypto[81];
2602
                                                /* FIXME inline can be more complex than that, and we're currently only offering SHA1_80 */
2603
                                                int res = sscanf(a->value, "%"SCNi32" AES_CM_128_HMAC_SHA1_%2d inline:%80s",
2604
                                                        &tag, &suite, crypto);
2605
                                                if(res != 3) {
2606
                                                        JANUS_LOG(LOG_WARN, "Failed to parse crypto line, ignoring... %s\n", a->value);
2607
                                                } else {
2608
                                                        gboolean video = (m->type == JANUS_SDP_VIDEO);
2609
                                                        int current_suite = video ? session->media.video_srtp_suite_in : session->media.audio_srtp_suite_in;
2610
                                                        if(current_suite == 0) {
2611
                                                                if(video)
2612
                                                                        session->media.video_srtp_suite_in = suite;
2613
                                                                else
2614
                                                                        session->media.audio_srtp_suite_in = suite;
2615
                                                                janus_sipre_srtp_set_remote(session, video, crypto, suite);
2616
                                                                session->media.has_srtp_remote = TRUE;
2617
                                                        } else {
2618
                                                                JANUS_LOG(LOG_WARN, "We already configured a %s crypto context (AES_CM_128_HMAC_SHA1_%d), skipping additional crypto line\n",
2619
                                                                        video ? "video" : "audio", current_suite);
2620
                                                        }
2621
                                                }
2622
                                        }
2623
                                }
2624
                        }
2625
                        tempA = tempA->next;
2626
                }
2627
                if(answer && (m->type == JANUS_SDP_AUDIO || m->type == JANUS_SDP_VIDEO)) {
2628
                        /* Check which codec was negotiated eventually */
2629
                        int pt = -1;
2630
                        if(m->ptypes)
2631
                                pt = GPOINTER_TO_INT(m->ptypes->data);
2632
                        if(pt > -1) {
2633
                                if(m->type == JANUS_SDP_AUDIO) {
2634
                                        session->media.audio_pt = pt;
2635
                                } else {
2636
                                        session->media.video_pt = pt;
2637
                                }
2638
                        }
2639
                }
2640
                temp = temp->next;
2641
        }
2642
        if(update && changed && *changed) {
2643
                /* Something changed: mark this on the session, so that the thread can update the sockets */
2644
                session->media.updated = TRUE;
2645
                if(session->media.pipefd[1] > 0) {
2646
                        int code = 1;
2647
                        ssize_t res = 0;
2648
                        do {
2649
                                res = write(session->media.pipefd[1], &code, sizeof(int));
2650
                        } while(res == -1 && errno == EINTR);
2651
                }
2652
        }
2653
}
2654

    
2655
char *janus_sipre_sdp_manipulate(janus_sipre_session *session, janus_sdp *sdp, gboolean answer) {
2656
        if(!session || !sdp)
2657
                return NULL;
2658
        /* Start replacing stuff */
2659
        JANUS_LOG(LOG_VERB, "Setting protocol to %s\n", session->media.require_srtp ? "RTP/SAVP" : "RTP/AVP");
2660
        GList *temp = sdp->m_lines;
2661
        while(temp) {
2662
                janus_sdp_mline *m = (janus_sdp_mline *)temp->data;
2663
                g_free(m->proto);
2664
                m->proto = g_strdup(session->media.require_srtp ? "RTP/SAVP" : "RTP/AVP");
2665
                if(m->type == JANUS_SDP_AUDIO) {
2666
                        m->port = session->media.local_audio_rtp_port;
2667
                        if(session->media.has_srtp_local) {
2668
                                char *crypto = NULL;
2669
                                session->media.audio_srtp_suite_out = 80;
2670
                                janus_sipre_srtp_set_local(session, FALSE, &crypto);
2671
                                /* FIXME 32? 80? Both? */
2672
                                janus_sdp_attribute *a = janus_sdp_attribute_create("crypto", "1 AES_CM_128_HMAC_SHA1_80 inline:%s", crypto);
2673
                                g_free(crypto);
2674
                                m->attributes = g_list_append(m->attributes, a);
2675
                        }
2676
                } else if(m->type == JANUS_SDP_VIDEO) {
2677
                        m->port = session->media.local_video_rtp_port;
2678
                        if(session->media.has_srtp_local) {
2679
                                char *crypto = NULL;
2680
                                session->media.audio_srtp_suite_out = 80;
2681
                                janus_sipre_srtp_set_local(session, TRUE, &crypto);
2682
                                /* FIXME 32? 80? Both? */
2683
                                janus_sdp_attribute *a = janus_sdp_attribute_create("crypto", "1 AES_CM_128_HMAC_SHA1_80 inline:%s", crypto);
2684
                                g_free(crypto);
2685
                                m->attributes = g_list_append(m->attributes, a);
2686
                        }
2687
                }
2688
                g_free(m->c_addr);
2689
                m->c_addr = g_strdup(local_ip);
2690
                if(answer && (m->type == JANUS_SDP_AUDIO || m->type == JANUS_SDP_VIDEO)) {
2691
                        /* Check which codec was negotiated eventually */
2692
                        int pt = -1;
2693
                        if(m->ptypes)
2694
                                pt = GPOINTER_TO_INT(m->ptypes->data);
2695
                        if(pt > -1) {
2696
                                if(m->type == JANUS_SDP_AUDIO) {
2697
                                        session->media.audio_pt = pt;
2698
                                } else {
2699
                                        session->media.video_pt = pt;
2700
                                }
2701
                        }
2702
                }
2703
                temp = temp->next;
2704
        }
2705
        /* Generate a SDP string out of our changes */
2706
        return janus_sdp_write(sdp);
2707
}
2708

    
2709
/* Bind local RTP/RTCP sockets */
2710
static int janus_sipre_allocate_local_ports(janus_sipre_session *session) {
2711
        if(session == NULL) {
2712
                JANUS_LOG(LOG_ERR, "Invalid session\n");
2713
                return -1;
2714
        }
2715
        /* Reset status */
2716
        if(session->media.audio_rtp_fd != -1) {
2717
                close(session->media.audio_rtp_fd);
2718
                session->media.audio_rtp_fd = -1;
2719
        }
2720
        if(session->media.audio_rtcp_fd != -1) {
2721
                close(session->media.audio_rtcp_fd);
2722
                session->media.audio_rtcp_fd = -1;
2723
        }
2724
        session->media.local_audio_rtp_port = 0;
2725
        session->media.local_audio_rtcp_port = 0;
2726
        session->media.audio_ssrc = 0;
2727
        if(session->media.video_rtp_fd != -1) {
2728
                close(session->media.video_rtp_fd);
2729
                session->media.video_rtp_fd = -1;
2730
        }
2731
        if(session->media.video_rtcp_fd != -1) {
2732
                close(session->media.video_rtcp_fd);
2733
                session->media.video_rtcp_fd = -1;
2734
        }
2735
        session->media.local_video_rtp_port = 0;
2736
        session->media.local_video_rtcp_port = 0;
2737
        session->media.video_ssrc = 0;
2738
        if(session->media.pipefd[0] > 0) {
2739
                close(session->media.pipefd[0]);
2740
                session->media.pipefd[0] = -1;
2741
        }
2742
        if(session->media.pipefd[1] > 0) {
2743
                close(session->media.pipefd[1]);
2744
                session->media.pipefd[1] = -1;
2745
        }
2746
        /* Start */
2747
        int attempts = 100;        /* FIXME Don't retry forever */
2748
        if(session->media.has_audio) {
2749
                JANUS_LOG(LOG_VERB, "Allocating audio ports:\n");
2750
                struct sockaddr_in audio_rtp_address, audio_rtcp_address;
2751
                while(session->media.local_audio_rtp_port == 0 || session->media.local_audio_rtcp_port == 0) {
2752
                        if(attempts == 0)        /* Too many failures */
2753
                                return -1;
2754
                        if(session->media.audio_rtp_fd == -1) {
2755
                                session->media.audio_rtp_fd = socket(AF_INET, SOCK_DGRAM, 0);
2756
                        }
2757
                        if(session->media.audio_rtcp_fd == -1) {
2758
                                session->media.audio_rtcp_fd = socket(AF_INET, SOCK_DGRAM, 0);
2759
                        }
2760
                        int rtp_port = g_random_int_range(10000, 60000);        /* FIXME Should this be configurable? */
2761
                        if(rtp_port % 2)
2762
                                rtp_port++;        /* Pick an even port for RTP */
2763
                        audio_rtp_address.sin_family = AF_INET;
2764
                        audio_rtp_address.sin_port = htons(rtp_port);
2765
                        inet_pton(AF_INET, local_ip, &audio_rtp_address.sin_addr.s_addr);
2766
                        if(bind(session->media.audio_rtp_fd, (struct sockaddr *)(&audio_rtp_address), sizeof(struct sockaddr)) < 0) {
2767
                                JANUS_LOG(LOG_ERR, "Bind failed for audio RTP (port %d), trying a different one...\n", rtp_port);
2768
                                attempts--;
2769
                                continue;
2770
                        }
2771
                        JANUS_LOG(LOG_VERB, "Audio RTP listener bound to port %d\n", rtp_port);
2772
                        int rtcp_port = rtp_port+1;
2773
                        audio_rtcp_address.sin_family = AF_INET;
2774
                        audio_rtcp_address.sin_port = htons(rtcp_port);
2775
                        inet_pton(AF_INET, local_ip, &audio_rtcp_address.sin_addr.s_addr);
2776
                        if(bind(session->media.audio_rtcp_fd, (struct sockaddr *)(&audio_rtcp_address), sizeof(struct sockaddr)) < 0) {
2777
                                JANUS_LOG(LOG_ERR, "Bind failed for audio RTCP (port %d), trying a different one...\n", rtcp_port);
2778
                                /* RTP socket is not valid anymore, reset it */
2779
                                close(session->media.audio_rtp_fd);
2780
                                session->media.audio_rtp_fd = -1;
2781
                                attempts--;
2782
                                continue;
2783
                        }
2784
                        JANUS_LOG(LOG_VERB, "Audio RTCP listener bound to port %d\n", rtcp_port);
2785
                        session->media.local_audio_rtp_port = rtp_port;
2786
                        session->media.local_audio_rtcp_port = rtcp_port;
2787
                }
2788
        }
2789
        if(session->media.has_video) {
2790
                JANUS_LOG(LOG_VERB, "Allocating video ports:\n");
2791
                struct sockaddr_in video_rtp_address, video_rtcp_address;
2792
                while(session->media.local_video_rtp_port == 0 || session->media.local_video_rtcp_port == 0) {
2793
                        if(attempts == 0)        /* Too many failures */
2794
                                return -1;
2795
                        if(session->media.video_rtp_fd == -1) {
2796
                                session->media.video_rtp_fd = socket(AF_INET, SOCK_DGRAM, 0);
2797
                        }
2798
                        if(session->media.video_rtcp_fd == -1) {
2799
                                session->media.video_rtcp_fd = socket(AF_INET, SOCK_DGRAM, 0);
2800
                        }
2801
                        int rtp_port = g_random_int_range(10000, 60000);        /* FIXME Should this be configurable? */
2802
                        if(rtp_port % 2)
2803
                                rtp_port++;        /* Pick an even port for RTP */
2804
                        video_rtp_address.sin_family = AF_INET;
2805
                        video_rtp_address.sin_port = htons(rtp_port);
2806
                        inet_pton(AF_INET, local_ip, &video_rtp_address.sin_addr.s_addr);
2807
                        if(bind(session->media.video_rtp_fd, (struct sockaddr *)(&video_rtp_address), sizeof(struct sockaddr)) < 0) {
2808
                                JANUS_LOG(LOG_ERR, "Bind failed for video RTP (port %d), trying a different one...\n", rtp_port);
2809
                                attempts--;
2810
                                continue;
2811
                        }
2812
                        JANUS_LOG(LOG_VERB, "Video RTP listener bound to port %d\n", rtp_port);
2813
                        int rtcp_port = rtp_port+1;
2814
                        video_rtcp_address.sin_family = AF_INET;
2815
                        video_rtcp_address.sin_port = htons(rtcp_port);
2816
                        inet_pton(AF_INET, local_ip, &video_rtcp_address.sin_addr.s_addr);
2817
                        if(bind(session->media.video_rtcp_fd, (struct sockaddr *)(&video_rtcp_address), sizeof(struct sockaddr)) < 0) {
2818
                                JANUS_LOG(LOG_ERR, "Bind failed for video RTCP (port %d), trying a different one...\n", rtcp_port);
2819
                                /* RTP socket is not valid anymore, reset it */
2820
                                close(session->media.video_rtp_fd);
2821
                                session->media.video_rtp_fd = -1;
2822
                                attempts--;
2823
                                continue;
2824
                        }
2825
                        JANUS_LOG(LOG_VERB, "Video RTCP listener bound to port %d\n", rtcp_port);
2826
                        session->media.local_video_rtp_port = rtp_port;
2827
                        session->media.local_video_rtcp_port = rtcp_port;
2828
                }
2829
        }
2830
        /* We need this to quickly interrupt the poll when it's time to update a session or wrap up */
2831
        pipe(session->media.pipefd);
2832
        return 0;
2833
}
2834

    
2835
/* Helper method to (re)connect RTP/RTCP sockets */
2836
static void janus_sipre_connect_sockets(janus_sipre_session *session, struct sockaddr_in *server_addr) {
2837
        if(!session || !server_addr)
2838
                return;
2839

    
2840
        if(session->media.updated) {
2841
                JANUS_LOG(LOG_VERB, "Updating session sockets\n");
2842
        }
2843

    
2844
        /* Connect peers (FIXME This pretty much sucks right now) */
2845
        if(session->media.remote_audio_rtp_port) {
2846
                server_addr->sin_port = htons(session->media.remote_audio_rtp_port);
2847
                if(connect(session->media.audio_rtp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
2848
                        JANUS_LOG(LOG_ERR, "[SIPre-%s] Couldn't connect audio RTP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_audio_rtp_port);
2849
                        JANUS_LOG(LOG_ERR, "[SIPre-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2850
                }
2851
        }
2852
        if(session->media.remote_audio_rtcp_port) {
2853
                server_addr->sin_port = htons(session->media.remote_audio_rtcp_port);
2854
                if(connect(session->media.audio_rtcp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
2855
                        JANUS_LOG(LOG_ERR, "[SIPre-%s] Couldn't connect audio RTCP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_audio_rtcp_port);
2856
                        JANUS_LOG(LOG_ERR, "[SIPre-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2857
                }
2858
        }
2859
        if(session->media.remote_video_rtp_port) {
2860
                server_addr->sin_port = htons(session->media.remote_video_rtp_port);
2861
                if(connect(session->media.video_rtp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
2862
                        JANUS_LOG(LOG_ERR, "[SIPre-%s] Couldn't connect video RTP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_video_rtp_port);
2863
                        JANUS_LOG(LOG_ERR, "[SIPre-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2864
                }
2865
        }
2866
        if(session->media.remote_video_rtcp_port) {
2867
                server_addr->sin_port = htons(session->media.remote_video_rtcp_port);
2868
                if(connect(session->media.video_rtcp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
2869
                        JANUS_LOG(LOG_ERR, "[SIPre-%s] Couldn't connect video RTCP? (%s:%d)\n", session->account.username, session->media.remote_ip, session->media.remote_video_rtcp_port);
2870
                        JANUS_LOG(LOG_ERR, "[SIPre-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2871
                }
2872
        }
2873

    
2874
}
2875

    
2876
/* Thread to relay RTP/RTCP frames coming from the SIPre peer */
2877
static void *janus_sipre_relay_thread(void *data) {
2878
        janus_sipre_session *session = (janus_sipre_session *)data;
2879
        if(!session || !session->account.username || !session->callee) {
2880
                g_thread_unref(g_thread_self());
2881
                return NULL;
2882
        }
2883
        JANUS_LOG(LOG_VERB, "Starting relay thread (%s <--> %s)\n", session->account.username, session->callee);
2884

    
2885
        gboolean have_server_ip = TRUE;
2886
        struct sockaddr_in server_addr;
2887
        memset(&server_addr, 0, sizeof(server_addr));
2888
        server_addr.sin_family = AF_INET;
2889
        if(inet_aton(session->media.remote_ip, &server_addr.sin_addr) == 0) {        /* Not a numeric IP... */
2890
                struct hostent *host = gethostbyname(session->media.remote_ip);        /* ...resolve name */
2891
                if(!host) {
2892
                        JANUS_LOG(LOG_ERR, "[SIPre-%s] Couldn't get host (%s)\n", session->account.username, session->media.remote_ip);
2893
                        have_server_ip = FALSE;
2894
                } else {
2895
                        server_addr.sin_addr = *(struct in_addr *)host->h_addr_list;
2896
                }
2897
        }
2898
        if(have_server_ip)
2899
                janus_sipre_connect_sockets(session, &server_addr);
2900

    
2901
        if(!session->callee) {
2902
                JANUS_LOG(LOG_VERB, "[SIPre-%s] Leaving thread, no callee...\n", session->account.username);
2903
                g_thread_unref(g_thread_self());
2904
                return NULL;
2905
        }
2906
        /* File descriptors */
2907
        socklen_t addrlen;
2908
        struct sockaddr_in remote;
2909
        int resfd = 0, bytes = 0;
2910
        struct pollfd fds[5];
2911
        int pipe_fd = session->media.pipefd[0];
2912
        char buffer[1500];
2913
        memset(buffer, 0, 1500);
2914
        /* Loop */
2915
        int num = 0;
2916
        gboolean goon = TRUE;
2917
        int astep = 0, vstep = 0;
2918
        guint32 ats = 0, vts = 0;
2919
        while(goon && session != NULL && !session->destroyed &&
2920
                        session->status > janus_sipre_call_status_idle &&
2921
                        session->status < janus_sipre_call_status_closing) {        /* FIXME We need a per-call watchdog as well */
2922

    
2923
                if(session->media.updated) {
2924
                        /* Apparently there was a session update */
2925
                        if(session->media.remote_ip != NULL && (inet_aton(session->media.remote_ip, &server_addr.sin_addr) != 0)) {
2926
                                janus_sipre_connect_sockets(session, &server_addr);
2927
                        } else {
2928
                                JANUS_LOG(LOG_ERR, "[SIPre-%s] Couldn't update session details (missing or invalid remote IP address)\n", session->account.username);
2929
                        }
2930
                        session->media.updated = FALSE;
2931
                }
2932

    
2933
                /* Prepare poll */
2934
                num = 0;
2935
                if(session->media.audio_rtp_fd != -1) {
2936
                        fds[num].fd = session->media.audio_rtp_fd;
2937
                        fds[num].events = POLLIN;
2938
                        fds[num].revents = 0;
2939
                        num++;
2940
                }
2941
                if(session->media.audio_rtcp_fd != -1) {
2942
                        fds[num].fd = session->media.audio_rtcp_fd;
2943
                        fds[num].events = POLLIN;
2944
                        fds[num].revents = 0;
2945
                        num++;
2946
                }
2947
                if(session->media.video_rtp_fd != -1) {
2948
                        fds[num].fd = session->media.video_rtp_fd;
2949
                        fds[num].events = POLLIN;
2950
                        fds[num].revents = 0;
2951
                        num++;
2952
                }
2953
                if(session->media.video_rtcp_fd != -1) {
2954
                        fds[num].fd = session->media.video_rtcp_fd;
2955
                        fds[num].events = POLLIN;
2956
                        fds[num].revents = 0;
2957
                        num++;
2958
                }
2959
                if(pipe_fd != -1) {
2960
                        fds[num].fd = pipe_fd;
2961
                        fds[num].events = POLLIN;
2962
                        fds[num].revents = 0;
2963
                        num++;
2964
                }
2965
                /* Wait for some data */
2966
                resfd = poll(fds, num, 1000);
2967
                if(resfd < 0) {
2968
                        JANUS_LOG(LOG_ERR, "[SIPre-%s] Error polling...\n", session->account.username);
2969
                        JANUS_LOG(LOG_ERR, "[SIPre-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2970
                        break;
2971
                } else if(resfd == 0) {
2972
                        /* No data, keep going */
2973
                        continue;
2974
                }
2975
                if(session == NULL || session->destroyed ||
2976
                                session->status <= janus_sipre_call_status_idle ||
2977
                                session->status >= janus_sipre_call_status_closing)
2978
                        break;
2979
                int i = 0;
2980
                for(i=0; i<num; i++) {
2981
                        if(fds[i].revents & (POLLERR | POLLHUP)) {
2982
                                /* If we just updated the session, let's wait until things have calmed down */
2983
                                if(session->media.updated)
2984
                                        break;
2985
                                /* Check the socket error */
2986
                                int error = 0;
2987
                                socklen_t errlen = sizeof(error);
2988
                                getsockopt(fds[i].fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
2989
                                if(error == 0) {
2990
                                        /* Maybe not a breaking error after all? */
2991
                                        continue;
2992
                                } else if(error == 111) {
2993
                                        /* ICMP error? If it's related to RTCP, let's just close the RTCP socket and move on */
2994
                                        if(fds[i].fd == session->media.audio_rtcp_fd) {
2995
                                                JANUS_LOG(LOG_WARN, "[SIPre-%s] Got a '%s' on the audio RTCP socket, closing it\n",
2996
                                                        session->account.username, strerror(error));
2997
                                                close(session->media.audio_rtcp_fd);
2998
                                                session->media.audio_rtcp_fd = -1;
2999
                                        } else if(fds[i].fd == session->media.video_rtcp_fd) {
3000
                                                JANUS_LOG(LOG_WARN, "[SIPre-%s] Got a '%s' on the video RTCP socket, closing it\n",
3001
                                                        session->account.username, strerror(error));
3002
                                                close(session->media.video_rtcp_fd);
3003
                                                session->media.video_rtcp_fd = -1;
3004
                                        }
3005
                                        /* FIXME Should we do the same with the RTP sockets as well? We may risk overreacting, there... */
3006
                                        continue;
3007
                                }
3008
                                JANUS_LOG(LOG_ERR, "[SIPre-%s] Error polling %d (socket #%d): %s...\n", session->account.username,
3009
                                        fds[i].fd, i, fds[i].revents & POLLERR ? "POLLERR" : "POLLHUP");
3010
                                JANUS_LOG(LOG_ERR, "[SIPre-%s]   -- %d (%s)\n", session->account.username, error, strerror(error));
3011
                                /* Can we assume it's pretty much over, after a POLLERR? */
3012
                                goon = FALSE;
3013
                                /* FIXME Simulate a "hangup" coming from the browser */
3014
                                janus_sipre_message *msg = g_malloc0(sizeof(janus_sipre_message));
3015
                                msg->handle = session->handle;
3016
                                msg->message = json_pack("{ss}", "request", "hangup");
3017
                                msg->transaction = NULL;
3018
                                msg->jsep = NULL;
3019
                                g_async_queue_push(messages, msg);
3020
                                break;
3021
                        } else if(fds[i].revents & POLLIN) {
3022
                                if(pipe_fd != -1 && fds[i].fd == pipe_fd) {
3023
                                        /* Poll interrupted for a reason, go on */
3024
                                        int code = 0;
3025
                                        bytes = read(pipe_fd, &code, sizeof(int));
3026
                                        break;
3027
                                }
3028
                                /* Got an RTP/RTCP packet */
3029
                                addrlen = sizeof(remote);
3030
                                bytes = recvfrom(fds[i].fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
3031
                                /* Let's check what this is */
3032
                                gboolean video = fds[i].fd == session->media.video_rtp_fd || fds[i].fd == session->media.video_rtcp_fd;
3033
                                gboolean rtcp = fds[i].fd == session->media.audio_rtcp_fd || fds[i].fd == session->media.video_rtcp_fd;
3034
                                if(!rtcp) {
3035
                                        /* Audio or Video RTP */
3036
                                        rtp_header *header = (rtp_header *)buffer;
3037
                                        if((video && session->media.video_ssrc_peer != ntohl(header->ssrc)) ||
3038
                                                        (!video && session->media.audio_ssrc_peer != ntohl(header->ssrc))) {
3039
                                                if(video) {
3040
                                                        session->media.video_ssrc_peer = ntohl(header->ssrc);
3041
                                                } else {
3042
                                                        session->media.audio_ssrc_peer = ntohl(header->ssrc);
3043
                                                }
3044
                                                JANUS_LOG(LOG_VERB, "[SIPre-%s] Got SIP peer %s SSRC: %"SCNu32"\n",
3045
                                                        session->account.username ? session->account.username : "unknown",
3046
                                                        video ? "video" : "audio", session->media.audio_ssrc_peer);
3047
                                        }
3048
                                        /* Is this SRTP? */
3049
                                        if(session->media.has_srtp_remote) {
3050
                                                int buflen = bytes;
3051
                                                srtp_err_status_t res = srtp_unprotect(
3052
                                                        (video ? session->media.video_srtp_in : session->media.audio_srtp_in),
3053
                                                        buffer, &buflen);
3054
                                                if(res != srtp_err_status_ok && res != srtp_err_status_replay_fail && res != srtp_err_status_replay_old) {
3055
                                                        guint32 timestamp = ntohl(header->timestamp);
3056
                                                        guint16 seq = ntohs(header->seq_number);
3057
                                                        JANUS_LOG(LOG_ERR, "[SIPre-%s] %s SRTP unprotect error: %s (len=%d-->%d, ts=%"SCNu32", seq=%"SCNu16")\n",
3058
                                                                session->account.username ? session->account.username : "unknown",
3059
                                                                video ? "Video" : "Audio", janus_srtp_error_str(res), bytes, buflen, timestamp, seq);
3060
                                                        continue;
3061
                                                }
3062
                                                bytes = buflen;
3063
                                        }
3064
                                        /* Check if the SSRC changed (e.g., after a re-INVITE or UPDATE) */
3065
                                        guint32 timestamp = ntohl(header->timestamp);
3066
                                        janus_rtp_header_update(header, &session->media.context, video,
3067
                                                (video ? (vstep ? vstep : 4500) : (astep ? astep : 960)));
3068
                                        if(video) {
3069
                                                if(vts == 0) {
3070
                                                        vts = timestamp;
3071
                                                } else if(vstep == 0) {
3072
                                                        vstep = timestamp-vts;
3073
                                                        if(vstep < 0) {
3074
                                                                vstep = 0;
3075
                                                        }
3076
                                                }
3077
                                        } else {
3078
                                                if(ats == 0) {
3079
                                                        ats = timestamp;
3080
                                                } else if(astep == 0) {
3081
                                                        astep = timestamp-ats;
3082
                                                        if(astep < 0) {
3083
                                                                astep = 0;
3084
                                                        }
3085
                                                }
3086
                                        }
3087
                                        /* Save the frame if we're recording */
3088
                                        janus_recorder_save_frame(video ? session->vrc_peer : session->arc_peer, buffer, bytes);
3089
                                        /* Relay to browser */
3090
                                        gateway->relay_rtp(session->handle, video, buffer, bytes);
3091
                                        continue;
3092
                                } else {
3093
                                        /* Audio or Video RTCP */
3094
                                        if(session->media.has_srtp_remote) {
3095
                                                int buflen = bytes;
3096
                                                srtp_err_status_t res = srtp_unprotect_rtcp(
3097
                                                        (video ? session->media.video_srtp_in : session->media.audio_srtp_in),
3098
                                                        buffer, &buflen);
3099
                                                if(res != srtp_err_status_ok && res != srtp_err_status_replay_fail && res != srtp_err_status_replay_old) {
3100
                                                        JANUS_LOG(LOG_ERR, "[SIPre-%s] %s SRTCP unprotect error: %s (len=%d-->%d)\n",
3101
                                                                session->account.username ? session->account.username : "unknown",
3102
                                                                video ? "Video" : "Audio", janus_srtp_error_str(res), bytes, buflen);
3103
                                                        continue;
3104
                                                }
3105
                                                bytes = buflen;
3106
                                        }
3107
                                        /* Relay to browser */
3108
                                        gateway->relay_rtcp(session->handle, video, buffer, bytes);
3109
                                        continue;
3110
                                }
3111
                        }
3112
                }
3113
        }
3114
        if(session->media.audio_rtp_fd != -1) {
3115
                close(session->media.audio_rtp_fd);
3116
                session->media.audio_rtp_fd = -1;
3117
        }
3118
        if(session->media.audio_rtcp_fd != -1) {
3119
                close(session->media.audio_rtcp_fd);
3120
                session->media.audio_rtcp_fd = -1;
3121
        }
3122
        session->media.local_audio_rtp_port = 0;
3123
        session->media.local_audio_rtcp_port = 0;
3124
        session->media.audio_ssrc = 0;
3125
        if(session->media.video_rtp_fd != -1) {
3126
                close(session->media.video_rtp_fd);
3127
                session->media.video_rtp_fd = -1;
3128
        }
3129
        if(session->media.video_rtcp_fd != -1) {
3130
                close(session->media.video_rtcp_fd);
3131
                session->media.video_rtcp_fd = -1;
3132
        }
3133
        session->media.local_video_rtp_port = 0;
3134
        session->media.local_video_rtcp_port = 0;
3135
        session->media.video_ssrc = 0;
3136
        if(session->media.pipefd[0] > 0) {
3137
                close(session->media.pipefd[0]);
3138
                session->media.pipefd[0] = -1;
3139
        }
3140
        if(session->media.pipefd[1] > 0) {
3141
                close(session->media.pipefd[1]);
3142
                session->media.pipefd[1] = -1;
3143
        }
3144
        /* Clean up SRTP stuff, if needed */
3145
        janus_sipre_srtp_cleanup(session);
3146
        /* Done */
3147
        JANUS_LOG(LOG_VERB, "Leaving SIPre relay thread\n");
3148
        g_thread_unref(g_thread_self());
3149
        return NULL;
3150
}
3151

    
3152

    
3153
/* libre loop thread */
3154
gpointer janus_sipre_stack_thread(gpointer user_data) {
3155
        JANUS_LOG(LOG_INFO, "Joining libre loop thread...\n");
3156

    
3157
        /* Setup libre */
3158
        int err = libre_init();
3159
        if(err) {
3160
                JANUS_LOG(LOG_ERR, "libre_init() failed: %d (%s)\n", err, strerror(err));
3161
                goto done;
3162
        }
3163
        /* Initialize this thread as a worker */
3164
        err = re_thread_init();
3165
        if(err != 0) {
3166
                printf("re_thread_init failed: %d (%s)\n", err, strerror(err));
3167
                goto done;
3168
        }
3169
        err = mqueue_alloc(&mq, janus_sipre_mqueue_handler, NULL);
3170
        if(err) {
3171
                JANUS_LOG(LOG_ERR, "Failed to initialize message queue: %d (%s)\n", err, strerror(err));
3172
                goto done;
3173
        }
3174
        g_atomic_int_set(&libre_inited, 1);
3175

    
3176
        /* Enter loop */
3177
        err = re_main(NULL);
3178
        if(err != 0) {
3179
                JANUS_LOG(LOG_ERR, "re_main() failed: %d (%s)\n", err, strerror(err));
3180
        }
3181

    
3182
        /* Done here */
3183
        JANUS_LOG(LOG_INFO, "Leaving libre loop thread...\n");
3184
        re_thread_close();
3185
        /* Deinitialize libre */
3186
        libre_close();
3187

    
3188
done:
3189
        g_atomic_int_set(&libre_inited, -1);
3190
        return NULL;
3191
}
3192

    
3193
/* Called when challenged for credentials */
3194
int janus_sipre_cb_auth(char **user, char **pass, const char *realm, void *arg) {
3195
        janus_sipre_session *session = (janus_sipre_session *)arg;
3196
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] janus_sipre_cb_auth (realm=%s)\n", session->account.username, realm);
3197
        /* TODO How do we handle hashed secrets? */
3198
        int err = 0;
3199
        err |= str_dup(user, session->account.authuser);
3200
        err |= str_dup(pass, session->account.secret);
3201
        JANUS_LOG(LOG_HUGE, "[SIPre-%s]   -- %s / %s\n", session->account.username, *user, *pass);
3202
        return err;
3203
}
3204

    
3205
/* Called when REGISTER responses are received */
3206
void janus_sipre_cb_register(int err, const struct sip_msg *msg, void *arg) {
3207
        janus_sipre_session *session = (janus_sipre_session *)arg;
3208
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] janus_sipre_cb_register\n", session->account.username);
3209
        if(err) {
3210
                JANUS_LOG(LOG_ERR, "[SIPre-%s] REGISTER error: %s\n", session->account.username, strerror(err));
3211
                /* FIXME Should we send an event here? */
3212
        } else {
3213
                const char *event_name = (session->stack.expires > 0 ? "registered" : "unregistered");
3214
                JANUS_LOG(LOG_VERB, "[SIPre-%s] REGISTER reply: %u\n", session->account.username, msg->scode);
3215
                if(msg->scode == 200) {
3216
                        if(session->stack.expires > 0) {
3217
                                if(session->account.registration_status < janus_sipre_registration_status_registered)
3218
                                        session->account.registration_status = janus_sipre_registration_status_registered;
3219
                        } else {
3220
                                session->account.registration_status = janus_sipre_registration_status_unregistered;
3221
                        }
3222
                        /* Notify the browser */
3223
                        json_t *call = json_object();
3224
                        json_object_set_new(call, "sip", json_string("event"));
3225
                        json_t *calling = json_object();
3226
                        json_object_set_new(calling, "event", json_string(event_name));
3227
                        json_object_set_new(calling, "username", json_string(session->account.username));
3228
                        json_object_set_new(calling, "register_sent", json_true());
3229
                        json_object_set_new(call, "result", calling);
3230
                        if(!session->destroyed) {
3231
                                int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, call, NULL);
3232
                                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3233
                        }
3234
                        json_decref(call);
3235
                        /* Also notify event handlers */
3236
                        if(notify_events && gateway->events_is_enabled()) {
3237
                                json_t *info = json_object();
3238
                                json_object_set_new(info, "event", json_string(event_name));
3239
                                json_object_set_new(info, "identity", json_string(session->account.identity));
3240
                                if(session->account.proxy)
3241
                                        json_object_set_new(info, "proxy", json_string(session->account.proxy));
3242
                                gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3243
                        }
3244
                } else {
3245
                        /* Authentication failed? */
3246
                        session->account.registration_status = janus_sipre_registration_status_failed;
3247
                        mem_deref(session->stack.reg);
3248
                        session->stack.reg = NULL;
3249
                        /* Tell the browser... */
3250
                        json_t *event = json_object();
3251
                        json_object_set_new(event, "sip", json_string("event"));
3252
                        json_t *result = json_object();
3253
                        json_object_set_new(result, "event", json_string("registration_failed"));
3254
                        json_object_set_new(result, "code", json_integer(msg->scode));
3255
                        char reason[256];
3256
                        reason[0] = '\0';
3257
                        if(msg->reason.l > 0) {
3258
                                g_snprintf(reason, (msg->reason.l < 255 ? msg->reason.l+1 : 255), "%s", msg->reason.p);
3259
                                json_object_set_new(result, "reason", json_string(reason));
3260
                        }
3261
                        json_object_set_new(event, "result", result);
3262
                        if(!session->destroyed) {
3263
                                int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, event, NULL);
3264
                                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3265
                        }
3266
                        json_decref(event);
3267
                        /* Also notify event handlers */
3268
                        if(notify_events && gateway->events_is_enabled()) {
3269
                                json_t *info = json_object();
3270
                                json_object_set_new(info, "event", json_string("registration_failed"));
3271
                                json_object_set_new(info, "code", json_integer(msg->scode));
3272
                                if(msg->reason.l > 0) {
3273
                                        json_object_set_new(info, "reason", json_string(reason));
3274
                                }
3275
                                gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3276
                        }
3277
                }
3278
        }
3279
}
3280

    
3281
/* Called when SIP progress (e.g., 180 Ringing or 183 Session Progress) responses are received */
3282
void janus_sipre_cb_progress(const struct sip_msg *msg, void *arg) {
3283
        janus_sipre_session *session = (janus_sipre_session *)arg;
3284
        char reason[256];
3285
        reason[0] = '\0';
3286
        if(msg->reason.l > 0) {
3287
                g_snprintf(reason, (msg->reason.l < 255 ? msg->reason.l+1 : 255), "%s", msg->reason.p);
3288
        }
3289
        /* Not ready yet, either notify the user (e.g., "ringing") or handle early media (if it's a 183) */
3290
        JANUS_LOG(LOG_WARN, "[SIPre-%s] Session progress: %u %s\n", session->account.username, msg->scode, reason);
3291
        if(msg->scode == 180) {
3292
                /* Ringing, notify the application */
3293
                json_t *ringing = json_object();
3294
                json_object_set_new(ringing, "sip", json_string("event"));
3295
                json_t *result = json_object();
3296
                json_object_set_new(result, "event", json_string("ringing"));
3297
                json_object_set_new(ringing, "result", result);
3298
                int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, ringing, NULL);
3299
                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3300
                json_decref(ringing);
3301
        } else if(msg->scode == 183) {
3302
                /* If's a Session Progress: check if there's an SDP, and if so, treat it like a 200 */
3303
                (void)janus_sipre_cb_answer(msg, arg);
3304
        }
3305
}
3306

    
3307
/* Called upon incoming INVITEs */
3308
void janus_sipre_cb_incoming(const struct sip_msg *msg, void *arg) {
3309
        janus_sipre_session *session = (janus_sipre_session *)arg;
3310
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] janus_sipre_cb_incoming (%p)\n", session->account.username, session);
3311
        /* Increase the reference to the msg instance, as we'll need it either
3312
         * to reply with an error right away, or for a success/error later */
3313
        mem_ref((struct sip_msg *)msg);
3314
        /* Parse a few relevant identifiers */
3315
        char *from = NULL;
3316
        re_sdprintf(&from, "%H", uri_encode, &msg->from.uri);
3317
        JANUS_LOG(LOG_HUGE, "[SIPre-%s]   -- Caller: %s\n", session->account.username, from);
3318
        char dname[256];
3319
        dname[0] = '\0';
3320
        if(msg->from.dname.l > 0) {
3321
                g_snprintf(dname, sizeof(dname), "%.*s", (int)msg->from.dname.l, msg->from.dname.p);
3322
                JANUS_LOG(LOG_HUGE, "[SIPre-%s]   -- Display: %s\n", session->account.username, dname);
3323
        }
3324
        char callid[256];
3325
        g_snprintf(callid, sizeof(callid), "%.*s", (int)msg->callid.l, msg->callid.p);
3326
        JANUS_LOG(LOG_HUGE, "[SIPre-%s]   -- Call-ID: %s\n", session->account.username, callid);
3327
        /* Make sure we're not in a call already */
3328
        if(session->stack.sess != NULL) {
3329
                /* Already in a call */
3330
                JANUS_LOG(LOG_VERB, "Already in a call (busy, status=%s)\n", janus_sipre_call_status_string(session->status));
3331
                mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 486, session));
3332
                /* Notify the web app about the missed invite */
3333
                json_t *missed = json_object();
3334
                json_object_set_new(missed, "sip", json_string("event"));
3335
                json_t *result = json_object();
3336
                json_object_set_new(result, "event", json_string("missed_call"));
3337
                json_object_set_new(result, "caller", json_string(from));
3338
                if(strlen(dname)) {
3339
                        json_object_set_new(result, "displayname", json_string(dname));
3340
                }
3341
                json_object_set_new(missed, "result", result);
3342
                if(!session->destroyed) {
3343
                        int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, missed, NULL);
3344
                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3345
                }
3346
                json_decref(missed);
3347
                /* Also notify event handlers */
3348
                if(notify_events && gateway->events_is_enabled()) {
3349
                        json_t *info = json_object();
3350
                        json_object_set_new(info, "event", json_string("missed_call"));
3351
                        json_object_set_new(info, "caller", json_string(from));
3352
                        gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3353
                }
3354
                return;
3355
        }
3356
        /* New incoming call, check if there's an SDP to process */
3357
        char sdp_offer[1024];
3358
        janus_sdp *sdp = NULL;
3359
        const char *offer = (const char *)mbuf_buf(msg->mb);
3360
        if(offer == NULL || mbuf_get_left(msg->mb) == 0) {
3361
                JANUS_LOG(LOG_WARN, "[SIPre-%s] Received offerless INVITE\n", session->account.username);
3362
        } else {
3363
                g_snprintf(sdp_offer, sizeof(sdp_offer), "%.*s", (int)mbuf_get_left(msg->mb), offer);
3364
                JANUS_LOG(LOG_WARN, "[SIPre-%s]   -- Offer: %s\n", session->account.username, sdp_offer);
3365
                /* Parse the remote SDP */
3366
                char sdperror[100];
3367
                sdp = janus_sdp_parse(sdp_offer, sdperror, sizeof(sdperror));
3368
                if(!sdp) {
3369
                        JANUS_LOG(LOG_ERR, "Error parsing SDP! %s\n", sdperror);
3370
                        mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
3371
                        return;
3372
                }
3373
        }
3374
        session->callee = g_strdup(from);
3375
        session->callid = g_strdup(callid);
3376
        g_hash_table_insert(callids, session->callid, session);
3377
        session->status = janus_sipre_call_status_invited;
3378
        /* Clean up SRTP stuff from before first, in case it's still needed */
3379
        janus_sipre_srtp_cleanup(session);
3380
        /* Parse SDP */
3381
        JANUS_LOG(LOG_VERB, "Someone is inviting us a call\n");
3382
        if(sdp) {
3383
                gboolean changed = FALSE;
3384
                janus_sipre_sdp_process(session, sdp, FALSE, FALSE, &changed);
3385
                /* Check if offer has neither audio nor video, fail with 488 */
3386
                if(!session->media.has_audio && !session->media.has_video) {
3387
                        mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
3388
                        janus_sdp_free(sdp);
3389
                        return;
3390
                }
3391
                /* Also fail with 488 if there's no remote IP address that can be used for RTP */
3392
                if(!session->media.remote_ip) {
3393
                        mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
3394
                        janus_sdp_free(sdp);
3395
                        return;
3396
                }
3397
        }
3398
        session->stack.invite = msg;
3399
        /* Notify the browser about the call */
3400
        json_t *jsep = NULL;
3401
        if(sdp)
3402
                jsep = json_pack("{ssss}", "type", "offer", "sdp", sdp_offer);
3403
        json_t *call = json_object();
3404
        json_object_set_new(call, "sip", json_string("event"));
3405
        json_t *calling = json_object();
3406
        json_object_set_new(calling, "event", json_string("incomingcall"));
3407
        json_object_set_new(calling, "username", json_string(session->callee));
3408
        if(strlen(dname)) {
3409
                json_object_set_new(calling, "displayname", json_string(dname));
3410
        }
3411
        if(sdp && session->media.has_srtp_remote) {
3412
                /* FIXME Maybe a true/false instead? */
3413
                json_object_set_new(calling, "srtp", json_string(session->media.require_srtp ? "sdes_mandatory" : "sdes_optional"));
3414
        }
3415
        json_object_set_new(call, "result", calling);
3416
        if(!session->destroyed) {
3417
                int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, call, jsep);
3418
                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3419
        }
3420
        json_decref(call);
3421
        if(jsep)
3422
                json_decref(jsep);
3423
        janus_sdp_free(sdp);
3424
        /* Also notify event handlers */
3425
        if(notify_events && gateway->events_is_enabled()) {
3426
                json_t *info = json_object();
3427
                json_object_set_new(info, "event", json_string("incomingcall"));
3428
                if(session->callid)
3429
                        json_object_set_new(info, "call-id", json_string(session->callid));
3430
                json_object_set_new(info, "username", json_string(session->callee));
3431
                if(strlen(dname))
3432
                        json_object_set_new(info, "displayname", json_string(dname));
3433
                gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3434
        }
3435
        /* Send a Ringing back */
3436
        mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 180, NULL));
3437
}
3438

    
3439
/* Called when an SDP offer is received (re-INVITE) */
3440
int janus_sipre_cb_offer(struct mbuf **mbp, const struct sip_msg *msg, void *arg) {
3441
        janus_sipre_session *session = (janus_sipre_session *)arg;
3442
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] janus_sipre_cb_offer\n", session->account.username);
3443
        /* Get the SDP */
3444
        const char *offer = (const char *)mbuf_buf(msg->mb);
3445
        if(offer == NULL) {
3446
                /* No SDP? */
3447
                JANUS_LOG(LOG_WARN, "[SIPre-%s] No SDP in the re-INVITE?\n", session->account.username);
3448
                return EINVAL;
3449
        }
3450
        char sdp_offer[1024];
3451
        g_snprintf(sdp_offer, sizeof(sdp_offer), "%.*s", (int)mbuf_get_left(msg->mb), offer);
3452
        JANUS_LOG(LOG_VERB, "Someone is updating a call:\n%s", sdp_offer);
3453
        /* Parse the remote SDP */
3454
        char sdperror[100];
3455
        janus_sdp *sdp = janus_sdp_parse(sdp_offer, sdperror, sizeof(sdperror));
3456
        if(!sdp) {
3457
                JANUS_LOG(LOG_ERR, "Error parsing SDP! %s\n", sdperror);
3458
                return EINVAL;
3459
        }
3460
        gboolean changed = FALSE;
3461
        janus_sipre_sdp_process(session, sdp, FALSE, TRUE, &changed);
3462
        janus_sdp_free(sdp);
3463
        /* Check if offer has neither audio nor video, fail with 488 */
3464
        if (!session->media.has_audio && !session->media.has_video) {
3465
                mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
3466
                return EINVAL;
3467
        }
3468
        /* Also fail with 488 if there's no remote IP address that can be used for RTP */
3469
        if (!session->media.remote_ip) {
3470
                mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
3471
                return EINVAL;
3472
        }
3473
        char *answer = janus_sdp_write(session->sdp);
3474
        JANUS_LOG(LOG_VERB, "Answering re-INVITE:\n%s", answer);
3475
        *mbp = mbuf_alloc(strlen(answer)+1);
3476
        mbuf_printf(*mbp, "%s", answer);
3477
        mbuf_set_pos(*mbp, 0);
3478
        return 0;
3479
}
3480

    
3481

    
3482
/* Called when an SDP answer is received */
3483
int janus_sipre_cb_answer(const struct sip_msg *msg, void *arg) {
3484
        janus_sipre_session *session = (janus_sipre_session *)arg;
3485
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] janus_sipre_cb_answer\n", session->account.username);
3486
        gboolean in_progress = FALSE;
3487
        if(msg->scode == 183)
3488
                in_progress = TRUE;
3489
        /* Get the SDP */
3490
        const char *answer = (const char *)mbuf_buf(msg->mb);
3491
        if(answer == NULL) {
3492
                /* No SDP? */
3493
                if(in_progress) {
3494
                        /* This was a 183, so we don't care */
3495
                        return 0;
3496
                }
3497
                JANUS_LOG(LOG_WARN, "[SIPre-%s] No SDP in the answer?\n", session->account.username);
3498
                return EINVAL;
3499
        }
3500
        char sdp_answer[1024];
3501
        g_snprintf(sdp_answer, sizeof(sdp_answer), "%.*s", (int)mbuf_get_left(msg->mb), answer);
3502
        /* Parse the SDP */
3503
        char sdperror[100];
3504
        janus_sdp *sdp = janus_sdp_parse(sdp_answer, sdperror, sizeof(sdperror));
3505
        if(!sdp) {
3506
                JANUS_LOG(LOG_ERR, "Error parsing SDP! %s\n", sdperror);
3507
                return EINVAL;
3508
        }
3509
        /* Parse SDP */
3510
        JANUS_LOG(LOG_VERB, "Peer accepted our call:\n%s", sdp_answer);
3511
        session->status = janus_sipre_call_status_incall;
3512
        gboolean changed = FALSE;
3513
        gboolean update = session->media.ready;
3514
        janus_sipre_sdp_process(session, sdp, TRUE, update, &changed);
3515
        /* If we asked for SRTP and are not getting it, fail */
3516
        if(session->media.require_srtp && !session->media.has_srtp_remote) {
3517
                JANUS_LOG(LOG_ERR, "We asked for mandatory SRTP but didn't get any in the reply!\n");
3518
                janus_sdp_free(sdp);
3519
                /* Hangup immediately */
3520
                session->media.earlymedia = FALSE;
3521
                session->media.ready = FALSE;
3522
                session->media.on_hold = FALSE;
3523
                session->status = janus_sipre_call_status_closing;
3524
                mqueue_push(mq, janus_sipre_mqueue_event_do_bye, janus_sipre_mqueue_payload_create(session, msg, 0, NULL));
3525
                g_free(session->callee);
3526
                session->callee = NULL;
3527
                return EINVAL;
3528
        }
3529
        if(!session->media.remote_ip) {
3530
                /* No remote address parsed? Give up */
3531
                JANUS_LOG(LOG_ERR, "No remote IP address found for RTP, something's wrong with the SDP!\n");
3532
                janus_sdp_free(sdp);
3533
                /* Hangup immediately */
3534
                session->media.earlymedia = FALSE;
3535
                session->media.ready = FALSE;
3536
                session->media.on_hold = FALSE;
3537
                session->status = janus_sipre_call_status_closing;
3538
                mqueue_push(mq, janus_sipre_mqueue_event_do_bye, janus_sipre_mqueue_payload_create(session, msg, 0, NULL));
3539
                g_free(session->callee);
3540
                session->callee = NULL;
3541
                return EINVAL;
3542
        }
3543
        if(session->media.audio_pt > -1) {
3544
                session->media.audio_pt_name = janus_get_codec_from_pt(sdp_answer, session->media.audio_pt);
3545
                JANUS_LOG(LOG_VERB, "Detected audio codec: %d (%s)\n", session->media.audio_pt, session->media.audio_pt_name);
3546
        }
3547
        if(session->media.video_pt > -1) {
3548
                session->media.video_pt_name = janus_get_codec_from_pt(sdp_answer, session->media.video_pt);
3549
                JANUS_LOG(LOG_VERB, "Detected video codec: %d (%s)\n", session->media.video_pt, session->media.video_pt_name);
3550
        }
3551
        session->media.ready = TRUE;        /* FIXME Maybe we need a better way to signal this */
3552
        if(update && !session->media.earlymedia) {
3553
                /* Don't push to the browser if this is in response to a hold/unhold we sent ourselves */
3554
                JANUS_LOG(LOG_WARN, "This is an update to an existing call (possibly in response to hold/unhold)\n");
3555
                return 0;
3556
        }
3557
        if(!session->media.earlymedia) {
3558
                GError *error = NULL;
3559
                char tname[16];
3560
                g_snprintf(tname, sizeof(tname), "siprertp %s", session->account.username);
3561
                g_thread_try_new(tname, janus_sipre_relay_thread, session, &error);
3562
                if(error != NULL) {
3563
                        JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the RTP/RTCP thread...\n", error->code, error->message ? error->message : "??");
3564
                }
3565
        }
3566
        /* Send event back to the browser */
3567
        json_t *jsep = NULL;
3568
        if(!session->media.earlymedia) {
3569
                jsep = json_pack("{ssss}", "type", "answer", "sdp", sdp_answer);
3570
        } else {
3571
                /* We've received the 200 OK after the 183, we can remove the flag now */
3572
                session->media.earlymedia = FALSE;
3573
        }
3574
        if(in_progress) {
3575
                /* If we just received the 183, set the flag instead so that we can handle the 200 OK differently */
3576
                session->media.earlymedia = TRUE;
3577
        }
3578
        json_t *call = json_object();
3579
        json_object_set_new(call, "sip", json_string("event"));
3580
        json_t *calling = json_object();
3581
        json_object_set_new(calling, "event", json_string(in_progress ? "progress" : "accepted"));
3582
        json_object_set_new(calling, "username", json_string(session->callee));
3583
        json_object_set_new(call, "result", calling);
3584
        if(!session->destroyed) {
3585
                int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, call, jsep);
3586
                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3587
        }
3588
        json_decref(call);
3589
        json_decref(jsep);
3590
        janus_sdp_free(sdp);
3591
        /* Also notify event handlers */
3592
        if(notify_events && gateway->events_is_enabled()) {
3593
                json_t *info = json_object();
3594
                json_object_set_new(info, "event", json_string(in_progress ? "progress" : "accepted"));
3595
                if(session->callid)
3596
                        json_object_set_new(info, "call-id", json_string(session->callid));
3597
                json_object_set_new(info, "username", json_string(session->callee));
3598
                gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3599
        }
3600

    
3601
        return 0;
3602
}
3603

    
3604
/* Called when the session is established */
3605
void janus_sipre_cb_established(const struct sip_msg *msg, void *arg) {
3606
        janus_sipre_session *session = (janus_sipre_session *)arg;
3607
        if(session == NULL) {
3608
                JANUS_LOG(LOG_WARN, "[SIPre-??] janus_sipre_cb_established\n");
3609
                return;
3610
        }
3611
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] janus_sipre_cb_established\n", session->account.username);
3612
        /* FIXME Anything to do here? */
3613
}
3614

    
3615
/* Called when an incoming SIP INFO arrives */
3616
void janus_sipre_cb_info(struct sip *sip, const struct sip_msg *msg, void *arg) {
3617
        janus_sipre_session *session = (janus_sipre_session *)arg;
3618
        if(session == NULL) {
3619
                JANUS_LOG(LOG_WARN, "[SIPre-??] janus_sipre_cb_info\n");
3620
                return;
3621
        }
3622
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] janus_sipre_cb_info\n", session->account.username);
3623
        char *from = NULL;
3624
        re_sdprintf(&from, "%H", uri_encode, &msg->from.uri);
3625
        JANUS_LOG(LOG_HUGE, "[SIPre-%s]   -- Sender: %s\n", session->account.username, from);
3626
        char dname[256];
3627
        dname[0] = '\0';
3628
        if(msg->from.dname.l > 0) {
3629
                g_snprintf(dname, sizeof(dname), "%.*s", (int)msg->from.dname.l, msg->from.dname.p);
3630
                JANUS_LOG(LOG_HUGE, "[SIPre-%s]   -- Display: %s\n", session->account.username, dname);
3631
        }
3632
        char type[200];
3633
        type[0] = '\0';
3634
        if(msg->ctyp.type.l > 0) {
3635
                g_snprintf(type, sizeof(type), "%.*s", (int)msg->ctyp.type.l, msg->ctyp.type.p);
3636
                JANUS_LOG(LOG_HUGE, "[SIPre-%s]   -- Type: %s\n", session->account.username, type);
3637
        }
3638
        const char *payload = (const char *)mbuf_buf(msg->mb);
3639
        char content[1024];
3640
        g_snprintf(content, sizeof(content), "%.*s", (int)mbuf_get_left(msg->mb), payload);
3641
        JANUS_LOG(LOG_HUGE, "[SIPre-%s]   -- Content: %s\n", session->account.username, content);
3642
        /* Notify the application */
3643
        json_t *info = json_object();
3644
        json_object_set_new(info, "sip", json_string("event"));
3645
        json_t *result = json_object();
3646
        json_object_set_new(result, "event", json_string("info"));
3647
        json_object_set_new(result, "sender", json_string(from));
3648
        if(strlen(dname)) {
3649
                json_object_set_new(result, "displayname", json_string(dname));
3650
        }
3651
        json_object_set_new(result, "type", json_string(type));
3652
        json_object_set_new(result, "content", json_string(content));
3653
        json_object_set_new(info, "result", result);
3654
        int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, info, NULL);
3655
        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3656
        json_decref(info);
3657
        /* Send a 200 back */
3658
        mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 200, session));
3659
}
3660

    
3661
/* Called when the session fails to connect or is terminated by the peer */
3662
void janus_sipre_cb_closed(int err, const struct sip_msg *msg, void *arg) {
3663
        janus_sipre_session *session = (janus_sipre_session *)arg;
3664
        if(session == NULL) {
3665
                JANUS_LOG(LOG_HUGE, "[SIPre-??] janus_sipre_cb_closed\n");
3666
                return;
3667
        }
3668
        if(err) {
3669
                JANUS_LOG(LOG_VERB, "[SIPre-%s] Session closed: %d %s\n", session->account.username, err, strerror(err));
3670
        } else {
3671
                JANUS_LOG(LOG_VERB, "[SIPre-%s] Session closed: %u %s\n", session->account.username, msg->scode, (char *)&msg->reason.p);
3672
        }
3673

    
3674
        /* Tell the browser... */
3675
        json_t *event = json_object();
3676
        json_object_set_new(event, "sip", json_string("event"));
3677
        json_t *result = json_object();
3678
        json_object_set_new(result, "event", json_string("hangup"));
3679
        json_object_set_new(result, "code", json_integer(err ? err : msg->scode));
3680
        char reason[256];
3681
        reason[0] = '\0';
3682
        if(!err && msg->reason.l > 0) {
3683
                g_snprintf(reason, (msg->reason.l < 255 ? msg->reason.l+1 : 255), "%s", msg->reason.p);
3684
        }
3685
        json_object_set_new(result, "reason", json_string(err ? strerror(err) : reason));
3686
        json_object_set_new(event, "result", result);
3687
        if(!session->destroyed) {
3688
                int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, event, NULL);
3689
                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3690
        }
3691
        json_decref(event);
3692
        /* Also notify event handlers */
3693
        if(notify_events && gateway->events_is_enabled()) {
3694
                json_t *info = json_object();
3695
                json_object_set_new(info, "event", json_string("hangup"));
3696
                json_object_set_new(info, "code", json_integer(err ? err : msg->scode));
3697
                json_object_set_new(info, "reason", json_string(err ? strerror(err) : reason));
3698
                gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3699
        }
3700

    
3701
        /* Cleanup */
3702
        mem_deref(session->stack.sess);
3703
        session->stack.sess = NULL;
3704
        session->media.earlymedia = FALSE;
3705
        session->media.ready = FALSE;
3706
        session->media.on_hold = FALSE;
3707
        session->status = janus_sipre_call_status_idle;
3708
}
3709

    
3710
/* Called when all SIP transactions are completed */
3711
void janus_sipre_cb_exit(void *arg) {
3712
        janus_sipre_session *session = (janus_sipre_session *)arg;
3713
        if(session == NULL) {
3714
                JANUS_LOG(LOG_HUGE, "[SIPre-??] janus_sipre_cb_exit\n");
3715
                return;
3716
        }
3717
        JANUS_LOG(LOG_INFO, "[SIPre-%s] Cleaning SIP stack\n", session->account.username);
3718
}
3719

    
3720
/* Callback to implement SIP requests in the re_main loop thread */
3721
void janus_sipre_mqueue_handler(int id, void *data, void *arg) {
3722
        JANUS_LOG(LOG_HUGE, "janus_sipre_mqueue_handler: %d (%s)\n", id, janus_sipre_mqueue_event_string((janus_sipre_mqueue_event)id));
3723
        switch((janus_sipre_mqueue_event)id) {
3724
                case janus_sipre_mqueue_event_do_init: {
3725
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3726
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3727
                        /* We need a DNS client */
3728
                        struct sa nsv[8];
3729
                        uint32_t nsn = ARRAY_SIZE(nsv);
3730
                        int err = dns_srv_get(NULL, 0, nsv, &nsn);
3731
                        if(err) {
3732
                                JANUS_LOG(LOG_ERR, "Failed to get the DNS servers list for the SIP stack: %d (%s)\n", err, strerror(err));
3733
                                g_free(payload);
3734
                                return;
3735
                        }
3736
                        err = dnsc_alloc(&session->stack.dns_client, NULL, nsv, nsn);
3737
                        if(err) {
3738
                                JANUS_LOG(LOG_ERR, "Failed to initialize the DNS client for the SIP stack: %d (%s)\n", err, strerror(err));
3739
                                g_free(payload);
3740
                                return;
3741
                        }
3742
                        /* Let's allocate the stack now */
3743
                        err = sip_alloc(&session->stack.sipstack, session->stack.dns_client, 32, 32, 32,
3744
                                (user_agent ? user_agent : JANUS_SIPRE_NAME), janus_sipre_cb_exit, session);
3745
                        if(err) {
3746
                                JANUS_LOG(LOG_ERR, "Failed to initialize libre SIP stack: %d (%s)\n", err, strerror(err));
3747
                                mem_deref(session->stack.dns_client);
3748
                                session->stack.dns_client = NULL;
3749
                                g_free(payload);
3750
                                return;
3751
                        }
3752
                        JANUS_LOG(LOG_INFO, "Initializing SIP transports\n");
3753
                        struct sa laddr, laddrs;
3754
                        sa_set_str(&laddr, local_ip, 0);
3755
                        sa_set_str(&laddrs, local_ip, 0);
3756
                        err = 0;
3757
                        err |= sip_transp_add(session->stack.sipstack, SIP_TRANSP_UDP, &laddr);
3758
                        err |= sip_transp_add(session->stack.sipstack, SIP_TRANSP_TCP, &laddr);
3759
                        if(err) {
3760
                                JANUS_LOG(LOG_ERR, "Failed to initialize libre SIP transports: %d (%s)\n", err, strerror(err));
3761
                                g_free(payload);
3762
                                return;
3763
                        }
3764
                        err = tls_alloc(&session->stack.tls, TLS_METHOD_SSLV23, NULL, NULL);
3765
                        err |= sip_transp_add(session->stack.sipstack, SIP_TRANSP_TLS, &laddrs, session->stack.tls);
3766
                        err |= sipsess_listen(&session->stack.sess_sock, session->stack.sipstack, 32, janus_sipre_cb_incoming, session);
3767
                        if(err) {
3768
                                sip_close(session->stack.sipstack, TRUE);
3769
                                session->stack.sipstack = NULL;
3770
                                mem_deref(session->stack.tls);
3771
                                session->stack.tls = NULL;
3772
                                JANUS_LOG(LOG_ERR, "Failed to initialize libre SIPS transports: %d (%s)\n", err, strerror(err));
3773
                                g_free(payload);
3774
                                return;
3775
                        }
3776
#ifdef HAVE_LIBRE_SIPTRACE
3777
                        if(gateway->events_is_enabled()) {
3778
                                /* Trace incoming/outgoing SIP messages */
3779
                                sip_set_trace(session->stack.sipstack, janus_sipre_msg_logger);
3780
                        }
3781
#endif
3782
                        mem_deref(session->stack.tls);
3783
                        session->stack.tls = NULL;
3784
                        g_free(payload);
3785
                        break;
3786
                }
3787
                case janus_sipre_mqueue_event_do_register:
3788
                case janus_sipre_mqueue_event_do_unregister: {
3789
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3790
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3791
                        /* Whether it's a REGISTER or an unregister, get rid of the previous instance */
3792
                        mem_deref(session->stack.reg);
3793
                        session->stack.reg = NULL;
3794
                        /* If it's an unregister, we're done */
3795
                        if(session->stack.expires == 0) {
3796
                                /* Notify the browser */
3797
                                json_t *event = json_object();
3798
                                json_object_set_new(event, "sip", json_string("event"));
3799
                                json_t *unreging = json_object();
3800
                                json_object_set_new(unreging, "event", json_string("unregistered"));
3801
                                json_object_set_new(unreging, "username", json_string(session->account.username));
3802
                                json_object_set_new(unreging, "register_sent", json_true());
3803
                                json_object_set_new(event, "result", unreging);
3804
                                if(!session->destroyed) {
3805
                                        int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, event, NULL);
3806
                                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3807
                                }
3808
                                json_decref(event);
3809
                                /* Also notify event handlers */
3810
                                if(notify_events && gateway->events_is_enabled()) {
3811
                                        json_t *info = json_object();
3812
                                        json_object_set_new(info, "event", json_string("unregistered"));
3813
                                        json_object_set_new(info, "identity", json_string(session->account.identity));
3814
                                        if(session->account.proxy)
3815
                                                json_object_set_new(info, "proxy", json_string(session->account.proxy));
3816
                                        gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3817
                                }
3818
                                break;
3819
                        }
3820
                        JANUS_LOG(LOG_VERB, "[SIPre-%s] Sending REGISTER\n", session->account.username);
3821
                        /* Check if there is an outbound proxy to take into account */
3822
                        const char *outbound_proxy[1];
3823
                        outbound_proxy[0] = session->account.outbound_proxy;
3824
                        /* Check if there are custom headers to add */
3825
                        char *headers = (char *)payload->data;
3826
                        /* Send the REGISTER */
3827
                        int err = sipreg_register(&session->stack.reg, session->stack.sipstack,
3828
                                session->account.proxy,
3829
                                session->account.identity, session->account.identity, session->stack.expires,
3830
                                session->account.username,
3831
                                outbound_proxy, (outbound_proxy[0] ? 1 : 0), 0,
3832
                                janus_sipre_cb_auth, session, FALSE,
3833
                                janus_sipre_cb_register, session, NULL, (headers ? headers : ""), NULL);
3834
                        g_free(headers);
3835
                        if(err != 0) {
3836
                                JANUS_LOG(LOG_ERR, "Error attempting to REGISTER: %d (%s)\n", err, strerror(err));
3837
                                /* Tell the browser... */
3838
                                json_t *event = json_object();
3839
                                json_object_set_new(event, "sip", json_string("event"));
3840
                                json_t *result = json_object();
3841
                                json_object_set_new(result, "event", json_string("registration_failed"));
3842
                                json_object_set_new(result, "code", json_integer(err));
3843
                                json_object_set_new(result, "reason", json_string(strerror(err)));
3844
                                json_object_set_new(event, "result", result);
3845
                                if(!session->destroyed) {
3846
                                        int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, event, NULL);
3847
                                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3848
                                }
3849
                                json_decref(event);
3850
                                /* Also notify event handlers */
3851
                                if(notify_events && gateway->events_is_enabled()) {
3852
                                        json_t *info = json_object();
3853
                                        json_object_set_new(info, "event", json_string("registration_failed"));
3854
                                        json_object_set_new(info, "code", json_integer(err));
3855
                                        json_object_set_new(info, "reason", json_string(strerror(err)));
3856
                                        gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3857
                                }
3858
                        }
3859
                        g_free(payload);
3860
                        break;
3861
                }
3862
                case janus_sipre_mqueue_event_do_call: {
3863
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3864
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3865
                        JANUS_LOG(LOG_VERB, "[SIPre-%s] Sending INVITE\n%s", session->account.username, session->temp_sdp);
3866
                        /* Check if there is an outbound proxy to take into account */
3867
                        const char *outbound_proxy[1];
3868
                        outbound_proxy[0] = session->account.outbound_proxy;
3869
                        /* Check if there are custom headers to add */
3870
                        char *headers = (char *)payload->data;
3871
                        /* Convert the SDP into a struct mbuf */
3872
                        struct mbuf *mb = mbuf_alloc(strlen(session->temp_sdp)+1);
3873
                        mbuf_printf(mb, "%s", session->temp_sdp);
3874
                        mbuf_set_pos(mb, 0);
3875
                        /* Send the INVITE */
3876
                        int err = sipsess_connect(&session->stack.sess, session->stack.sess_sock,
3877
                                session->callee,
3878
                                session->account.display_name, session->account.identity,
3879
                                session->account.username,
3880
                                outbound_proxy, (outbound_proxy[0] ? 1 : 0),
3881
                                "application/sdp", mb,
3882
                                janus_sipre_cb_auth, session, FALSE,
3883
                                janus_sipre_cb_offer, janus_sipre_cb_answer,
3884
                                janus_sipre_cb_progress, janus_sipre_cb_established,
3885
                                NULL, NULL, janus_sipre_cb_closed, session,
3886
                                "%s", (headers ? headers : ""));
3887
                        g_free(headers);
3888
                        if(err != 0) {
3889
                                JANUS_LOG(LOG_ERR, "Error attempting to INVITE: %d (%s)\n", err, strerror(err));
3890
                                /* Tell the browser... */
3891
                                json_t *event = json_object();
3892
                                json_object_set_new(event, "sip", json_string("event"));
3893
                                json_t *result = json_object();
3894
                                json_object_set_new(result, "event", json_string("hangup"));
3895
                                json_object_set_new(result, "code", json_integer(err));
3896
                                json_object_set_new(result, "reason", json_string(strerror(err)));
3897
                                json_object_set_new(event, "result", result);
3898
                                if(!session->destroyed) {
3899
                                        int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, event, NULL);
3900
                                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3901
                                }
3902
                                json_decref(event);
3903
                                /* Also notify event handlers */
3904
                                if(notify_events && gateway->events_is_enabled()) {
3905
                                        json_t *info = json_object();
3906
                                        json_object_set_new(info, "event", json_string("hangup"));
3907
                                        json_object_set_new(info, "code", json_integer(err));
3908
                                        json_object_set_new(info, "reason", json_string(strerror(err)));
3909
                                        gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3910
                                }
3911
                        }
3912
                        mem_deref(mb);
3913
                        g_free(session->temp_sdp);
3914
                        session->temp_sdp = NULL;
3915
                        g_free(payload);
3916
                        break;
3917
                }
3918
                case janus_sipre_mqueue_event_do_accept: {
3919
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3920
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3921
                        JANUS_LOG(LOG_VERB, "[SIPre-%s] Sending 200 OK\n%s", session->account.username, session->temp_sdp);
3922
                        /* Convert the SDP into a struct mbuf */
3923
                        struct mbuf *mb = mbuf_alloc(strlen(session->temp_sdp)+1);
3924
                        mbuf_printf(mb, "%s", session->temp_sdp);
3925
                        mbuf_set_pos(mb, 0);
3926
                        /* Send the 200 OK */
3927
                        int err = sipsess_answer(session->stack.sess, 200, "OK", mb, NULL);
3928
                        if(err != 0) {
3929
                                JANUS_LOG(LOG_ERR, "Error attempting to send the 200 OK: %d (%s)\n", err, strerror(err));
3930
                                /* Tell the browser... */
3931
                                json_t *event = json_object();
3932
                                json_object_set_new(event, "sip", json_string("event"));
3933
                                json_t *result = json_object();
3934
                                json_object_set_new(result, "event", json_string("hangup"));
3935
                                json_object_set_new(result, "code", json_integer(err));
3936
                                json_object_set_new(result, "reason", json_string(strerror(err)));
3937
                                json_object_set_new(event, "result", result);
3938
                                if(!session->destroyed) {
3939
                                        int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, event, NULL);
3940
                                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3941
                                }
3942
                                json_decref(event);
3943
                                /* Also notify event handlers */
3944
                                if(notify_events && gateway->events_is_enabled()) {
3945
                                        json_t *info = json_object();
3946
                                        json_object_set_new(info, "event", json_string("hangup"));
3947
                                        json_object_set_new(info, "code", json_integer(err));
3948
                                        json_object_set_new(info, "reason", json_string(strerror(err)));
3949
                                        gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3950
                                }
3951
                        }
3952
                        mem_deref(mb);
3953
                        g_free(session->temp_sdp);
3954
                        session->temp_sdp = NULL;
3955
                        g_free(payload);
3956
                        break;
3957
                }
3958
                case janus_sipre_mqueue_event_do_rcode: {
3959
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3960
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3961
                        JANUS_LOG(LOG_VERB, "[SIPre-%s] Sending response code %d\n", session->account.username, payload->rcode);
3962
                        /* Send the response code */
3963
                        int err = 0;
3964
                        if(session->stack.sess == NULL) {
3965
                                /* We still need to accept the connection */
3966
                                err = sipsess_accept(&session->stack.sess, session->stack.sess_sock,
3967
                                        session->stack.invite, payload->rcode, janus_sipre_error_reason(payload->rcode),
3968
                                        session->account.display_name ? session->account.display_name : session->account.username,
3969
                                        "application/sdp", NULL,
3970
                                        janus_sipre_cb_auth, session, FALSE,
3971
                                        janus_sipre_cb_offer, janus_sipre_cb_answer,
3972
                                        janus_sipre_cb_established, janus_sipre_cb_info, NULL,
3973
                                        janus_sipre_cb_closed, session, NULL);
3974
                        } else {
3975
                                /* Connection already accepted */
3976
                                if(payload->rcode < 200) {
3977
                                        /* 1xx */
3978
                                        err = sipsess_progress(session->stack.sess, payload->rcode, janus_sipre_error_reason(payload->rcode), N