Statistics
| Branch: | Revision:

janus-gateway / plugins / janus_sipre.c @ 486455a0

History | View | Annotate | Download (158 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 hold , \c unhold and \c hangup . \c register can be used,
21
 * as the name suggests, to register a username at a SIP registrar to
22
 * call and be called, while \c unregister unregisters it; \c call is used
23
 * to send an INVITE to a different SIPre URI through the plugin, while
24
 * \c accept is used to accept the call in case one is invited instead
25
 * of inviting; ; \c hold and \c unhold can be used respectively to put a
26
 * call on-hold and to resume it; finally, \c hangup can be used to terminate the
27
 * communication at any time, either to hangup (BYE) an ongoing call or
28
 * to cancel/decline (CANCEL/BYE) a call that hasn't started yet.
29
 *
30
 * Actual API docs: TBD.
31
 *
32
 * \ingroup plugins
33
 * \ref plugins
34
 */
35

    
36
#include "plugin.h"
37

    
38
#include <arpa/inet.h>
39
#include <net/if.h>
40
#include <sys/socket.h>
41
#include <netdb.h>
42
#include <poll.h>
43

    
44
#include <jansson.h>
45

    
46
#include <re_types.h>
47
#include <re_fmt.h>
48
#include <re_mbuf.h>
49
#include <re_msg.h>
50
#include <re_list.h>
51
#include <re_sa.h>
52
#include <re_main.h>
53
#include <re_mem.h>
54
#include <re_mqueue.h>
55
#include <re_sdp.h>
56
#include <re_uri.h>
57
#include <re_sip.h>
58
#include <re_sipreg.h>
59
#include <re_sipsess.h>
60
#include <re_srtp.h>
61
#include <re_tmr.h>
62
#include <re_tls.h>
63
#include <re_dns.h>
64

    
65
#include "../debug.h"
66
#include "../apierror.h"
67
#include "../config.h"
68
#include "../mutex.h"
69
#include "../record.h"
70
#include "../rtp.h"
71
#include "../rtcp.h"
72
#include "../sdp-utils.h"
73
#include "../utils.h"
74
#include "../ip-utils.h"
75

    
76

    
77
/* Plugin information */
78
#define JANUS_SIPRE_VERSION                        1
79
#define JANUS_SIPRE_VERSION_STRING        "0.0.1"
80
#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."
81
#define JANUS_SIPRE_NAME                        "JANUS SIPre plugin"
82
#define JANUS_SIPRE_AUTHOR                        "Meetecho s.r.l."
83
#define JANUS_SIPRE_PACKAGE                        "janus.plugin.sipre"
84

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

    
105
/* Plugin setup */
106
static janus_plugin janus_sipre_plugin =
107
        JANUS_PLUGIN_INIT (
108
                .init = janus_sipre_init,
109
                .destroy = janus_sipre_destroy,
110

    
111
                .get_api_compatibility = janus_sipre_get_api_compatibility,
112
                .get_version = janus_sipre_get_version,
113
                .get_version_string = janus_sipre_get_version_string,
114
                .get_description = janus_sipre_get_description,
115
                .get_name = janus_sipre_get_name,
116
                .get_author = janus_sipre_get_author,
117
                .get_package = janus_sipre_get_package,
118

    
119
                .create_session = janus_sipre_create_session,
120
                .handle_message = janus_sipre_handle_message,
121
                .setup_media = janus_sipre_setup_media,
122
                .incoming_rtp = janus_sipre_incoming_rtp,
123
                .incoming_rtcp = janus_sipre_incoming_rtcp,
124
                .hangup_media = janus_sipre_hangup_media,
125
                .destroy_session = janus_sipre_destroy_session,
126
                .query_session = janus_sipre_query_session,
127
        );
128

    
129
/* Plugin creator */
130
janus_plugin *create(void) {
131
        JANUS_LOG(LOG_VERB, "%s created!\n", JANUS_SIPRE_NAME);
132
        return &janus_sipre_plugin;
133
}
134

    
135
/* Parameter validation */
136
static struct janus_json_parameter request_parameters[] = {
137
        {"request", JANUS_JSON_STRING, JANUS_JSON_PARAM_REQUIRED}
138
};
139
static struct janus_json_parameter register_parameters[] = {
140
        {"type", JANUS_JSON_STRING, 0},
141
        {"send_register", JANUS_JSON_BOOL, 0},
142
        {"sips", JANUS_JSON_BOOL, 0},
143
        {"username", JANUS_JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
144
        {"secret", JANUS_JSON_STRING, 0},
145
        {"ha1_secret", JANUS_JSON_STRING, 0},
146
        {"authuser", JANUS_JSON_STRING, 0},
147
        {"headers", JANUS_JSON_OBJECT, 0},
148
        {"refresh", JANUS_JSON_BOOL, 0}
149
};
150
static struct janus_json_parameter proxy_parameters[] = {
151
        {"proxy", JSON_STRING, 0},
152
        {"outbound_proxy", JSON_STRING, 0}
153
};
154
static struct janus_json_parameter call_parameters[] = {
155
        {"uri", JANUS_JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
156
        {"autoack", JANUS_JSON_BOOL, 0},
157
        {"headers", JANUS_JSON_OBJECT, 0},
158
        {"srtp", JANUS_JSON_STRING, 0}
159
};
160
static struct janus_json_parameter accept_parameters[] = {
161
        {"srtp", JANUS_JSON_STRING, 0}
162
};
163
static struct janus_json_parameter recording_parameters[] = {
164
        {"action", JANUS_JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
165
        {"audio", JANUS_JSON_BOOL, 0},
166
        {"video", JANUS_JSON_BOOL, 0},
167
        {"peer_audio", JANUS_JSON_BOOL, 0},
168
        {"peer_video", JANUS_JSON_BOOL, 0},
169
        {"filename", JANUS_JSON_STRING, 0}
170
};
171
static struct janus_json_parameter dtmf_info_parameters[] = {
172
        {"digit", JANUS_JSON_STRING, JANUS_JSON_PARAM_REQUIRED},
173
        {"duration", JANUS_JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE}
174
};
175

    
176
/* Useful stuff */
177
static volatile gint initialized = 0, stopping = 0;
178
static gboolean notify_events = TRUE;
179
static janus_callbacks *gateway = NULL;
180

    
181
static char *local_ip = NULL;
182
static int keepalive_interval = 120;
183
static gboolean behind_nat = FALSE;
184
static char *user_agent;
185
#define JANUS_DEFAULT_REGISTER_TTL        3600
186
static uint32_t register_ttl = JANUS_DEFAULT_REGISTER_TTL;
187

    
188
static GThread *handler_thread;
189
static GThread *watchdog;
190
static void *janus_sipre_handler(void *data);
191

    
192
typedef struct janus_sipre_message {
193
        janus_plugin_session *handle;
194
        char *transaction;
195
        json_t *message;
196
        json_t *jsep;
197
} janus_sipre_message;
198
static GAsyncQueue *messages = NULL;
199
static janus_sipre_message exit_message;
200

    
201
static void janus_sipre_message_free(janus_sipre_message *msg) {
202
        if(!msg || msg == &exit_message)
203
                return;
204

    
205
        msg->handle = NULL;
206

    
207
        g_free(msg->transaction);
208
        msg->transaction = NULL;
209
        if(msg->message)
210
                json_decref(msg->message);
211
        msg->message = NULL;
212
        if(msg->jsep)
213
                json_decref(msg->jsep);
214
        msg->jsep = NULL;
215

    
216
        g_free(msg);
217
}
218

    
219
/* libre SIP stack */
220
static volatile int libre_inited = 0;
221
GThread *sipstack_thread = NULL;
222

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

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

    
361
/* Registration info */
362
typedef enum {
363
        janus_sipre_registration_status_disabled = -2,
364
        janus_sipre_registration_status_failed = -1,
365
        janus_sipre_registration_status_unregistered = 0,
366
        janus_sipre_registration_status_registering,
367
        janus_sipre_registration_status_registered,
368
        janus_sipre_registration_status_unregistering,
369
} janus_sipre_registration_status;
370

    
371
static const char *janus_sipre_registration_status_string(janus_sipre_registration_status status) {
372
        switch(status) {
373
                case janus_sipre_registration_status_disabled:
374
                        return "disabled";
375
                case janus_sipre_registration_status_failed:
376
                        return "failed";
377
                case janus_sipre_registration_status_unregistered:
378
                        return "unregistered";
379
                case janus_sipre_registration_status_registering:
380
                        return "registering";
381
                case janus_sipre_registration_status_registered:
382
                        return "registered";
383
                case janus_sipre_registration_status_unregistering:
384
                        return "unregistering";
385
                default:
386
                        return "unknown";
387
        }
388
}
389

    
390

    
391
typedef enum {
392
        janus_sipre_call_status_idle = 0,
393
        janus_sipre_call_status_inviting,
394
        janus_sipre_call_status_invited,
395
        janus_sipre_call_status_incall,
396
        janus_sipre_call_status_closing,
397
} janus_sipre_call_status;
398

    
399
static const char *janus_sipre_call_status_string(janus_sipre_call_status status) {
400
        switch(status) {
401
                case janus_sipre_call_status_idle:
402
                        return "idle";
403
                case janus_sipre_call_status_inviting:
404
                        return "inviting";
405
                case janus_sipre_call_status_invited:
406
                        return "invited";
407
                case janus_sipre_call_status_incall:
408
                        return "incall";
409
                case janus_sipre_call_status_closing:
410
                        return "closing";
411
                default:
412
                        return "unknown";
413
        }
414
}
415

    
416

    
417
typedef enum {
418
        janus_sipre_secret_type_plaintext = 1,
419
        janus_sipre_secret_type_hashed = 2,
420
        janus_sipre_secret_type_unknown
421
} janus_sipre_secret_type;
422

    
423
typedef struct janus_sipre_account {
424
        char *identity;
425
        char *user_agent;                /* Used to override the general UA string */
426
        gboolean sips;
427
        char *username;
428
        char *display_name;                /* Used for outgoing calls in the From header */
429
        char *authuser;                        /**< username to use for authentication */
430
        char *secret;
431
        janus_sipre_secret_type secret_type;
432
        int sip_port;
433
        char *proxy;
434
        char *outbound_proxy;
435
        janus_sipre_registration_status registration_status;
436
} janus_sipre_account;
437

    
438
typedef struct janus_sipre_stack {
439
        struct sip *sipstack;                                /* SIP stack */
440
        struct tls *tls;                                        /* TLS transport, if needed */
441
        struct sipsess *sess;                                /* SIP session */
442
        struct sipsess_sock *sess_sock;                /* SIP session socket */
443
        struct sipreg *reg;                                        /* SIP registration */
444
        struct dnsc *dns_client;                        /* DNS client */
445
        uint32_t expires;                                        /* Registration interval (seconds) */
446
        const struct sip_msg *invite;                /* Current INVITE */
447
        void *session;                                                /* Opaque pointer to the plugin session */
448
} janus_sipre_stack;
449

    
450
typedef struct janus_sipre_media {
451
        char *remote_ip;
452
        gboolean ready;
453
        gboolean autoack;
454
        gboolean require_srtp, has_srtp_local, has_srtp_remote;
455
        gboolean on_hold;
456
        gboolean has_audio;
457
        int audio_rtp_fd, audio_rtcp_fd;
458
        int local_audio_rtp_port, remote_audio_rtp_port;
459
        int local_audio_rtcp_port, remote_audio_rtcp_port;
460
        guint32 audio_ssrc, audio_ssrc_peer;
461
        int audio_pt;
462
        const char *audio_pt_name;
463
        srtp_t audio_srtp_in, audio_srtp_out;
464
        srtp_policy_t audio_remote_policy, audio_local_policy;
465
        int audio_srtp_suite_in, audio_srtp_suite_out;
466
        gboolean audio_send;
467
        janus_sdp_mdirection pre_hold_audio_dir;
468
        gboolean has_video;
469
        int video_rtp_fd, video_rtcp_fd;
470
        int local_video_rtp_port, remote_video_rtp_port;
471
        int local_video_rtcp_port, remote_video_rtcp_port;
472
        guint32 video_ssrc, video_ssrc_peer;
473
        int video_pt;
474
        const char *video_pt_name;
475
        srtp_t video_srtp_in, video_srtp_out;
476
        srtp_policy_t video_remote_policy, video_local_policy;
477
        int video_srtp_suite_in, video_srtp_suite_out;
478
        gboolean video_send;
479
        janus_sdp_mdirection pre_hold_video_dir;
480
        janus_rtp_switching_context context;
481
        int pipefd[2];
482
        gboolean updated;
483
} janus_sipre_media;
484

    
485
typedef struct janus_sipre_session {
486
        janus_plugin_session *handle;
487
        janus_sipre_stack stack;
488
        janus_sipre_account account;
489
        janus_sipre_call_status status;
490
        janus_sipre_media media;
491
        char *transaction;
492
        char *callee;
493
        char *callid;
494
        char *temp_sdp;
495
        janus_sdp *sdp;                                /* The SDP this user sent */
496
        janus_recorder *arc;                /* The Janus recorder instance for this user's audio, if enabled */
497
        janus_recorder *arc_peer;        /* The Janus recorder instance for the peer's audio, if enabled */
498
        janus_recorder *vrc;                /* The Janus recorder instance for this user's video, if enabled */
499
        janus_recorder *vrc_peer;        /* The Janus recorder instance for the peer's video, if enabled */
500
        janus_mutex rec_mutex;                /* Mutex to protect the recorders from race conditions */
501
        volatile gint hangingup;
502
        gint64 destroyed;        /* Time at which this session was marked as destroyed */
503
        janus_mutex mutex;
504
} janus_sipre_session;
505
static GHashTable *sessions;
506
static GList *old_sessions;
507
static GHashTable *identities;
508
static GHashTable *callids;
509
static janus_mutex sessions_mutex;
510

    
511

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

    
616

    
617
/* libre event thread */
618
gpointer janus_sipre_stack_thread(gpointer user_data);
619
/* libre callbacks */
620
int janus_sipre_cb_auth(char **user, char **pass, const char *realm, void *arg);
621
void janus_sipre_cb_register(int err, const struct sip_msg *msg, void *arg);
622
void janus_sipre_cb_progress(const struct sip_msg *msg, void *arg);
623
void janus_sipre_cb_incoming(const struct sip_msg *msg, void *arg);
624
int janus_sipre_cb_offer(struct mbuf **mbp, const struct sip_msg *msg, void *arg);
625
int janus_sipre_cb_answer(const struct sip_msg *msg, void *arg);
626
void janus_sipre_cb_established(const struct sip_msg *msg, void *arg);
627
void janus_sipre_cb_closed(int err, const struct sip_msg *msg, void *arg);
628
void janus_sipre_cb_exit(void *arg);
629

    
630
/* URI parsing utilities */
631
static int janus_sipre_parse_uri(const char *uri) {
632
        if(uri == NULL)
633
                return -1;
634
        struct sip_addr addr;
635
        struct pl pluri;
636
        pl_set_str(&pluri, uri);
637
        if(sip_addr_decode(&addr, &pluri) != 0)
638
                return -1;
639
        return 0;
640
}
641
static char *janus_sipre_get_uri_username(const char *uri) {
642
        if(uri == NULL)
643
                return NULL;
644
        struct sip_addr addr;
645
        struct pl pluri;
646
        pl_set_str(&pluri, uri);
647
        if(sip_addr_decode(&addr, &pluri) != 0)
648
                return NULL;
649
        char *at = strchr(addr.uri.user.p, '@');
650
        if(at != NULL)
651
                *(at) = '\0';
652
        char *username = g_strdup(addr.uri.user.p);
653
        if(at != NULL)
654
                *(at) = '@';
655
        return username;
656
}
657
static char *janus_sipre_get_uri_host(const char *uri) {
658
        if(uri == NULL)
659
                return NULL;
660
        struct sip_addr addr;
661
        struct pl pluri;
662
        pl_set_str(&pluri, uri);
663
        if(sip_addr_decode(&addr, &pluri) != 0)
664
                return NULL;
665
        return g_strdup(addr.uri.host.p);
666
}
667
static uint16_t janus_sipre_get_uri_port(const char *uri) {
668
        if(uri == NULL)
669
                return 0;
670
        struct sip_addr addr;
671
        struct pl pluri;
672
        pl_set_str(&pluri, uri);
673
        if(sip_addr_decode(&addr, &pluri) != 0)
674
                return 0;
675
        return addr.uri.port;
676
}
677

    
678

    
679
/* SDP parsing and manipulation */
680
void janus_sipre_sdp_process(janus_sipre_session *session, janus_sdp *sdp, gboolean answer, gboolean update, gboolean *changed);
681
char *janus_sipre_sdp_manipulate(janus_sipre_session *session, janus_sdp *sdp, gboolean answer);
682
/* Media */
683
static int janus_sipre_allocate_local_ports(janus_sipre_session *session);
684
static void *janus_sipre_relay_thread(void *data);
685

    
686

    
687
/* Error codes */
688
#define JANUS_SIPRE_ERROR_UNKNOWN_ERROR                499
689
#define JANUS_SIPRE_ERROR_NO_MESSAGE                        440
690
#define JANUS_SIPRE_ERROR_INVALID_JSON                441
691
#define JANUS_SIPRE_ERROR_INVALID_REQUEST                442
692
#define JANUS_SIPRE_ERROR_MISSING_ELEMENT                443
693
#define JANUS_SIPRE_ERROR_INVALID_ELEMENT                444
694
#define JANUS_SIPRE_ERROR_ALREADY_REGISTERED        445
695
#define JANUS_SIPRE_ERROR_INVALID_ADDRESS                446
696
#define JANUS_SIPRE_ERROR_WRONG_STATE                        447
697
#define JANUS_SIPRE_ERROR_MISSING_SDP                        448
698
#define JANUS_SIPRE_ERROR_LIBRE_ERROR                449
699
#define JANUS_SIPRE_ERROR_IO_ERROR                        450
700
#define JANUS_SIPRE_ERROR_RECORDING_ERROR                451
701
#define JANUS_SIPRE_ERROR_TOO_STRICT                        452
702

    
703

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

    
801

    
802
/* Random string helper (for call-ids) */
803
static char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
804
static void janus_sipre_random_string(int length, char *buffer) {
805
        if(length > 0 && buffer) {
806
                int l = (int)(sizeof(charset)-1);
807
                int i=0;
808
                for(i=0; i<length; i++) {
809
                        int key = rand() % l;
810
                        buffer[i] = charset[key];
811
                }
812
                buffer[length-1] = '\0';
813
        }
814
}
815

    
816

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

    
835

    
836
/* Plugin implementation */
837
int janus_sipre_init(janus_callbacks *callback, const char *config_path) {
838
        if(g_atomic_int_get(&stopping)) {
839
                /* Still stopping from before */
840
                return -1;
841
        }
842
        if(callback == NULL || config_path == NULL) {
843
                /* Invalid arguments */
844
                return -1;
845
        }
846

    
847
        /* Read configuration */
848
        char filename[255];
849
        g_snprintf(filename, 255, "%s/%s.cfg", config_path, JANUS_SIPRE_PACKAGE);
850
        JANUS_LOG(LOG_VERB, "Configuration file: %s\n", filename);
851
        janus_config *config = janus_config_parse(filename);
852
        if(config != NULL) {
853
                janus_config_print(config);
854

    
855
                janus_config_item *item = janus_config_get_item_drilldown(config, "general", "local_ip");
856
                if(item && item->value) {
857
                        /* Verify that the address is valid */
858
                        struct ifaddrs *ifas = NULL;
859
                        janus_network_address iface;
860
                        janus_network_address_string_buffer ibuf;
861
                        if(getifaddrs(&ifas) || ifas == NULL) {
862
                                JANUS_LOG(LOG_ERR, "Unable to acquire list of network devices/interfaces; some configurations may not work as expected...\n");
863
                        } else {
864
                                if(janus_network_lookup_interface(ifas, item->value, &iface) != 0) {
865
                                        JANUS_LOG(LOG_WARN, "Error setting local IP address to %s, falling back to detecting IP address...\n", item->value);
866
                                } else {
867
                                        if(janus_network_address_to_string_buffer(&iface, &ibuf) != 0 || janus_network_address_string_buffer_is_null(&ibuf)) {
868
                                                JANUS_LOG(LOG_WARN, "Error getting local IP address from %s, falling back to detecting IP address...\n", item->value);
869
                                        } else {
870
                                                local_ip = g_strdup(janus_network_address_string_from_buffer(&ibuf));
871
                                        }
872
                                }
873
                        }
874
                }
875

    
876
                item = janus_config_get_item_drilldown(config, "general", "keepalive_interval");
877
                if(item && item->value) {
878
                        keepalive_interval = atoi(item->value);
879
                }
880
                JANUS_LOG(LOG_VERB, "SIPre keep-alive interval set to %d seconds\n", keepalive_interval);
881

    
882
                item = janus_config_get_item_drilldown(config, "general", "register_ttl");
883
                if(item && item->value) {
884
                        register_ttl = atol(item->value);
885
                }
886
                JANUS_LOG(LOG_VERB, "SIPre registration TTL set to %d seconds\n", register_ttl);
887

    
888
                item = janus_config_get_item_drilldown(config, "general", "behind_nat");
889
                if(item && item->value) {
890
                        behind_nat = janus_is_true(item->value);
891
                }
892

    
893
                item = janus_config_get_item_drilldown(config, "general", "user_agent");
894
                if(item && item->value) {
895
                        user_agent = g_strdup(item->value);
896
                } else {
897
                        user_agent = g_strdup("Janus WebRTC Gateway SIPre Plugin "JANUS_SIPRE_VERSION_STRING);
898
                }
899
                JANUS_LOG(LOG_VERB, "SIPre User-Agent set to %s\n", user_agent);
900

    
901
                item = janus_config_get_item_drilldown(config, "general", "events");
902
                if(item != NULL && item->value != NULL) {
903
                        notify_events = janus_is_true(item->value);
904
                }
905
                if(!notify_events && callback->events_is_enabled()) {
906
                        JANUS_LOG(LOG_WARN, "Notification of events to handlers disabled for %s\n", JANUS_SIPRE_NAME);
907
                }
908

    
909
                janus_config_destroy(config);
910
        }
911
        config = NULL;
912

    
913
        if(local_ip == NULL) {
914
                local_ip = janus_network_detect_local_ip_as_string(janus_network_query_options_any_ip);
915
                if(local_ip == NULL) {
916
                        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");
917
                        local_ip = g_strdup("127.0.0.1");
918
                }
919
        }
920
        JANUS_LOG(LOG_VERB, "Local IP set to %s\n", local_ip);
921

    
922
#ifdef HAVE_SRTP_2
923
        /* Init randomizer (for randum numbers in SRTP) */
924
        RAND_poll();
925
#endif
926

    
927
        sessions = g_hash_table_new(NULL, NULL);
928
        callids = g_hash_table_new(g_str_hash, g_str_equal);
929
        identities = g_hash_table_new(g_str_hash, g_str_equal);
930
        janus_mutex_init(&sessions_mutex);
931
        messages = g_async_queue_new_full((GDestroyNotify) janus_sipre_message_free);
932
        /* This is the callback we'll need to invoke to contact the gateway */
933
        gateway = callback;
934

    
935
        g_atomic_int_set(&initialized, 1);
936

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

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

    
976
        JANUS_LOG(LOG_INFO, "%s initialized!\n", JANUS_SIPRE_NAME);
977
        return 0;
978
}
979

    
980
void janus_sipre_destroy(void) {
981
        if(!g_atomic_int_get(&initialized))
982
                return;
983
        g_atomic_int_set(&stopping, 1);
984

    
985
        g_async_queue_push(messages, &exit_message);
986
        if(handler_thread != NULL) {
987
                g_thread_join(handler_thread);
988
                handler_thread = NULL;
989
        }
990

    
991
        /* Break the libre loop */
992
        mqueue_push(mq, janus_sipre_mqueue_event_do_exit, NULL);
993
        if(sipstack_thread != NULL) {
994
                g_thread_join(sipstack_thread);
995
                sipstack_thread = NULL;
996
        }
997
        if(watchdog != NULL) {
998
                g_thread_join(watchdog);
999
                watchdog = NULL;
1000
        }
1001
        /* FIXME We should destroy the sessions cleanly */
1002
        janus_mutex_lock(&sessions_mutex);
1003
        g_hash_table_destroy(sessions);
1004
        g_hash_table_destroy(callids);
1005
        g_hash_table_destroy(identities);
1006
        sessions = NULL;
1007
        callids = NULL;
1008
        identities = NULL;
1009
        janus_mutex_unlock(&sessions_mutex);
1010
        g_async_queue_unref(messages);
1011
        messages = NULL;
1012
        g_atomic_int_set(&initialized, 0);
1013
        g_atomic_int_set(&stopping, 0);
1014

    
1015
        g_free(local_ip);
1016

    
1017
        JANUS_LOG(LOG_INFO, "%s destroyed!\n", JANUS_SIPRE_NAME);
1018
}
1019

    
1020
int janus_sipre_get_api_compatibility(void) {
1021
        /* Important! This is what your plugin MUST always return: don't lie here or bad things will happen */
1022
        return JANUS_PLUGIN_API_VERSION;
1023
}
1024

    
1025
int janus_sipre_get_version(void) {
1026
        return JANUS_SIPRE_VERSION;
1027
}
1028

    
1029
const char *janus_sipre_get_version_string(void) {
1030
        return JANUS_SIPRE_VERSION_STRING;
1031
}
1032

    
1033
const char *janus_sipre_get_description(void) {
1034
        return JANUS_SIPRE_DESCRIPTION;
1035
}
1036

    
1037
const char *janus_sipre_get_name(void) {
1038
        return JANUS_SIPRE_NAME;
1039
}
1040

    
1041
const char *janus_sipre_get_author(void) {
1042
        return JANUS_SIPRE_AUTHOR;
1043
}
1044

    
1045
const char *janus_sipre_get_package(void) {
1046
        return JANUS_SIPRE_PACKAGE;
1047
}
1048

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

    
1122
        mqueue_push(mq, janus_sipre_mqueue_event_do_init, janus_sipre_mqueue_payload_create(session, NULL, 0, NULL));
1123

    
1124
        janus_mutex_lock(&sessions_mutex);
1125
        g_hash_table_insert(sessions, handle, session);
1126
        janus_mutex_unlock(&sessions_mutex);
1127

    
1128

    
1129
        return;
1130
}
1131

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

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

    
1200
struct janus_plugin_result *janus_sipre_handle_message(janus_plugin_session *handle, char *transaction, json_t *message, json_t *jsep) {
1201
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
1202
                return janus_plugin_result_new(JANUS_PLUGIN_ERROR, g_atomic_int_get(&stopping) ? "Shutting down" : "Plugin not initialized", NULL);
1203
        janus_sipre_message *msg = g_malloc0(sizeof(janus_sipre_message));
1204
        msg->handle = handle;
1205
        msg->transaction = transaction;
1206
        msg->message = message;
1207
        msg->jsep = jsep;
1208
        g_async_queue_push(messages, msg);
1209

    
1210
        /* All the requests to this plugin are handled asynchronously */
1211
        return janus_plugin_result_new(JANUS_PLUGIN_OK_WAIT, NULL, NULL);
1212
}
1213

    
1214
void janus_sipre_setup_media(janus_plugin_session *handle) {
1215
        JANUS_LOG(LOG_INFO, "WebRTC media is now available\n");
1216
        if(g_atomic_int_get(&stopping) || !g_atomic_int_get(&initialized))
1217
                return;
1218
        janus_sipre_session *session = (janus_sipre_session *)handle->plugin_handle;
1219
        if(!session) {
1220
                JANUS_LOG(LOG_ERR, "No session associated with this handle...\n");
1221
                return;
1222
        }
1223
        if(session->destroyed)
1224
                return;
1225
        g_atomic_int_set(&session->hangingup, 0);
1226
        /* TODO Only relay RTP/RTCP when we get this event */
1227
}
1228

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

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

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

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

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

    
1466
                        gboolean send_register = TRUE;
1467
                        json_t *do_register = json_object_get(root, "send_register");
1468
                        if(do_register != NULL) {
1469
                                if(guest) {
1470
                                        JANUS_LOG(LOG_ERR, "Conflicting elements: send_register cannot be true if guest is true\n");
1471
                                        error_code = JANUS_SIPRE_ERROR_INVALID_ELEMENT;
1472
                                        g_snprintf(error_cause, 512, "Conflicting elements: send_register cannot be true if guest is true");
1473
                                        goto error;
1474
                                }
1475
                                send_register = json_is_true(do_register);
1476
                        }
1477

    
1478
                        gboolean sips = TRUE;
1479
                        json_t *do_sipres = json_object_get(root, "sips");
1480
                        if(do_sipres != NULL) {
1481
                                sips = json_is_true(do_sipres);
1482
                        }
1483

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

    
1520
                        /* Parse register TTL */
1521
                        int ttl = register_ttl;
1522
                        json_t *reg_ttl = json_object_get(root, "register_ttl");
1523
                        if(reg_ttl && json_is_integer(reg_ttl))
1524
                                ttl = json_integer_value(reg_ttl);
1525
                        if(ttl <= 0)
1526
                                ttl = JANUS_DEFAULT_REGISTER_TTL;
1527
                        session->stack.expires = ttl;
1528

    
1529
                        /* Parse display name */
1530
                        const char* display_name_text = NULL;
1531
                        json_t *display_name = json_object_get(root, "display_name");
1532
                        if(display_name && json_is_string(display_name))
1533
                                display_name_text = json_string_value(display_name);
1534

    
1535
                        /* Parse user agent */
1536
                        const char* user_agent_text = NULL;
1537
                        json_t *user_agent = json_object_get(root, "user_agent");
1538
                        if(user_agent && json_is_string(user_agent))
1539
                                user_agent_text = json_string_value(user_agent);
1540

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

    
1609
                        /* If this is a refresh, get rid of the old values */
1610
                        if(refresh) {
1611
                                /* Cleanup old values */
1612
                                if(session->account.identity != NULL) {
1613
                                        g_hash_table_remove(identities, session->account.identity);
1614
                                        g_free(session->account.identity);
1615
                                }
1616
                                session->account.identity = NULL;
1617
                                session->account.sips = TRUE;
1618
                                if(session->account.username != NULL)
1619
                                        g_free(session->account.username);
1620
                                session->account.username = NULL;
1621
                                if(session->account.display_name != NULL)
1622
                                        g_free(session->account.display_name);
1623
                                session->account.display_name = NULL;
1624
                                if(session->account.authuser != NULL)
1625
                                        g_free(session->account.authuser);
1626
                                session->account.authuser = NULL;
1627
                                if(session->account.secret != NULL)
1628
                                        g_free(session->account.secret);
1629
                                session->account.secret = NULL;
1630
                                session->account.secret_type = janus_sipre_secret_type_unknown;
1631
                                if(session->account.proxy != NULL)
1632
                                        g_free(session->account.proxy);
1633
                                session->account.proxy = NULL;
1634
                                if(session->account.outbound_proxy != NULL)
1635
                                        g_free(session->account.outbound_proxy);
1636
                                session->account.outbound_proxy = NULL;
1637
                                if(session->account.user_agent != NULL)
1638
                                        g_free(session->account.user_agent);
1639
                                session->account.user_agent = NULL;
1640
                                session->account.registration_status = janus_sipre_registration_status_unregistered;
1641
                        }
1642
                        session->account.identity = g_strdup(username_text);
1643
                        g_hash_table_insert(identities, session->account.identity, session);
1644
                        session->account.sips = sips;
1645
                        session->account.username = g_strdup(user_id);
1646
                        session->account.authuser = g_strdup(authuser_text ? authuser_text : user_id);
1647
                        session->account.secret = secret_text ? g_strdup(secret_text) : NULL;
1648
                        session->account.secret_type = secret_type;
1649
                        if(display_name_text) {
1650
                                session->account.display_name = g_strdup(display_name_text);
1651
                        }
1652
                        if(user_agent_text) {
1653
                                session->account.user_agent = g_strdup(user_agent_text);
1654
                        }
1655
                        if(proxy_text) {
1656
                                session->account.proxy = g_strdup(proxy_text);
1657
                        } else {
1658
                                /* Build one from the user's identity */
1659
                                char uri[256];
1660
                                g_snprintf(uri, sizeof(uri), "sip:%s:%"SCNu16, user_host, (user_port ? user_port : 5060));
1661
                                session->account.proxy = g_strdup(uri);
1662
                        }
1663
                        if(obproxy_text) {
1664
                                session->account.outbound_proxy = g_strdup(obproxy_text);
1665
                        }
1666
                        g_free(user_host);
1667
                        g_free(user_id);
1668

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

    
2452
                /* Prepare JSON event */
2453
                json_t *event = json_object();
2454
                json_object_set_new(event, "sip", json_string("event"));
2455
                if(result != NULL)
2456
                        json_object_set_new(event, "result", result);
2457
                int ret = gateway->push_event(msg->handle, &janus_sipre_plugin, msg->transaction, event, NULL);
2458
                JANUS_LOG(LOG_VERB, "  >> Pushing event: %d (%s)\n", ret, janus_get_api_error(ret));
2459
                json_decref(event);
2460
                janus_sipre_message_free(msg);
2461
                continue;
2462

    
2463
error:
2464
                {
2465
                        /* Prepare JSON error event */
2466
                        json_t *event = json_object();
2467
                        json_object_set_new(event, "sip", json_string("event"));
2468
                        json_object_set_new(event, "error_code", json_integer(error_code));
2469
                        json_object_set_new(event, "error", json_string(error_cause));
2470
                        int ret = gateway->push_event(msg->handle, &janus_sipre_plugin, msg->transaction, event, NULL);
2471
                        JANUS_LOG(LOG_VERB, "  >> Pushing event: %d (%s)\n", ret, janus_get_api_error(ret));
2472
                        json_decref(event);
2473
                        janus_sipre_message_free(msg);
2474
                }
2475
        }
2476
        JANUS_LOG(LOG_VERB, "Leaving SIPre handler thread\n");
2477
        return NULL;
2478
}
2479

    
2480

    
2481
/* Process an incoming SDP */
2482
void janus_sipre_sdp_process(janus_sipre_session *session, janus_sdp *sdp, gboolean answer, gboolean update, gboolean *changed) {
2483
        if(!session || !sdp)
2484
                return;
2485
        /* c= */
2486
        if(sdp->c_addr) {
2487
                if(update && strcmp(sdp->c_addr, session->media.remote_ip)) {
2488
                        /* This is an update and an address changed */
2489
                        if(changed)
2490
                                *changed = TRUE;
2491
                }
2492
                g_free(session->media.remote_ip);
2493
                session->media.remote_ip = g_strdup(sdp->c_addr);
2494
        }
2495
        GList *temp = sdp->m_lines;
2496
        while(temp) {
2497
                janus_sdp_mline *m = (janus_sdp_mline *)temp->data;
2498
                session->media.require_srtp = session->media.require_srtp || (m->proto && !strcasecmp(m->proto, "RTP/SAVP"));
2499
                if(m->type == JANUS_SDP_AUDIO) {
2500
                        if(m->port) {
2501
                                if(m->port != session->media.remote_audio_rtp_port) {
2502
                                        /* This is an update and an address changed */
2503
                                        if(changed)
2504
                                                *changed = TRUE;
2505
                                }
2506
                                session->media.has_audio = TRUE;
2507
                                session->media.remote_audio_rtp_port = m->port;
2508
                                session->media.remote_audio_rtcp_port = m->port+1;        /* FIXME We're assuming RTCP is on the next port */
2509
                                if(m->direction == JANUS_SDP_SENDONLY || m->direction == JANUS_SDP_INACTIVE)
2510
                                        session->media.audio_send = FALSE;
2511
                                else
2512
                                        session->media.audio_send = TRUE;
2513
                        } else {
2514
                                session->media.audio_send = FALSE;
2515
                        }
2516
                } else if(m->type == JANUS_SDP_VIDEO) {
2517
                        if(m->port) {
2518
                                if(m->port != session->media.remote_video_rtp_port) {
2519
                                        /* This is an update and an address changed */
2520
                                        if(changed)
2521
                                                *changed = TRUE;
2522
                                }
2523
                                session->media.has_video = TRUE;
2524
                                session->media.remote_video_rtp_port = m->port;
2525
                                session->media.remote_video_rtcp_port = m->port+1;        /* FIXME We're assuming RTCP is on the next port */
2526
                                if(m->direction == JANUS_SDP_SENDONLY || m->direction == JANUS_SDP_INACTIVE)
2527
                                        session->media.video_send = FALSE;
2528
                                else
2529
                                        session->media.video_send = TRUE;
2530
                        } else {
2531
                                session->media.video_send = FALSE;
2532
                        }
2533
                } else {
2534
                        JANUS_LOG(LOG_WARN, "Unsupported media line (not audio/video)\n");
2535
                        temp = temp->next;
2536
                        continue;
2537
                }
2538
                if(m->c_addr) {
2539
                        if(update && strcmp(m->c_addr, session->media.remote_ip)) {
2540
                                /* This is an update and an address changed */
2541
                                if(changed)
2542
                                        *changed = TRUE;
2543
                        }
2544
                        g_free(session->media.remote_ip);
2545
                        session->media.remote_ip = g_strdup(m->c_addr);
2546
                }
2547
                if(update) {
2548
                        /* FIXME This is a session update, we only accept changes in IP/ports */
2549
                        temp = temp->next;
2550
                        continue;
2551
                }
2552
                GList *tempA = m->attributes;
2553
                while(tempA) {
2554
                        janus_sdp_attribute *a = (janus_sdp_attribute *)tempA->data;
2555
                        if(a->name) {
2556
                                if(!strcasecmp(a->name, "crypto")) {
2557
                                        if(m->type == JANUS_SDP_AUDIO || m->type == JANUS_SDP_VIDEO) {
2558
                                                gint32 tag = 0;
2559
                                                int suite;
2560
                                                char crypto[81];
2561
                                                /* FIXME inline can be more complex than that, and we're currently only offering SHA1_80 */
2562
                                                int res = sscanf(a->value, "%"SCNi32" AES_CM_128_HMAC_SHA1_%2d inline:%80s",
2563
                                                        &tag, &suite, crypto);
2564
                                                if(res != 3) {
2565
                                                        JANUS_LOG(LOG_WARN, "Failed to parse crypto line, ignoring... %s\n", a->value);
2566
                                                } else {
2567
                                                        gboolean video = (m->type == JANUS_SDP_VIDEO);
2568
                                                        int current_suite = video ? session->media.video_srtp_suite_in : session->media.audio_srtp_suite_in;
2569
                                                        if(current_suite == 0) {
2570
                                                                if(video)
2571
                                                                        session->media.video_srtp_suite_in = suite;
2572
                                                                else
2573
                                                                        session->media.audio_srtp_suite_in = suite;
2574
                                                                janus_sipre_srtp_set_remote(session, video, crypto, suite);
2575
                                                                session->media.has_srtp_remote = TRUE;
2576
                                                        } else {
2577
                                                                JANUS_LOG(LOG_WARN, "We already configured a %s crypto context (AES_CM_128_HMAC_SHA1_%d), skipping additional crypto line\n",
2578
                                                                        video ? "video" : "audio", current_suite);
2579
                                                        }
2580
                                                }
2581
                                        }
2582
                                }
2583
                        }
2584
                        tempA = tempA->next;
2585
                }
2586
                if(answer && (m->type == JANUS_SDP_AUDIO || m->type == JANUS_SDP_VIDEO)) {
2587
                        /* Check which codec was negotiated eventually */
2588
                        int pt = -1;
2589
                        if(m->ptypes)
2590
                                pt = GPOINTER_TO_INT(m->ptypes->data);
2591
                        if(pt > -1) {
2592
                                if(m->type == JANUS_SDP_AUDIO) {
2593
                                        session->media.audio_pt = pt;
2594
                                } else {
2595
                                        session->media.video_pt = pt;
2596
                                }
2597
                        }
2598
                }
2599
                temp = temp->next;
2600
        }
2601
        if(update && changed && *changed) {
2602
                /* Something changed: mark this on the session, so that the thread can update the sockets */
2603
                session->media.updated = TRUE;
2604
                if(session->media.pipefd[1] > 0) {
2605
                        int code = 1;
2606
                        ssize_t res = 0;
2607
                        do {
2608
                                res = write(session->media.pipefd[1], &code, sizeof(int));
2609
                        } while(res == -1 && errno == EINTR);
2610
                }
2611
        }
2612
}
2613

    
2614
char *janus_sipre_sdp_manipulate(janus_sipre_session *session, janus_sdp *sdp, gboolean answer) {
2615
        if(!session || !sdp)
2616
                return NULL;
2617
        /* Start replacing stuff */
2618
        JANUS_LOG(LOG_VERB, "Setting protocol to %s\n", session->media.require_srtp ? "RTP/SAVP" : "RTP/AVP");
2619
        GList *temp = sdp->m_lines;
2620
        while(temp) {
2621
                janus_sdp_mline *m = (janus_sdp_mline *)temp->data;
2622
                g_free(m->proto);
2623
                m->proto = g_strdup(session->media.require_srtp ? "RTP/SAVP" : "RTP/AVP");
2624
                if(m->type == JANUS_SDP_AUDIO) {
2625
                        m->port = session->media.local_audio_rtp_port;
2626
                        if(session->media.has_srtp_local) {
2627
                                char *crypto = NULL;
2628
                                session->media.audio_srtp_suite_out = 80;
2629
                                janus_sipre_srtp_set_local(session, FALSE, &crypto);
2630
                                /* FIXME 32? 80? Both? */
2631
                                janus_sdp_attribute *a = janus_sdp_attribute_create("crypto", "1 AES_CM_128_HMAC_SHA1_80 inline:%s", crypto);
2632
                                g_free(crypto);
2633
                                m->attributes = g_list_append(m->attributes, a);
2634
                        }
2635
                } else if(m->type == JANUS_SDP_VIDEO) {
2636
                        m->port = session->media.local_video_rtp_port;
2637
                        if(session->media.has_srtp_local) {
2638
                                char *crypto = NULL;
2639
                                session->media.audio_srtp_suite_out = 80;
2640
                                janus_sipre_srtp_set_local(session, TRUE, &crypto);
2641
                                /* FIXME 32? 80? Both? */
2642
                                janus_sdp_attribute *a = janus_sdp_attribute_create("crypto", "1 AES_CM_128_HMAC_SHA1_80 inline:%s", crypto);
2643
                                g_free(crypto);
2644
                                m->attributes = g_list_append(m->attributes, a);
2645
                        }
2646
                }
2647
                g_free(m->c_addr);
2648
                m->c_addr = g_strdup(local_ip);
2649
                if(answer && (m->type == JANUS_SDP_AUDIO || m->type == JANUS_SDP_VIDEO)) {
2650
                        /* Check which codec was negotiated eventually */
2651
                        int pt = -1;
2652
                        if(m->ptypes)
2653
                                pt = GPOINTER_TO_INT(m->ptypes->data);
2654
                        if(pt > -1) {
2655
                                if(m->type == JANUS_SDP_AUDIO) {
2656
                                        session->media.audio_pt = pt;
2657
                                } else {
2658
                                        session->media.video_pt = pt;
2659
                                }
2660
                        }
2661
                }
2662
                temp = temp->next;
2663
        }
2664
        /* Generate a SDP string out of our changes */
2665
        return janus_sdp_write(sdp);
2666
}
2667

    
2668
/* Bind local RTP/RTCP sockets */
2669
static int janus_sipre_allocate_local_ports(janus_sipre_session *session) {
2670
        if(session == NULL) {
2671
                JANUS_LOG(LOG_ERR, "Invalid session\n");
2672
                return -1;
2673
        }
2674
        /* Reset status */
2675
        if(session->media.audio_rtp_fd != -1) {
2676
                close(session->media.audio_rtp_fd);
2677
                session->media.audio_rtp_fd = -1;
2678
        }
2679
        if(session->media.audio_rtcp_fd != -1) {
2680
                close(session->media.audio_rtcp_fd);
2681
                session->media.audio_rtcp_fd = -1;
2682
        }
2683
        session->media.local_audio_rtp_port = 0;
2684
        session->media.local_audio_rtcp_port = 0;
2685
        session->media.audio_ssrc = 0;
2686
        if(session->media.video_rtp_fd != -1) {
2687
                close(session->media.video_rtp_fd);
2688
                session->media.video_rtp_fd = -1;
2689
        }
2690
        if(session->media.video_rtcp_fd != -1) {
2691
                close(session->media.video_rtcp_fd);
2692
                session->media.video_rtcp_fd = -1;
2693
        }
2694
        session->media.local_video_rtp_port = 0;
2695
        session->media.local_video_rtcp_port = 0;
2696
        session->media.video_ssrc = 0;
2697
        if(session->media.pipefd[0] > 0) {
2698
                close(session->media.pipefd[0]);
2699
                session->media.pipefd[0] = -1;
2700
        }
2701
        if(session->media.pipefd[1] > 0) {
2702
                close(session->media.pipefd[1]);
2703
                session->media.pipefd[1] = -1;
2704
        }
2705
        /* Start */
2706
        int attempts = 100;        /* FIXME Don't retry forever */
2707
        if(session->media.has_audio) {
2708
                JANUS_LOG(LOG_VERB, "Allocating audio ports:\n");
2709
                struct sockaddr_in audio_rtp_address, audio_rtcp_address;
2710
                while(session->media.local_audio_rtp_port == 0 || session->media.local_audio_rtcp_port == 0) {
2711
                        if(attempts == 0)        /* Too many failures */
2712
                                return -1;
2713
                        if(session->media.audio_rtp_fd == -1) {
2714
                                session->media.audio_rtp_fd = socket(AF_INET, SOCK_DGRAM, 0);
2715
                        }
2716
                        if(session->media.audio_rtcp_fd == -1) {
2717
                                session->media.audio_rtcp_fd = socket(AF_INET, SOCK_DGRAM, 0);
2718
                        }
2719
                        int rtp_port = g_random_int_range(10000, 60000);        /* FIXME Should this be configurable? */
2720
                        if(rtp_port % 2)
2721
                                rtp_port++;        /* Pick an even port for RTP */
2722
                        audio_rtp_address.sin_family = AF_INET;
2723
                        audio_rtp_address.sin_port = htons(rtp_port);
2724
                        inet_pton(AF_INET, local_ip, &audio_rtp_address.sin_addr.s_addr);
2725
                        if(bind(session->media.audio_rtp_fd, (struct sockaddr *)(&audio_rtp_address), sizeof(struct sockaddr)) < 0) {
2726
                                JANUS_LOG(LOG_ERR, "Bind failed for audio RTP (port %d), trying a different one...\n", rtp_port);
2727
                                attempts--;
2728
                                continue;
2729
                        }
2730
                        JANUS_LOG(LOG_VERB, "Audio RTP listener bound to port %d\n", rtp_port);
2731
                        int rtcp_port = rtp_port+1;
2732
                        audio_rtcp_address.sin_family = AF_INET;
2733
                        audio_rtcp_address.sin_port = htons(rtcp_port);
2734
                        inet_pton(AF_INET, local_ip, &audio_rtcp_address.sin_addr.s_addr);
2735
                        if(bind(session->media.audio_rtcp_fd, (struct sockaddr *)(&audio_rtcp_address), sizeof(struct sockaddr)) < 0) {
2736
                                JANUS_LOG(LOG_ERR, "Bind failed for audio RTCP (port %d), trying a different one...\n", rtcp_port);
2737
                                /* RTP socket is not valid anymore, reset it */
2738
                                close(session->media.audio_rtp_fd);
2739
                                session->media.audio_rtp_fd = -1;
2740
                                attempts--;
2741
                                continue;
2742
                        }
2743
                        JANUS_LOG(LOG_VERB, "Audio RTCP listener bound to port %d\n", rtcp_port);
2744
                        session->media.local_audio_rtp_port = rtp_port;
2745
                        session->media.local_audio_rtcp_port = rtcp_port;
2746
                }
2747
        }
2748
        if(session->media.has_video) {
2749
                JANUS_LOG(LOG_VERB, "Allocating video ports:\n");
2750
                struct sockaddr_in video_rtp_address, video_rtcp_address;
2751
                while(session->media.local_video_rtp_port == 0 || session->media.local_video_rtcp_port == 0) {
2752
                        if(attempts == 0)        /* Too many failures */
2753
                                return -1;
2754
                        if(session->media.video_rtp_fd == -1) {
2755
                                session->media.video_rtp_fd = socket(AF_INET, SOCK_DGRAM, 0);
2756
                        }
2757
                        if(session->media.video_rtcp_fd == -1) {
2758
                                session->media.video_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
                        video_rtp_address.sin_family = AF_INET;
2764
                        video_rtp_address.sin_port = htons(rtp_port);
2765
                        inet_pton(AF_INET, local_ip, &video_rtp_address.sin_addr.s_addr);
2766
                        if(bind(session->media.video_rtp_fd, (struct sockaddr *)(&video_rtp_address), sizeof(struct sockaddr)) < 0) {
2767
                                JANUS_LOG(LOG_ERR, "Bind failed for video RTP (port %d), trying a different one...\n", rtp_port);
2768
                                attempts--;
2769
                                continue;
2770
                        }
2771
                        JANUS_LOG(LOG_VERB, "Video RTP listener bound to port %d\n", rtp_port);
2772
                        int rtcp_port = rtp_port+1;
2773
                        video_rtcp_address.sin_family = AF_INET;
2774
                        video_rtcp_address.sin_port = htons(rtcp_port);
2775
                        inet_pton(AF_INET, local_ip, &video_rtcp_address.sin_addr.s_addr);
2776
                        if(bind(session->media.video_rtcp_fd, (struct sockaddr *)(&video_rtcp_address), sizeof(struct sockaddr)) < 0) {
2777
                                JANUS_LOG(LOG_ERR, "Bind failed for video RTCP (port %d), trying a different one...\n", rtcp_port);
2778
                                /* RTP socket is not valid anymore, reset it */
2779
                                close(session->media.video_rtp_fd);
2780
                                session->media.video_rtp_fd = -1;
2781
                                attempts--;
2782
                                continue;
2783
                        }
2784
                        JANUS_LOG(LOG_VERB, "Video RTCP listener bound to port %d\n", rtcp_port);
2785
                        session->media.local_video_rtp_port = rtp_port;
2786
                        session->media.local_video_rtcp_port = rtcp_port;
2787
                }
2788
        }
2789
        /* We need this to quickly interrupt the poll when it's time to update a session or wrap up */
2790
        pipe(session->media.pipefd);
2791
        return 0;
2792
}
2793

    
2794
/* Helper method to (re)connect RTP/RTCP sockets */
2795
static void janus_sipre_connect_sockets(janus_sipre_session *session, struct sockaddr_in *server_addr) {
2796
        if(!session || !server_addr)
2797
                return;
2798

    
2799
        if(session->media.updated) {
2800
                JANUS_LOG(LOG_VERB, "Updating session sockets\n");
2801
        }
2802

    
2803
        /* Connect peers (FIXME This pretty much sucks right now) */
2804
        if(session->media.remote_audio_rtp_port) {
2805
                server_addr->sin_port = htons(session->media.remote_audio_rtp_port);
2806
                if(connect(session->media.audio_rtp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
2807
                        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);
2808
                        JANUS_LOG(LOG_ERR, "[SIPre-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2809
                }
2810
        }
2811
        if(session->media.remote_audio_rtcp_port) {
2812
                server_addr->sin_port = htons(session->media.remote_audio_rtcp_port);
2813
                if(connect(session->media.audio_rtcp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
2814
                        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);
2815
                        JANUS_LOG(LOG_ERR, "[SIPre-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2816
                }
2817
        }
2818
        if(session->media.remote_video_rtp_port) {
2819
                server_addr->sin_port = htons(session->media.remote_video_rtp_port);
2820
                if(connect(session->media.video_rtp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
2821
                        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);
2822
                        JANUS_LOG(LOG_ERR, "[SIPre-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2823
                }
2824
        }
2825
        if(session->media.remote_video_rtcp_port) {
2826
                server_addr->sin_port = htons(session->media.remote_video_rtcp_port);
2827
                if(connect(session->media.video_rtcp_fd, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) == -1) {
2828
                        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);
2829
                        JANUS_LOG(LOG_ERR, "[SIPre-%s]   -- %d (%s)\n", session->account.username, errno, strerror(errno));
2830
                }
2831
        }
2832

    
2833
}
2834

    
2835
/* Thread to relay RTP/RTCP frames coming from the SIPre peer */
2836
static void *janus_sipre_relay_thread(void *data) {
2837
        janus_sipre_session *session = (janus_sipre_session *)data;
2838
        if(!session || !session->account.username || !session->callee) {
2839
                g_thread_unref(g_thread_self());
2840
                return NULL;
2841
        }
2842
        JANUS_LOG(LOG_VERB, "Starting relay thread (%s <--> %s)\n", session->account.username, session->callee);
2843

    
2844
        gboolean have_server_ip = TRUE;
2845
        struct sockaddr_in server_addr;
2846
        memset(&server_addr, 0, sizeof(server_addr));
2847
        server_addr.sin_family = AF_INET;
2848
        if(inet_aton(session->media.remote_ip, &server_addr.sin_addr) == 0) {        /* Not a numeric IP... */
2849
                struct hostent *host = gethostbyname(session->media.remote_ip);        /* ...resolve name */
2850
                if(!host) {
2851
                        JANUS_LOG(LOG_ERR, "[SIPre-%s] Couldn't get host (%s)\n", session->account.username, session->media.remote_ip);
2852
                        have_server_ip = FALSE;
2853
                } else {
2854
                        server_addr.sin_addr = *(struct in_addr *)host->h_addr_list;
2855
                }
2856
        }
2857
        if(have_server_ip)
2858
                janus_sipre_connect_sockets(session, &server_addr);
2859

    
2860
        if(!session->callee) {
2861
                JANUS_LOG(LOG_VERB, "[SIPre-%s] Leaving thread, no callee...\n", session->account.username);
2862
                g_thread_unref(g_thread_self());
2863
                return NULL;
2864
        }
2865
        /* File descriptors */
2866
        socklen_t addrlen;
2867
        struct sockaddr_in remote;
2868
        int resfd = 0, bytes = 0;
2869
        struct pollfd fds[5];
2870
        int pipe_fd = session->media.pipefd[0];
2871
        char buffer[1500];
2872
        memset(buffer, 0, 1500);
2873
        /* Loop */
2874
        int num = 0;
2875
        gboolean goon = TRUE;
2876
        int astep = 0, vstep = 0;
2877
        guint32 ats = 0, vts = 0;
2878
        while(goon && session != NULL && !session->destroyed &&
2879
                        session->status > janus_sipre_call_status_idle &&
2880
                        session->status < janus_sipre_call_status_closing) {        /* FIXME We need a per-call watchdog as well */
2881

    
2882
                if(session->media.updated) {
2883
                        /* Apparently there was a session update */
2884
                        if(session->media.remote_ip != NULL && (inet_aton(session->media.remote_ip, &server_addr.sin_addr) != 0)) {
2885
                                janus_sipre_connect_sockets(session, &server_addr);
2886
                        } else {
2887
                                JANUS_LOG(LOG_ERR, "[SIPre-%s] Couldn't update session details (missing or invalid remote IP address)\n", session->account.username);
2888
                        }
2889
                        session->media.updated = FALSE;
2890
                }
2891

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

    
3111

    
3112
/* libre loop thread */
3113
gpointer janus_sipre_stack_thread(gpointer user_data) {
3114
        JANUS_LOG(LOG_INFO, "Joining libre loop thread...\n");
3115

    
3116
        /* Setup libre */
3117
        int err = libre_init();
3118
        if(err) {
3119
                JANUS_LOG(LOG_ERR, "libre_init() failed: %d (%s)\n", err, strerror(err));
3120
                goto done;
3121
        }
3122
        /* Initialize this thread as a worker */
3123
        err = re_thread_init();
3124
        if(err != 0) {
3125
                printf("re_thread_init failed: %d (%s)\n", err, strerror(err));
3126
                goto done;
3127
        }
3128
        err = mqueue_alloc(&mq, janus_sipre_mqueue_handler, NULL);
3129
        if(err) {
3130
                JANUS_LOG(LOG_ERR, "Failed to initialize message queue: %d (%s)\n", err, strerror(err));
3131
                goto done;
3132
        }
3133
        g_atomic_int_set(&libre_inited, 1);
3134

    
3135
        /* Enter loop */
3136
        err = re_main(NULL);
3137
        if(err != 0) {
3138
                JANUS_LOG(LOG_ERR, "re_main() failed: %d (%s)\n", err, strerror(err));
3139
        }
3140

    
3141
        /* Done here */
3142
        JANUS_LOG(LOG_INFO, "Leaving libre loop thread...\n");
3143
        re_thread_close();
3144
        /* Deinitialize libre */
3145
        libre_close();
3146

    
3147
done:
3148
        g_atomic_int_set(&libre_inited, -1);
3149
        return NULL;
3150
}
3151

    
3152
/* Called when challenged for credentials */
3153
int janus_sipre_cb_auth(char **user, char **pass, const char *realm, void *arg) {
3154
        janus_sipre_session *session = (janus_sipre_session *)arg;
3155
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] janus_sipre_cb_auth (realm=%s)\n", session->account.username, realm);
3156
        /* TODO How do we handle hashed secrets? */
3157
        int err = 0;
3158
        err |= str_dup(user, session->account.authuser);
3159
        err |= str_dup(pass, session->account.secret);
3160
        JANUS_LOG(LOG_HUGE, "[SIPre-%s]   -- %s / %s\n", session->account.username, *user, *pass);
3161
        return err;
3162
}
3163

    
3164
/* Called when REGISTER responses are received */
3165
void janus_sipre_cb_register(int err, const struct sip_msg *msg, void *arg) {
3166
        janus_sipre_session *session = (janus_sipre_session *)arg;
3167
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] janus_sipre_cb_register\n", session->account.username);
3168
        if(err) {
3169
                JANUS_LOG(LOG_ERR, "[SIPre-%s] REGISTER error: %s\n", session->account.username, strerror(err));
3170
                /* FIXME Should we send an event here? */
3171
        } else {
3172
                const char *event_name = (session->stack.expires > 0 ? "registered" : "unregistered");
3173
                JANUS_LOG(LOG_VERB, "[SIPre-%s] REGISTER reply: %u\n", session->account.username, msg->scode);
3174
                if(msg->scode == 200) {
3175
                        if(session->stack.expires > 0) {
3176
                                if(session->account.registration_status < janus_sipre_registration_status_registered)
3177
                                        session->account.registration_status = janus_sipre_registration_status_registered;
3178
                        } else {
3179
                                session->account.registration_status = janus_sipre_registration_status_unregistered;
3180
                        }
3181
                        /* Notify the browser */
3182
                        json_t *call = json_object();
3183
                        json_object_set_new(call, "sip", json_string("event"));
3184
                        json_t *calling = json_object();
3185
                        json_object_set_new(calling, "event", json_string(event_name));
3186
                        json_object_set_new(calling, "username", json_string(session->account.username));
3187
                        json_object_set_new(calling, "register_sent", json_true());
3188
                        json_object_set_new(call, "result", calling);
3189
                        if(!session->destroyed) {
3190
                                int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, call, NULL);
3191
                                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3192
                        }
3193
                        json_decref(call);
3194
                        /* Also notify event handlers */
3195
                        if(notify_events && gateway->events_is_enabled()) {
3196
                                json_t *info = json_object();
3197
                                json_object_set_new(info, "event", json_string(event_name));
3198
                                json_object_set_new(info, "identity", json_string(session->account.identity));
3199
                                if(session->account.proxy)
3200
                                        json_object_set_new(info, "proxy", json_string(session->account.proxy));
3201
                                gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3202
                        }
3203
                } else {
3204
                        /* Authentication failed? */
3205
                        session->account.registration_status = janus_sipre_registration_status_failed;
3206
                        mem_deref(session->stack.reg);
3207
                        session->stack.reg = NULL;
3208
                        /* Tell the browser... */
3209
                        json_t *event = json_object();
3210
                        json_object_set_new(event, "sip", json_string("event"));
3211
                        json_t *result = json_object();
3212
                        json_object_set_new(result, "event", json_string("registration_failed"));
3213
                        json_object_set_new(result, "code", json_integer(msg->scode));
3214
                        char reason[256];
3215
                        reason[0] = '\0';
3216
                        if(msg->reason.l > 0) {
3217
                                g_snprintf(reason, (msg->reason.l < 255 ? msg->reason.l+1 : 255), "%s", msg->reason.p);
3218
                                json_object_set_new(result, "reason", json_string(reason));
3219
                        }
3220
                        json_object_set_new(event, "result", result);
3221
                        if(!session->destroyed) {
3222
                                int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, event, NULL);
3223
                                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3224
                        }
3225
                        json_decref(event);
3226
                        /* Also notify event handlers */
3227
                        if(notify_events && gateway->events_is_enabled()) {
3228
                                json_t *info = json_object();
3229
                                json_object_set_new(info, "event", json_string("registration_failed"));
3230
                                json_object_set_new(info, "code", json_integer(msg->scode));
3231
                                if(msg->reason.l > 0) {
3232
                                        json_object_set_new(info, "reason", json_string(reason));
3233
                                }
3234
                                gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3235
                        }
3236
                }
3237
        }
3238
}
3239

    
3240
/* Called when SIP progress (e.g., 180 Ringing) responses are received */
3241
void janus_sipre_cb_progress(const struct sip_msg *msg, void *arg) {
3242
        janus_sipre_session *session = (janus_sipre_session *)arg;
3243
        char reason[256];
3244
        reason[0] = '\0';
3245
        if(msg->reason.l > 0) {
3246
                g_snprintf(reason, (msg->reason.l < 255 ? msg->reason.l+1 : 255), "%s", msg->reason.p);
3247
        }
3248
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] Session progress: %u %s\n", session->account.username, msg->scode, reason);
3249
        /* FIXME Anything we should do with this? Notify the user? */
3250
}
3251

    
3252
/* Called upon incoming INVITEs */
3253
void janus_sipre_cb_incoming(const struct sip_msg *msg, void *arg) {
3254
        janus_sipre_session *session = (janus_sipre_session *)arg;
3255
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] janus_sipre_cb_incoming (%p)\n", session->account.username, session);
3256
        /* Increase the reference to the msg instance, as we'll need it either
3257
         * to reply with an error right away, or for a success/error later */
3258
        mem_ref((struct sip_msg *)msg);
3259
        /* Parse a few relevant identifiers */
3260
        char *from = NULL;
3261
        re_sdprintf(&from, "%H", uri_encode, &msg->from.uri);
3262
        JANUS_LOG(LOG_HUGE, "[SIPre-%s]   -- Caller: %s\n", session->account.username, from);
3263
        char dname[256];
3264
        dname[0] = '\0';
3265
        if(msg->from.dname.l > 0) {
3266
                g_snprintf(dname, sizeof(dname), "%.*s", (int)msg->from.dname.l, msg->from.dname.p);
3267
                JANUS_LOG(LOG_HUGE, "[SIPre-%s]   -- Display: %s\n", session->account.username, dname);
3268
        }
3269
        char callid[256];
3270
        g_snprintf(callid, sizeof(callid), "%.*s", (int)msg->callid.l, msg->callid.p);
3271
        JANUS_LOG(LOG_HUGE, "[SIPre-%s]   -- Call-ID: %s\n", session->account.username, callid);
3272
        /* Make sure we're not in a call already */
3273
        if(session->stack.sess != NULL) {
3274
                /* Already in a call */
3275
                JANUS_LOG(LOG_VERB, "Already in a call (busy, status=%s)\n", janus_sipre_call_status_string(session->status));
3276
                mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 486, session));
3277
                /* Notify the web app about the missed invite */
3278
                json_t *missed = json_object();
3279
                json_object_set_new(missed, "sip", json_string("event"));
3280
                json_t *result = json_object();
3281
                json_object_set_new(result, "event", json_string("missed_call"));
3282
                json_object_set_new(result, "caller", json_string(from));
3283
                if(strlen(dname)) {
3284
                        json_object_set_new(result, "displayname", json_string(dname));
3285
                }
3286
                json_object_set_new(missed, "result", result);
3287
                if(!session->destroyed) {
3288
                        int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, missed, NULL);
3289
                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3290
                }
3291
                json_decref(missed);
3292
                /* Also notify event handlers */
3293
                if(notify_events && gateway->events_is_enabled()) {
3294
                        json_t *info = json_object();
3295
                        json_object_set_new(info, "event", json_string("missed_call"));
3296
                        json_object_set_new(info, "caller", json_string(from));
3297
                        gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3298
                }
3299
                return;
3300
        }
3301
        /* New incoming call, check if there's an SDP to process */
3302
        char sdp_offer[1024];
3303
        janus_sdp *sdp = NULL;
3304
        const char *offer = (const char *)mbuf_buf(msg->mb);
3305
        if(offer == NULL || mbuf_get_left(msg->mb) == 0) {
3306
                JANUS_LOG(LOG_WARN, "[SIPre-%s] Received offerless INVITE\n", session->account.username);
3307
        } else {
3308
                g_snprintf(sdp_offer, sizeof(sdp_offer), "%.*s", (int)mbuf_get_left(msg->mb), offer);
3309
                JANUS_LOG(LOG_WARN, "[SIPre-%s]   -- Offer: %s\n", session->account.username, sdp_offer);
3310
                /* Parse the remote SDP */
3311
                char sdperror[100];
3312
                sdp = janus_sdp_parse(sdp_offer, sdperror, sizeof(sdperror));
3313
                if(!sdp) {
3314
                        JANUS_LOG(LOG_ERR, "Error parsing SDP! %s\n", sdperror);
3315
                        mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
3316
                        return;
3317
                }
3318
        }
3319
        session->callee = g_strdup(from);
3320
        session->callid = g_strdup(callid);
3321
        g_hash_table_insert(callids, session->callid, session);
3322
        session->status = janus_sipre_call_status_invited;
3323
        /* Clean up SRTP stuff from before first, in case it's still needed */
3324
        janus_sipre_srtp_cleanup(session);
3325
        /* Parse SDP */
3326
        JANUS_LOG(LOG_VERB, "Someone is inviting us a call\n");
3327
        if(sdp) {
3328
                gboolean changed = FALSE;
3329
                janus_sipre_sdp_process(session, sdp, FALSE, FALSE, &changed);
3330
                /* Check if offer has neither audio nor video, fail with 488 */
3331
                if(!session->media.has_audio && !session->media.has_video) {
3332
                        mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
3333
                        janus_sdp_free(sdp);
3334
                        return;
3335
                }
3336
                /* Also fail with 488 if there's no remote IP address that can be used for RTP */
3337
                if(!session->media.remote_ip) {
3338
                        mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
3339
                        janus_sdp_free(sdp);
3340
                        return;
3341
                }
3342
        }
3343
        session->stack.invite = msg;
3344
        /* Notify the browser about the call */
3345
        json_t *jsep = NULL;
3346
        if(sdp)
3347
                jsep = json_pack("{ssss}", "type", "offer", "sdp", sdp_offer);
3348
        json_t *call = json_object();
3349
        json_object_set_new(call, "sip", json_string("event"));
3350
        json_t *calling = json_object();
3351
        json_object_set_new(calling, "event", json_string("incomingcall"));
3352
        json_object_set_new(calling, "username", json_string(session->callee));
3353
        if(strlen(dname)) {
3354
                json_object_set_new(calling, "displayname", json_string(dname));
3355
        }
3356
        if(sdp && session->media.has_srtp_remote) {
3357
                /* FIXME Maybe a true/false instead? */
3358
                json_object_set_new(calling, "srtp", json_string(session->media.require_srtp ? "sdes_mandatory" : "sdes_optional"));
3359
        }
3360
        json_object_set_new(call, "result", calling);
3361
        if(!session->destroyed) {
3362
                int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, call, jsep);
3363
                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3364
        }
3365
        json_decref(call);
3366
        if(jsep)
3367
                json_decref(jsep);
3368
        janus_sdp_free(sdp);
3369
        /* Also notify event handlers */
3370
        if(notify_events && gateway->events_is_enabled()) {
3371
                json_t *info = json_object();
3372
                json_object_set_new(info, "event", json_string("incomingcall"));
3373
                if(session->callid)
3374
                        json_object_set_new(info, "call-id", json_string(session->callid));
3375
                json_object_set_new(info, "username", json_string(session->callee));
3376
                if(strlen(dname))
3377
                        json_object_set_new(info, "displayname", json_string(dname));
3378
                gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3379
        }
3380
        /* Send a Ringing back */
3381
        mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 180, NULL));
3382
}
3383

    
3384
/* Called when an SDP offer is received (re-INVITE) */
3385
int janus_sipre_cb_offer(struct mbuf **mbp, const struct sip_msg *msg, void *arg) {
3386
        janus_sipre_session *session = (janus_sipre_session *)arg;
3387
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] janus_sipre_cb_offer\n", session->account.username);
3388
        /* Get the SDP */
3389
        const char *offer = (const char *)mbuf_buf(msg->mb);
3390
        if(offer == NULL) {
3391
                /* No SDP? */
3392
                JANUS_LOG(LOG_WARN, "[SIPre-%s] No SDP in the re-INVITE?\n", session->account.username);
3393
                return EINVAL;
3394
        }
3395
        char sdp_offer[1024];
3396
        g_snprintf(sdp_offer, sizeof(sdp_offer), "%.*s", (int)mbuf_get_left(msg->mb), offer);
3397
        JANUS_LOG(LOG_VERB, "Someone is updating a call:\n%s", sdp_offer);
3398
        /* Parse the remote SDP */
3399
        char sdperror[100];
3400
        janus_sdp *sdp = janus_sdp_parse(sdp_offer, sdperror, sizeof(sdperror));
3401
        if(!sdp) {
3402
                JANUS_LOG(LOG_ERR, "Error parsing SDP! %s\n", sdperror);
3403
                return EINVAL;
3404
        }
3405
        gboolean changed = FALSE;
3406
        janus_sipre_sdp_process(session, sdp, FALSE, TRUE, &changed);
3407
        janus_sdp_free(sdp);
3408
        /* Check if offer has neither audio nor video, fail with 488 */
3409
        if (!session->media.has_audio && !session->media.has_video) {
3410
                mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
3411
                return EINVAL;
3412
        }
3413
        /* Also fail with 488 if there's no remote IP address that can be used for RTP */
3414
        if (!session->media.remote_ip) {
3415
                mqueue_push(mq, janus_sipre_mqueue_event_do_rcode, janus_sipre_mqueue_payload_create(session, msg, 488, NULL));
3416
                return EINVAL;
3417
        }
3418
        char *answer = janus_sdp_write(session->sdp);
3419
        JANUS_LOG(LOG_VERB, "Answering re-INVITE:\n%s", answer);
3420
        *mbp = mbuf_alloc(strlen(answer)+1);
3421
        mbuf_printf(*mbp, "%s", answer);
3422
        mbuf_set_pos(*mbp, 0);
3423
        return 0;
3424
}
3425

    
3426

    
3427
/* Called when an SDP answer is received */
3428
int janus_sipre_cb_answer(const struct sip_msg *msg, void *arg) {
3429
        janus_sipre_session *session = (janus_sipre_session *)arg;
3430
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] janus_sipre_cb_answer\n", session->account.username);
3431
        /* Get the SDP */
3432
        const char *answer = (const char *)mbuf_buf(msg->mb);
3433
        if(answer == NULL) {
3434
                /* No SDP? */
3435
                JANUS_LOG(LOG_WARN, "[SIPre-%s] No SDP in the answer?\n", session->account.username);
3436
                return EINVAL;
3437
        }
3438
        char sdp_answer[1024];
3439
        g_snprintf(sdp_answer, sizeof(sdp_answer), "%.*s", (int)mbuf_get_left(msg->mb), answer);
3440
        /* Parse the SDP */
3441
        char sdperror[100];
3442
        janus_sdp *sdp = janus_sdp_parse(sdp_answer, sdperror, sizeof(sdperror));
3443
        if(!sdp) {
3444
                JANUS_LOG(LOG_ERR, "Error parsing SDP! %s\n", sdperror);
3445
                return EINVAL;
3446
        }
3447
        /* Parse SDP */
3448
        JANUS_LOG(LOG_VERB, "Peer accepted our call:\n%s", sdp_answer);
3449
        session->status = janus_sipre_call_status_incall;
3450
        gboolean changed = FALSE;
3451
        gboolean update = session->media.ready;
3452
        janus_sipre_sdp_process(session, sdp, TRUE, update, &changed);
3453
        /* If we asked for SRTP and are not getting it, fail */
3454
        if(session->media.require_srtp && !session->media.has_srtp_remote) {
3455
                JANUS_LOG(LOG_ERR, "We asked for mandatory SRTP but didn't get any in the reply!\n");
3456
                janus_sdp_free(sdp);
3457
                /* Hangup immediately */
3458
                session->media.ready = FALSE;
3459
                session->media.on_hold = FALSE;
3460
                session->status = janus_sipre_call_status_closing;
3461
                mqueue_push(mq, janus_sipre_mqueue_event_do_bye, janus_sipre_mqueue_payload_create(session, msg, 0, NULL));
3462
                g_free(session->callee);
3463
                session->callee = NULL;
3464
                return EINVAL;
3465
        }
3466
        if(!session->media.remote_ip) {
3467
                /* No remote address parsed? Give up */
3468
                JANUS_LOG(LOG_ERR, "No remote IP address found for RTP, something's wrong with the SDP!\n");
3469
                janus_sdp_free(sdp);
3470
                /* Hangup immediately */
3471
                session->media.ready = FALSE;
3472
                session->media.on_hold = FALSE;
3473
                session->status = janus_sipre_call_status_closing;
3474
                mqueue_push(mq, janus_sipre_mqueue_event_do_bye, janus_sipre_mqueue_payload_create(session, msg, 0, NULL));
3475
                g_free(session->callee);
3476
                session->callee = NULL;
3477
                return EINVAL;
3478
        }
3479
        if(session->media.audio_pt > -1) {
3480
                session->media.audio_pt_name = janus_get_codec_from_pt(sdp_answer, session->media.audio_pt);
3481
                JANUS_LOG(LOG_VERB, "Detected audio codec: %d (%s)\n", session->media.audio_pt, session->media.audio_pt_name);
3482
        }
3483
        if(session->media.video_pt > -1) {
3484
                session->media.video_pt_name = janus_get_codec_from_pt(sdp_answer, session->media.video_pt);
3485
                JANUS_LOG(LOG_VERB, "Detected video codec: %d (%s)\n", session->media.video_pt, session->media.video_pt_name);
3486
        }
3487
        session->media.ready = TRUE;        /* FIXME Maybe we need a better way to signal this */
3488
        if(update) {
3489
                /* Don't push to the browser if this is in response to a hold/unhold we sent ourselves */
3490
                JANUS_LOG(LOG_WARN, "This is an update to an existing call (possibly in response to hold/unhold)\n");
3491
                return 0;
3492
        }
3493
        GError *error = NULL;
3494
        char tname[16];
3495
        g_snprintf(tname, sizeof(tname), "siprertp %s", session->account.username);
3496
        g_thread_try_new(tname, janus_sipre_relay_thread, session, &error);
3497
        if(error != NULL) {
3498
                JANUS_LOG(LOG_ERR, "Got error %d (%s) trying to launch the RTP/RTCP thread...\n", error->code, error->message ? error->message : "??");
3499
        }
3500
        /* Send SDP to the browser */
3501
        json_t *jsep = json_pack("{ssss}", "type", "answer", "sdp", sdp_answer);
3502
        json_t *call = json_object();
3503
        json_object_set_new(call, "sip", json_string("event"));
3504
        json_t *calling = json_object();
3505
        json_object_set_new(calling, "event", json_string("accepted"));
3506
        json_object_set_new(calling, "username", json_string(session->callee));
3507
        json_object_set_new(call, "result", calling);
3508
        if(!session->destroyed) {
3509
                int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, call, jsep);
3510
                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3511
        }
3512
        json_decref(call);
3513
        json_decref(jsep);
3514
        janus_sdp_free(sdp);
3515
        /* Also notify event handlers */
3516
        if(notify_events && gateway->events_is_enabled()) {
3517
                json_t *info = json_object();
3518
                json_object_set_new(info, "event", json_string("accepted"));
3519
                if(session->callid)
3520
                        json_object_set_new(info, "call-id", json_string(session->callid));
3521
                json_object_set_new(info, "username", json_string(session->callee));
3522
                gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3523
        }
3524

    
3525
        return 0;
3526
}
3527

    
3528
/* Called when the session is established */
3529
void janus_sipre_cb_established(const struct sip_msg *msg, void *arg) {
3530
        janus_sipre_session *session = (janus_sipre_session *)arg;
3531
        if(session == NULL) {
3532
                JANUS_LOG(LOG_WARN, "[SIPre-??] janus_sipre_cb_established\n");
3533
                return;
3534
        }
3535
        JANUS_LOG(LOG_HUGE, "[SIPre-%s] janus_sipre_cb_established\n", session->account.username);
3536
        /* FIXME Anything to do here? */
3537
}
3538

    
3539
/* Called when the session fails to connect or is terminated by the peer */
3540
void janus_sipre_cb_closed(int err, const struct sip_msg *msg, void *arg) {
3541
        janus_sipre_session *session = (janus_sipre_session *)arg;
3542
        if(session == NULL) {
3543
                JANUS_LOG(LOG_HUGE, "[SIPre-??] janus_sipre_cb_closed\n");
3544
                return;
3545
        }
3546
        if(err) {
3547
                JANUS_LOG(LOG_VERB, "[SIPre-%s] Session closed: %d %s\n", session->account.username, err, strerror(err));
3548
        } else {
3549
                JANUS_LOG(LOG_VERB, "[SIPre-%s] Session closed: %u %s\n", session->account.username, msg->scode, (char *)&msg->reason.p);
3550
        }
3551

    
3552
        /* Tell the browser... */
3553
        json_t *event = json_object();
3554
        json_object_set_new(event, "sip", json_string("event"));
3555
        json_t *result = json_object();
3556
        json_object_set_new(result, "event", json_string("hangup"));
3557
        json_object_set_new(result, "code", json_integer(err ? err : msg->scode));
3558
        char reason[256];
3559
        reason[0] = '\0';
3560
        if(!err && msg->reason.l > 0) {
3561
                g_snprintf(reason, (msg->reason.l < 255 ? msg->reason.l+1 : 255), "%s", msg->reason.p);
3562
        }
3563
        json_object_set_new(result, "reason", json_string(err ? strerror(err) : reason));
3564
        json_object_set_new(event, "result", result);
3565
        if(!session->destroyed) {
3566
                int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, event, NULL);
3567
                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3568
        }
3569
        json_decref(event);
3570
        /* Also notify event handlers */
3571
        if(notify_events && gateway->events_is_enabled()) {
3572
                json_t *info = json_object();
3573
                json_object_set_new(info, "event", json_string("hangup"));
3574
                json_object_set_new(info, "code", json_integer(err ? err : msg->scode));
3575
                json_object_set_new(info, "reason", json_string(err ? strerror(err) : reason));
3576
                gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3577
        }
3578

    
3579
        /* Cleanup */
3580
        mem_deref(session->stack.sess);
3581
        session->stack.sess = NULL;
3582
        session->media.ready = FALSE;
3583
        session->media.on_hold = FALSE;
3584
        session->status = janus_sipre_call_status_idle;
3585
}
3586

    
3587
/* Called when all SIP transactions are completed */
3588
void janus_sipre_cb_exit(void *arg) {
3589
        janus_sipre_session *session = (janus_sipre_session *)arg;
3590
        if(session == NULL) {
3591
                JANUS_LOG(LOG_HUGE, "[SIPre-??] janus_sipre_cb_exit\n");
3592
                return;
3593
        }
3594
        JANUS_LOG(LOG_INFO, "[SIPre-%s] Cleaning SIP stack\n", session->account.username);
3595
}
3596

    
3597
/* Callback to implement SIP requests in the re_main loop thread */
3598
void janus_sipre_mqueue_handler(int id, void *data, void *arg) {
3599
        JANUS_LOG(LOG_HUGE, "janus_sipre_mqueue_handler: %d (%s)\n", id, janus_sipre_mqueue_event_string((janus_sipre_mqueue_event)id));
3600
        switch((janus_sipre_mqueue_event)id) {
3601
                case janus_sipre_mqueue_event_do_init: {
3602
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3603
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3604
                        /* We need a DNS client */
3605
                        struct sa nsv[8];
3606
                        uint32_t nsn = ARRAY_SIZE(nsv);
3607
                        int err = dns_srv_get(NULL, 0, nsv, &nsn);
3608
                        if(err) {
3609
                                JANUS_LOG(LOG_ERR, "Failed to get the DNS servers list for the SIP stack: %d (%s)\n", err, strerror(err));
3610
                                g_free(payload);
3611
                                return;
3612
                        }
3613
                        err = dnsc_alloc(&session->stack.dns_client, NULL, nsv, nsn);
3614
                        if(err) {
3615
                                JANUS_LOG(LOG_ERR, "Failed to initialize the DNS client for the SIP stack: %d (%s)\n", err, strerror(err));
3616
                                g_free(payload);
3617
                                return;
3618
                        }
3619
                        /* Let's allocate the stack now */
3620
                        err = sip_alloc(&session->stack.sipstack, session->stack.dns_client, 32, 32, 32, JANUS_SIPRE_NAME, janus_sipre_cb_exit, session);
3621
                        if(err) {
3622
                                JANUS_LOG(LOG_ERR, "Failed to initialize libre SIP stack: %d (%s)\n", err, strerror(err));
3623
                                mem_deref(session->stack.dns_client);
3624
                                session->stack.dns_client = NULL;
3625
                                g_free(payload);
3626
                                return;
3627
                        }
3628
                        JANUS_LOG(LOG_INFO, "Initializing SIP transports\n");
3629
                        struct sa laddr, laddrs;
3630
                        sa_set_str(&laddr, local_ip, 0);
3631
                        sa_set_str(&laddrs, local_ip, 0);
3632
                        err = 0;
3633
                        err |= sip_transp_add(session->stack.sipstack, SIP_TRANSP_UDP, &laddr);
3634
                        err |= sip_transp_add(session->stack.sipstack, SIP_TRANSP_TCP, &laddr);
3635
                        if(err) {
3636
                                JANUS_LOG(LOG_ERR, "Failed to initialize libre SIP transports: %d (%s)\n", err, strerror(err));
3637
                                g_free(payload);
3638
                                return;
3639
                        }
3640
                        err = tls_alloc(&session->stack.tls, TLS_METHOD_SSLV23, NULL, NULL);
3641
                        err |= sip_transp_add(session->stack.sipstack, SIP_TRANSP_TLS, &laddrs, session->stack.tls);
3642
                        err |= sipsess_listen(&session->stack.sess_sock, session->stack.sipstack, 32, janus_sipre_cb_incoming, session);
3643
                        if(err) {
3644
                                mem_deref(session->stack.sipstack);
3645
                                session->stack.sipstack = NULL;
3646
                                mem_deref(session->stack.tls);
3647
                                session->stack.tls = NULL;
3648
                                JANUS_LOG(LOG_ERR, "Failed to initialize libre SIPS transports: %d (%s)\n", err, strerror(err));
3649
                                g_free(payload);
3650
                                return;
3651
                        }
3652
#ifdef HAVE_LIBRE_SIPTRACE
3653
                        if(gateway->events_is_enabled()) {
3654
                                /* Trace incoming/outgoing SIP messages */
3655
                                sip_set_trace(session->stack.sipstack, janus_sipre_msg_logger);
3656
                        }
3657
#endif
3658
                        mem_deref(session->stack.tls);
3659
                        session->stack.tls = NULL;
3660
                        g_free(payload);
3661
                        break;
3662
                }
3663
                case janus_sipre_mqueue_event_do_register:
3664
                case janus_sipre_mqueue_event_do_unregister: {
3665
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3666
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3667
                        /* Whether it's a REGISTER or an unregister, get rid of the previous instance */
3668
                        mem_deref(session->stack.reg);
3669
                        session->stack.reg = NULL;
3670
                        /* If it's an unregister, we're done */
3671
                        if(session->stack.expires == 0) {
3672
                                /* Notify the browser */
3673
                                json_t *event = json_object();
3674
                                json_object_set_new(event, "sip", json_string("event"));
3675
                                json_t *unreging = json_object();
3676
                                json_object_set_new(unreging, "event", json_string("unregistered"));
3677
                                json_object_set_new(unreging, "username", json_string(session->account.username));
3678
                                json_object_set_new(unreging, "register_sent", json_true());
3679
                                json_object_set_new(event, "result", unreging);
3680
                                if(!session->destroyed) {
3681
                                        int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, event, NULL);
3682
                                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3683
                                }
3684
                                json_decref(event);
3685
                                /* Also notify event handlers */
3686
                                if(notify_events && gateway->events_is_enabled()) {
3687
                                        json_t *info = json_object();
3688
                                        json_object_set_new(info, "event", json_string("unregistered"));
3689
                                        json_object_set_new(info, "identity", json_string(session->account.identity));
3690
                                        if(session->account.proxy)
3691
                                                json_object_set_new(info, "proxy", json_string(session->account.proxy));
3692
                                        gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3693
                                }
3694
                                break;
3695
                        }
3696
                        JANUS_LOG(LOG_VERB, "[SIPre-%s] Sending REGISTER\n", session->account.username);
3697
                        /* Check if there is an outbound proxy to take into account */
3698
                        const char *outbound_proxy[1];
3699
                        outbound_proxy[0] = session->account.outbound_proxy;
3700
                        /* Check if there are custom headers to add */
3701
                        char *headers = (char *)payload->data;
3702
                        /* Send the REGISTER */
3703
                        int err = sipreg_register(&session->stack.reg, session->stack.sipstack,
3704
                                session->account.proxy,
3705
                                session->account.identity, session->account.identity, session->stack.expires,
3706
                                session->account.username,
3707
                                outbound_proxy, (outbound_proxy[0] ? 1 : 0), 0,
3708
                                janus_sipre_cb_auth, session, FALSE,
3709
                                janus_sipre_cb_register, session, NULL, (headers ? headers : ""), NULL);
3710
                        g_free(headers);
3711
                        if(err != 0) {
3712
                                JANUS_LOG(LOG_ERR, "Error attempting to REGISTER: %d (%s)\n", err, strerror(err));
3713
                                /* Tell the browser... */
3714
                                json_t *event = json_object();
3715
                                json_object_set_new(event, "sip", json_string("event"));
3716
                                json_t *result = json_object();
3717
                                json_object_set_new(result, "event", json_string("registration_failed"));
3718
                                json_object_set_new(result, "code", json_integer(err));
3719
                                json_object_set_new(result, "reason", json_string(strerror(err)));
3720
                                json_object_set_new(event, "result", result);
3721
                                if(!session->destroyed) {
3722
                                        int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, event, NULL);
3723
                                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3724
                                }
3725
                                json_decref(event);
3726
                                /* Also notify event handlers */
3727
                                if(notify_events && gateway->events_is_enabled()) {
3728
                                        json_t *info = json_object();
3729
                                        json_object_set_new(info, "event", json_string("registration_failed"));
3730
                                        json_object_set_new(info, "code", json_integer(err));
3731
                                        json_object_set_new(info, "reason", json_string(strerror(err)));
3732
                                        gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3733
                                }
3734
                        }
3735
                        g_free(payload);
3736
                        break;
3737
                }
3738
                case janus_sipre_mqueue_event_do_call: {
3739
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3740
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3741
                        JANUS_LOG(LOG_VERB, "[SIPre-%s] Sending INVITE\n%s", session->account.username, session->temp_sdp);
3742
                        /* Check if there is an outbound proxy to take into account */
3743
                        const char *outbound_proxy[1];
3744
                        outbound_proxy[0] = session->account.outbound_proxy;
3745
                        /* Check if there are custom headers to add */
3746
                        char *headers = (char *)payload->data;
3747
                        /* Convert the SDP into a struct mbuf */
3748
                        struct mbuf *mb = mbuf_alloc(strlen(session->temp_sdp)+1);
3749
                        mbuf_printf(mb, "%s", session->temp_sdp);
3750
                        mbuf_set_pos(mb, 0);
3751
                        /* Send the INVITE */
3752
                        int err = sipsess_connect(&session->stack.sess, session->stack.sess_sock,
3753
                                session->callee,
3754
                                session->account.display_name, session->account.identity,
3755
                                session->account.username,
3756
                                outbound_proxy, (outbound_proxy[0] ? 1 : 0),
3757
                                "application/sdp", mb,
3758
                                janus_sipre_cb_auth, session, FALSE,
3759
                                janus_sipre_cb_offer, janus_sipre_cb_answer,
3760
                                janus_sipre_cb_progress, janus_sipre_cb_established,
3761
                                NULL, NULL, janus_sipre_cb_closed, session,
3762
                                "%s", (headers ? headers : ""));
3763
                        g_free(headers);
3764
                        if(err != 0) {
3765
                                JANUS_LOG(LOG_ERR, "Error attempting to INVITE: %d (%s)\n", err, strerror(err));
3766
                                /* Tell the browser... */
3767
                                json_t *event = json_object();
3768
                                json_object_set_new(event, "sip", json_string("event"));
3769
                                json_t *result = json_object();
3770
                                json_object_set_new(result, "event", json_string("hangup"));
3771
                                json_object_set_new(result, "code", json_integer(err));
3772
                                json_object_set_new(result, "reason", json_string(strerror(err)));
3773
                                json_object_set_new(event, "result", result);
3774
                                if(!session->destroyed) {
3775
                                        int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, event, NULL);
3776
                                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3777
                                }
3778
                                json_decref(event);
3779
                                /* Also notify event handlers */
3780
                                if(notify_events && gateway->events_is_enabled()) {
3781
                                        json_t *info = json_object();
3782
                                        json_object_set_new(info, "event", json_string("hangup"));
3783
                                        json_object_set_new(info, "code", json_integer(err));
3784
                                        json_object_set_new(info, "reason", json_string(strerror(err)));
3785
                                        gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3786
                                }
3787
                        }
3788
                        mem_deref(mb);
3789
                        g_free(session->temp_sdp);
3790
                        session->temp_sdp = NULL;
3791
                        g_free(payload);
3792
                        break;
3793
                }
3794
                case janus_sipre_mqueue_event_do_accept: {
3795
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3796
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3797
                        JANUS_LOG(LOG_VERB, "[SIPre-%s] Sending 200 OK\n%s", session->account.username, session->temp_sdp);
3798
                        /* Convert the SDP into a struct mbuf */
3799
                        struct mbuf *mb = mbuf_alloc(strlen(session->temp_sdp)+1);
3800
                        mbuf_printf(mb, "%s", session->temp_sdp);
3801
                        mbuf_set_pos(mb, 0);
3802
                        /* Send the 200 OK */
3803
                        int err = sipsess_answer(session->stack.sess, 200, "OK", mb, NULL);
3804
                        if(err != 0) {
3805
                                JANUS_LOG(LOG_ERR, "Error attempting to send the 200 OK: %d (%s)\n", err, strerror(err));
3806
                                /* Tell the browser... */
3807
                                json_t *event = json_object();
3808
                                json_object_set_new(event, "sip", json_string("event"));
3809
                                json_t *result = json_object();
3810
                                json_object_set_new(result, "event", json_string("hangup"));
3811
                                json_object_set_new(result, "code", json_integer(err));
3812
                                json_object_set_new(result, "reason", json_string(strerror(err)));
3813
                                json_object_set_new(event, "result", result);
3814
                                if(!session->destroyed) {
3815
                                        int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, event, NULL);
3816
                                        JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3817
                                }
3818
                                json_decref(event);
3819
                                /* Also notify event handlers */
3820
                                if(notify_events && gateway->events_is_enabled()) {
3821
                                        json_t *info = json_object();
3822
                                        json_object_set_new(info, "event", json_string("hangup"));
3823
                                        json_object_set_new(info, "code", json_integer(err));
3824
                                        json_object_set_new(info, "reason", json_string(strerror(err)));
3825
                                        gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3826
                                }
3827
                        }
3828
                        mem_deref(mb);
3829
                        g_free(session->temp_sdp);
3830
                        session->temp_sdp = NULL;
3831
                        g_free(payload);
3832
                        break;
3833
                }
3834
                case janus_sipre_mqueue_event_do_rcode: {
3835
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3836
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3837
                        JANUS_LOG(LOG_VERB, "[SIPre-%s] Sending response code %d\n", session->account.username, payload->rcode);
3838
                        /* Send the response code */
3839
                        int err = 0;
3840
                        if(session->stack.sess == NULL) {
3841
                                /* We still need to accept the connection */
3842
                                err = sipsess_accept(&session->stack.sess, session->stack.sess_sock,
3843
                                        session->stack.invite, payload->rcode, janus_sipre_error_reason(payload->rcode),
3844
                                        session->account.display_name ? session->account.display_name : session->account.username,
3845
                                        "application/sdp", NULL,
3846
                                        janus_sipre_cb_auth, session, FALSE,
3847
                                        janus_sipre_cb_offer, janus_sipre_cb_answer,
3848
                                        janus_sipre_cb_established, NULL, NULL,
3849
                                        janus_sipre_cb_closed, session, NULL);
3850
                        } else {
3851
                                /* Connection already accepted */
3852
                                if(payload->rcode < 200) {
3853
                                        /* 1xx */
3854
                                        err = sipsess_progress(session->stack.sess, payload->rcode, janus_sipre_error_reason(payload->rcode), NULL, NULL);
3855
                                } else if(payload->rcode < 300) {
3856
                                        /* 2xx */
3857
                                        err = sipsess_answer(session->stack.sess, payload->rcode, janus_sipre_error_reason(payload->rcode), NULL, NULL);
3858
                                } else {
3859
                                        /* 3xx, 4xx, 5xx, 6xx */
3860
                                        if(payload->data == NULL) {
3861
                                                /* Send an error message on the current call */
3862
                                                err = sipsess_reject(session->stack.sess, payload->rcode, janus_sipre_error_reason(payload->rcode), NULL);
3863
                                                session->media.ready = FALSE;
3864
                                                session->media.on_hold = FALSE;
3865
                                                session->status = janus_sipre_call_status_idle;
3866
                                        } else {
3867
                                                /* We're rejecting a new call because we're busy in another one: accept first and then reject */
3868
                                                struct sipsess *sess = NULL;
3869
                                                err = sipsess_accept(&sess, session->stack.sess_sock,
3870
                                                        payload->msg, 180, janus_sipre_error_reason(180),
3871
                                                        session->account.display_name ? session->account.display_name : session->account.username,
3872
                                                        "application/sdp", NULL,
3873
                                                        janus_sipre_cb_auth, session, FALSE,
3874
                                                        janus_sipre_cb_offer, janus_sipre_cb_answer,
3875
                                                        janus_sipre_cb_established, NULL, NULL,
3876
                                                        janus_sipre_cb_closed, session, NULL);
3877
                                                err = sipsess_reject(sess, payload->rcode, janus_sipre_error_reason(payload->rcode), NULL);
3878
                                        }
3879
                                }
3880
                        }
3881
                        if(err != 0) {
3882
                                JANUS_LOG(LOG_ERR, "Error attempting to send the %d error code: %d (%s)\n", payload->rcode, err, strerror(err));
3883
                        }
3884
                        if(payload->rcode > 399) {
3885
                                g_free(session->callee);
3886
                                session->callee = NULL;
3887
                                g_free(session->callid);
3888
                                session->callid = NULL;
3889
                                /* FIXME */
3890
                                session->stack.sess = NULL;
3891
                        }
3892
                        mem_deref((void *)payload->msg);
3893
                        g_free(payload);
3894
                        break;
3895
                }
3896
                case janus_sipre_mqueue_event_do_update: {
3897
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3898
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3899
                        JANUS_LOG(LOG_VERB, "[SIPre-%s] Sending SIP re-INVITE\n", session->account.username);
3900
                        /* Convert the SDP into a struct mbuf */
3901
                        struct mbuf *mb = mbuf_alloc(strlen(session->temp_sdp)+1);
3902
                        mbuf_printf(mb, "%s", session->temp_sdp);
3903
                        mbuf_set_pos(mb, 0);
3904
                        /* Send the INVITE */
3905
                        int err = sipsess_modify(session->stack.sess, mb);
3906
                        if(err != 0) {
3907
                                JANUS_LOG(LOG_ERR, "Error attempting to re-INVITE: %d (%s)\n", err, strerror(err));
3908
                        }
3909
                        mem_deref(mb);
3910
                        g_free(session->temp_sdp);
3911
                        session->temp_sdp = NULL;
3912
                        g_free(payload);
3913
                        break;
3914
                }
3915
                case janus_sipre_mqueue_event_do_sipinfo: {
3916
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3917
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3918
                        JANUS_LOG(LOG_VERB, "[SIPre-%s] Sending SIP INFO (DTMF): %s\n", session->account.username, (char *)payload->data);
3919
                        /* Convert the SDP into a struct mbuf */
3920
                        struct mbuf *mb = mbuf_alloc(strlen((char *)payload->data)+1);
3921
                        mbuf_printf(mb, "%s", (char *)payload->data);
3922
                        mbuf_set_pos(mb, 0);
3923
                        g_free(payload->data);
3924
                        /* Send the 200 OK */
3925
                        int err = sipsess_info(session->stack.sess, "application/dtmf-relay", mb, NULL, NULL);
3926
                        if(err != 0) {
3927
                                JANUS_LOG(LOG_ERR, "Error attempting to send the SIP INFO: %d (%s)\n", err, strerror(err));
3928
                                /* Tell the browser... */
3929
                                json_t *event = json_object();
3930
                                json_object_set_new(event, "sip", json_string("event"));
3931
                                json_t *result = json_object();
3932
                                json_object_set_new(result, "event", json_string("dtmferror"));
3933
                                json_object_set_new(result, "code", json_integer(err));
3934
                                json_object_set_new(result, "reason", json_string(strerror(err)));
3935
                                json_object_set_new(event, "result", result);
3936
                        }
3937
                        mem_deref(mb);
3938
                        g_free(payload);
3939
                        break;
3940
                }
3941
                case janus_sipre_mqueue_event_do_bye: {
3942
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3943
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3944
                        JANUS_LOG(LOG_VERB, "[SIPre-%s] Sending BYE\n", session->account.username);
3945
                        /* Send a BYE */
3946
                        mem_deref(session->stack.sess);
3947
                        session->stack.sess = NULL;
3948
                        g_free(session->callee);
3949
                        session->callee = NULL;
3950
                        g_free(payload);
3951
                        /* Tell the browser... */
3952
                        json_t *event = json_object();
3953
                        json_object_set_new(event, "sip", json_string("event"));
3954
                        json_t *result = json_object();
3955
                        json_object_set_new(result, "event", json_string("hangup"));
3956
                        json_object_set_new(result, "code", json_integer(200));
3957
                        json_object_set_new(result, "reason", json_string("BYE"));
3958
                        json_object_set_new(event, "result", result);
3959
                        if(!session->destroyed) {
3960
                                int ret = gateway->push_event(session->handle, &janus_sipre_plugin, session->transaction, event, NULL);
3961
                                JANUS_LOG(LOG_VERB, "  >> Pushing event to peer: %d (%s)\n", ret, janus_get_api_error(ret));
3962
                        }
3963
                        json_decref(event);
3964
                        /* Also notify event handlers */
3965
                        if(notify_events && gateway->events_is_enabled()) {
3966
                                json_t *info = json_object();
3967
                                json_object_set_new(info, "event", json_string("hangup"));
3968
                                json_object_set_new(info, "code", json_integer(200));
3969
                                json_object_set_new(info, "reason", json_string("BYE"));
3970
                                gateway->notify_event(&janus_sipre_plugin, session->handle, info);
3971
                        }
3972
                        session->media.ready = FALSE;
3973
                        session->media.on_hold = FALSE;
3974
                        session->status = janus_sipre_call_status_idle;
3975
                        break;
3976
                }
3977
                case janus_sipre_mqueue_event_do_destroy: {
3978
                        janus_sipre_mqueue_payload *payload = (janus_sipre_mqueue_payload *)data;
3979
                        janus_sipre_session *session = (janus_sipre_session *)payload->session;
3980
                        JANUS_LOG(LOG_VERB, "[SIPre-%s] Destroying session\n", session->account.username);
3981
                        /* FIXME How to correctly clean up? */
3982
                        mem_deref(session->stack.reg);
3983