1 /* $Id$ */
2 /*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include <pjsua-lib/pjsua.h>
21 #include <pjsua-lib/pjsua_internal.h>
22
23
24 #define THIS_FILE "pjsua_core.c"
25
26 #define DEFAULT_RTP_PORT 4000
27
28
29 /* Internal prototypes */
30 static void resolve_stun_entry(pjsua_stun_resolve *sess);
31
32
33 /* PJSUA application instance. */
34 struct pjsua_data pjsua_var;
35
36
pjsua_get_var(void)37 PJ_DEF(struct pjsua_data*) pjsua_get_var(void)
38 {
39 return &pjsua_var;
40 }
41
42
43 /* Display error */
pjsua_perror(const char * sender,const char * title,pj_status_t status)44 PJ_DEF(void) pjsua_perror( const char *sender, const char *title,
45 pj_status_t status)
46 {
47 char errmsg[PJ_ERR_MSG_SIZE];
48
49 pj_strerror(status, errmsg, sizeof(errmsg));
50 PJ_LOG(1,(sender, "%s: %s [status=%d]", title, errmsg, status));
51 }
52
53
init_data()54 static void init_data()
55 {
56 unsigned i;
57
58 pj_bzero(&pjsua_var, sizeof(pjsua_var));
59
60 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i)
61 pjsua_var.acc[i].index = i;
62
63 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i)
64 pjsua_var.tpdata[i].index = i;
65
66 pjsua_var.stun_status = PJ_EUNKNOWN;
67 pjsua_var.nat_status = PJ_EPENDING;
68 pj_list_init(&pjsua_var.stun_res);
69 pj_list_init(&pjsua_var.outbound_proxy);
70
71 pjsua_config_default(&pjsua_var.ua_cfg);
72
73 for (i=0; i<PJSUA_MAX_VID_WINS; ++i) {
74 pjsua_vid_win_reset(i);
75 }
76 }
77
78
pjsua_logging_config_default(pjsua_logging_config * cfg)79 PJ_DEF(void) pjsua_logging_config_default(pjsua_logging_config *cfg)
80 {
81 pj_bzero(cfg, sizeof(*cfg));
82
83 cfg->msg_logging = PJ_TRUE;
84 cfg->level = 5;
85 cfg->console_level = 4;
86 cfg->decor = PJ_LOG_HAS_SENDER | PJ_LOG_HAS_TIME |
87 PJ_LOG_HAS_MICRO_SEC | PJ_LOG_HAS_NEWLINE |
88 PJ_LOG_HAS_SPACE | PJ_LOG_HAS_THREAD_SWC |
89 PJ_LOG_HAS_INDENT;
90 #if (defined(PJ_WIN32) && PJ_WIN32 != 0) || (defined(PJ_WIN64) && PJ_WIN64 != 0)
91 cfg->decor |= PJ_LOG_HAS_COLOR;
92 #endif
93 }
94
pjsua_logging_config_dup(pj_pool_t * pool,pjsua_logging_config * dst,const pjsua_logging_config * src)95 PJ_DEF(void) pjsua_logging_config_dup(pj_pool_t *pool,
96 pjsua_logging_config *dst,
97 const pjsua_logging_config *src)
98 {
99 pj_memcpy(dst, src, sizeof(*src));
100 pj_strdup_with_null(pool, &dst->log_filename, &src->log_filename);
101 }
102
pjsua_config_default(pjsua_config * cfg)103 PJ_DEF(void) pjsua_config_default(pjsua_config *cfg)
104 {
105 pj_bzero(cfg, sizeof(*cfg));
106
107 cfg->max_calls = PJSUA_MAX_CALLS;
108 cfg->thread_cnt = PJSUA_SEPARATE_WORKER_FOR_TIMER? 2 : 1;
109 cfg->nat_type_in_sdp = 1;
110 cfg->stun_ignore_failure = PJ_TRUE;
111 cfg->force_lr = PJ_TRUE;
112 cfg->enable_unsolicited_mwi = PJ_TRUE;
113 cfg->use_srtp = PJSUA_DEFAULT_USE_SRTP;
114 cfg->srtp_secure_signaling = PJSUA_DEFAULT_SRTP_SECURE_SIGNALING;
115 cfg->hangup_forked_call = PJ_TRUE;
116
117 cfg->use_timer = PJSUA_SIP_TIMER_OPTIONAL;
118 pjsip_timer_setting_default(&cfg->timer_setting);
119 pjsua_srtp_opt_default(&cfg->srtp_opt);
120 }
121
pjsua_config_dup(pj_pool_t * pool,pjsua_config * dst,const pjsua_config * src)122 PJ_DEF(void) pjsua_config_dup(pj_pool_t *pool,
123 pjsua_config *dst,
124 const pjsua_config *src)
125 {
126 unsigned i;
127
128 pj_memcpy(dst, src, sizeof(*src));
129
130 for (i=0; i<src->outbound_proxy_cnt; ++i) {
131 pj_strdup_with_null(pool, &dst->outbound_proxy[i],
132 &src->outbound_proxy[i]);
133 }
134
135 for (i=0; i<src->cred_count; ++i) {
136 pjsip_cred_dup(pool, &dst->cred_info[i], &src->cred_info[i]);
137 }
138
139 pj_strdup_with_null(pool, &dst->user_agent, &src->user_agent);
140 pj_strdup_with_null(pool, &dst->stun_domain, &src->stun_domain);
141 pj_strdup_with_null(pool, &dst->stun_host, &src->stun_host);
142
143 for (i=0; i<src->stun_srv_cnt; ++i) {
144 pj_strdup_with_null(pool, &dst->stun_srv[i], &src->stun_srv[i]);
145 }
146
147 pjsua_srtp_opt_dup(pool, &dst->srtp_opt, &src->srtp_opt, PJ_FALSE);
148 }
149
pjsua_msg_data_init(pjsua_msg_data * msg_data)150 PJ_DEF(void) pjsua_msg_data_init(pjsua_msg_data *msg_data)
151 {
152 pj_bzero(msg_data, sizeof(*msg_data));
153 pj_list_init(&msg_data->hdr_list);
154 pjsip_media_type_init(&msg_data->multipart_ctype, NULL, NULL);
155 pj_list_init(&msg_data->multipart_parts);
156 }
157
pjsua_msg_data_clone(pj_pool_t * pool,const pjsua_msg_data * rhs)158 PJ_DEF(pjsua_msg_data*) pjsua_msg_data_clone(pj_pool_t *pool,
159 const pjsua_msg_data *rhs)
160 {
161 pjsua_msg_data *msg_data;
162 const pjsip_hdr *hdr;
163 const pjsip_multipart_part *mpart;
164
165 PJ_ASSERT_RETURN(pool && rhs, NULL);
166
167 msg_data = PJ_POOL_ZALLOC_T(pool, pjsua_msg_data);
168 PJ_ASSERT_RETURN(msg_data != NULL, NULL);
169
170 pj_strdup(pool, &msg_data->target_uri, &rhs->target_uri);
171
172 pj_list_init(&msg_data->hdr_list);
173 hdr = rhs->hdr_list.next;
174 while (hdr != &rhs->hdr_list) {
175 pj_list_push_back(&msg_data->hdr_list, pjsip_hdr_clone(pool, hdr));
176 hdr = hdr->next;
177 }
178
179 pj_strdup(pool, &msg_data->content_type, &rhs->content_type);
180 pj_strdup(pool, &msg_data->msg_body, &rhs->msg_body);
181
182 pjsip_media_type_cp(pool, &msg_data->multipart_ctype,
183 &rhs->multipart_ctype);
184
185 pj_list_init(&msg_data->multipart_parts);
186 mpart = rhs->multipart_parts.next;
187 while (mpart != &rhs->multipart_parts) {
188 pj_list_push_back(&msg_data->multipart_parts,
189 pjsip_multipart_clone_part(pool, mpart));
190 mpart = mpart->next;
191 }
192
193 return msg_data;
194 }
195
pjsua_transport_config_default(pjsua_transport_config * cfg)196 PJ_DEF(void) pjsua_transport_config_default(pjsua_transport_config *cfg)
197 {
198 pj_bzero(cfg, sizeof(*cfg));
199 pjsip_tls_setting_default(&cfg->tls_setting);
200 }
201
pjsua_transport_config_dup(pj_pool_t * pool,pjsua_transport_config * dst,const pjsua_transport_config * src)202 PJ_DEF(void) pjsua_transport_config_dup(pj_pool_t *pool,
203 pjsua_transport_config *dst,
204 const pjsua_transport_config *src)
205 {
206 pj_memcpy(dst, src, sizeof(*src));
207 pj_strdup(pool, &dst->public_addr, &src->public_addr);
208 pj_strdup(pool, &dst->bound_addr, &src->bound_addr);
209 }
210
pjsua_ice_config_from_media_config(pj_pool_t * pool,pjsua_ice_config * dst,const pjsua_media_config * src)211 PJ_DEF(void) pjsua_ice_config_from_media_config( pj_pool_t *pool,
212 pjsua_ice_config *dst,
213 const pjsua_media_config *src)
214 {
215 PJ_UNUSED_ARG(pool);
216
217 dst->enable_ice = src->enable_ice;
218 dst->ice_max_host_cands = src->ice_max_host_cands;
219 dst->ice_opt = src->ice_opt;
220 dst->ice_no_rtcp = src->ice_no_rtcp;
221 dst->ice_always_update = src->ice_always_update;
222 }
223
pjsua_ice_config_dup(pj_pool_t * pool,pjsua_ice_config * dst,const pjsua_ice_config * src)224 PJ_DEF(void) pjsua_ice_config_dup( pj_pool_t *pool,
225 pjsua_ice_config *dst,
226 const pjsua_ice_config *src)
227 {
228 PJ_UNUSED_ARG(pool);
229 pj_memcpy(dst, src, sizeof(*src));
230 }
231
pjsua_turn_config_from_media_config(pj_pool_t * pool,pjsua_turn_config * dst,const pjsua_media_config * src)232 PJ_DEF(void) pjsua_turn_config_from_media_config(pj_pool_t *pool,
233 pjsua_turn_config *dst,
234 const pjsua_media_config *src)
235 {
236 dst->enable_turn = src->enable_turn;
237 dst->turn_conn_type = src->turn_conn_type;
238 if (pool == NULL) {
239 dst->turn_server = src->turn_server;
240 dst->turn_auth_cred = src->turn_auth_cred;
241
242 #if PJ_HAS_SSL_SOCK
243 pj_memcpy(&dst->turn_tls_setting, &src->turn_tls_setting,
244 sizeof(src->turn_tls_setting));
245 #endif
246 } else {
247 if (pj_stricmp(&dst->turn_server, &src->turn_server))
248 pj_strdup(pool, &dst->turn_server, &src->turn_server);
249 pj_stun_auth_cred_dup(pool, &dst->turn_auth_cred,
250 &src->turn_auth_cred);
251
252 #if PJ_HAS_SSL_SOCK
253 pj_turn_sock_tls_cfg_dup(pool, &dst->turn_tls_setting,
254 &src->turn_tls_setting);
255 #endif
256 }
257 }
258
pjsua_turn_config_dup(pj_pool_t * pool,pjsua_turn_config * dst,const pjsua_turn_config * src)259 PJ_DEF(void) pjsua_turn_config_dup(pj_pool_t *pool,
260 pjsua_turn_config *dst,
261 const pjsua_turn_config *src)
262 {
263 pj_memcpy(dst, src, sizeof(*src));
264 if (pool) {
265 pj_strdup(pool, &dst->turn_server, &src->turn_server);
266 pj_stun_auth_cred_dup(pool, &dst->turn_auth_cred,
267 &src->turn_auth_cred);
268
269 #if PJ_HAS_SSL_SOCK
270 pj_turn_sock_tls_cfg_dup(pool, &dst->turn_tls_setting,
271 &src->turn_tls_setting);
272 #endif
273 }
274 }
275
276
pjsua_srtp_opt_default(pjsua_srtp_opt * cfg)277 PJ_DEF(void) pjsua_srtp_opt_default(pjsua_srtp_opt *cfg)
278 {
279 pj_bzero(cfg, sizeof(*cfg));
280 }
281
282
pjsua_srtp_opt_dup(pj_pool_t * pool,pjsua_srtp_opt * dst,const pjsua_srtp_opt * src,pj_bool_t check_str)283 PJ_DEF(void) pjsua_srtp_opt_dup( pj_pool_t *pool, pjsua_srtp_opt *dst,
284 const pjsua_srtp_opt *src,
285 pj_bool_t check_str)
286 {
287 pjsua_srtp_opt backup_dst;
288
289 if (check_str) pj_memcpy(&backup_dst, dst, sizeof(*dst));
290 pj_memcpy(dst, src, sizeof(*src));
291
292 if (pool) {
293 unsigned i;
294
295 for (i = 0; i < src->crypto_count; i++) {
296 if (!check_str ||
297 pj_stricmp(&backup_dst.crypto[i].key, &src->crypto[i].key))
298 {
299 pj_strdup(pool, &dst->crypto[i].key, &src->crypto[i].key);
300 } else {
301 /* If strings are identical, use the old string to
302 * avoid wasting memory.
303 */
304 dst->crypto[i].key = backup_dst.crypto[i].key;
305 }
306 if (!check_str ||
307 pj_stricmp(&backup_dst.crypto[i].name, &src->crypto[i].name))
308 {
309 pj_strdup(pool, &dst->crypto[i].name, &src->crypto[i].name);
310 } else {
311 /* If strings are identical, use the old string to
312 * avoid wasting memory.
313 */
314 dst->crypto[i].name = backup_dst.crypto[i].name;
315 }
316 }
317 }
318 }
319
320
pjsua_acc_config_default(pjsua_acc_config * cfg)321 PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg)
322 {
323 pjsua_media_config med_cfg;
324
325 pj_bzero(cfg, sizeof(*cfg));
326
327 cfg->reg_timeout = PJSUA_REG_INTERVAL;
328 cfg->reg_delay_before_refresh = PJSIP_REGISTER_CLIENT_DELAY_BEFORE_REFRESH;
329 cfg->unreg_timeout = PJSUA_UNREG_TIMEOUT;
330 pjsip_publishc_opt_default(&cfg->publish_opt);
331 cfg->unpublish_max_wait_time_msec = PJSUA_UNPUBLISH_MAX_WAIT_TIME_MSEC;
332 cfg->transport_id = PJSUA_INVALID_ID;
333 cfg->allow_contact_rewrite = PJ_TRUE;
334 cfg->allow_via_rewrite = PJ_TRUE;
335 cfg->require_100rel = pjsua_var.ua_cfg.require_100rel;
336 cfg->use_timer = pjsua_var.ua_cfg.use_timer;
337 cfg->timer_setting = pjsua_var.ua_cfg.timer_setting;
338 cfg->lock_codec = 1;
339 cfg->ka_interval = 15;
340 cfg->ka_data = pj_str("\r\n");
341 cfg->vid_cap_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
342 cfg->vid_rend_dev = PJMEDIA_VID_DEFAULT_RENDER_DEV;
343 #if PJMEDIA_HAS_VIDEO
344 pjmedia_vid_stream_rc_config_default(&cfg->vid_stream_rc_cfg);
345 pjmedia_vid_stream_sk_config_default(&cfg->vid_stream_sk_cfg);
346 #endif
347 pjsua_transport_config_default(&cfg->rtp_cfg);
348 cfg->rtp_cfg.port = DEFAULT_RTP_PORT;
349 pjmedia_rtcp_fb_setting_default(&cfg->rtcp_fb_cfg);
350
351 pjsua_media_config_default(&med_cfg);
352 pjsua_ice_config_from_media_config(NULL, &cfg->ice_cfg, &med_cfg);
353 pjsua_turn_config_from_media_config(NULL, &cfg->turn_cfg, &med_cfg);
354
355 cfg->use_srtp = pjsua_var.ua_cfg.use_srtp;
356 cfg->srtp_secure_signaling = pjsua_var.ua_cfg.srtp_secure_signaling;
357 cfg->srtp_optional_dup_offer = pjsua_var.ua_cfg.srtp_optional_dup_offer;
358 cfg->srtp_opt = pjsua_var.ua_cfg.srtp_opt;
359 cfg->reg_retry_interval = PJSUA_REG_RETRY_INTERVAL;
360 cfg->reg_retry_random_interval = 10;
361 cfg->contact_rewrite_method = PJSUA_CONTACT_REWRITE_METHOD;
362 cfg->contact_use_src_port = PJ_TRUE;
363 cfg->use_rfc5626 = PJ_TRUE;
364 cfg->reg_use_proxy = PJSUA_REG_USE_OUTBOUND_PROXY |
365 PJSUA_REG_USE_ACC_PROXY;
366 #if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
367 cfg->use_stream_ka = (PJMEDIA_STREAM_ENABLE_KA != 0);
368 pjmedia_stream_ka_config_default(&cfg->stream_ka_cfg);
369 #endif
370 pj_list_init(&cfg->reg_hdr_list);
371 pj_list_init(&cfg->sub_hdr_list);
372 cfg->call_hold_type = PJSUA_CALL_HOLD_TYPE_DEFAULT;
373 cfg->register_on_acc_add = PJ_TRUE;
374 cfg->mwi_expires = PJSIP_MWI_DEFAULT_EXPIRES;
375
376 cfg->media_stun_use = PJSUA_STUN_RETRY_ON_FAILURE;
377 cfg->ip_change_cfg.shutdown_tp = PJ_TRUE;
378 cfg->ip_change_cfg.hangup_calls = PJ_FALSE;
379 cfg->ip_change_cfg.reinvite_flags = PJSUA_CALL_REINIT_MEDIA |
380 PJSUA_CALL_UPDATE_CONTACT |
381 PJSUA_CALL_UPDATE_VIA;
382 }
383
pjsua_buddy_config_default(pjsua_buddy_config * cfg)384 PJ_DEF(void) pjsua_buddy_config_default(pjsua_buddy_config *cfg)
385 {
386 pj_bzero(cfg, sizeof(*cfg));
387 }
388
pjsua_media_config_default(pjsua_media_config * cfg)389 PJ_DEF(void) pjsua_media_config_default(pjsua_media_config *cfg)
390 {
391 const pj_sys_info *si = pj_get_sys_info();
392 pj_str_t dev_model = {"iPhone5", 7};
393
394 pj_bzero(cfg, sizeof(*cfg));
395
396 cfg->clock_rate = PJSUA_DEFAULT_CLOCK_RATE;
397 /* It is reported that there may be some media server resampling problem
398 * with iPhone 5 devices running iOS 7, so we set the sound device's
399 * clock rate to 44100 to avoid resampling.
400 */
401 if (pj_stristr(&si->machine, &dev_model) &&
402 ((si->os_ver & 0xFF000000) >> 24) >= 7)
403 {
404 cfg->snd_clock_rate = 44100;
405 } else {
406 cfg->snd_clock_rate = 0;
407 }
408 cfg->channel_count = 1;
409 cfg->audio_frame_ptime = PJSUA_DEFAULT_AUDIO_FRAME_PTIME;
410 cfg->max_media_ports = PJSUA_MAX_CONF_PORTS;
411 cfg->has_ioqueue = PJ_TRUE;
412 cfg->thread_cnt = 1;
413 cfg->quality = PJSUA_DEFAULT_CODEC_QUALITY;
414 cfg->ilbc_mode = PJSUA_DEFAULT_ILBC_MODE;
415 cfg->ec_tail_len = PJSUA_DEFAULT_EC_TAIL_LEN;
416 cfg->snd_rec_latency = PJMEDIA_SND_DEFAULT_REC_LATENCY;
417 cfg->snd_play_latency = PJMEDIA_SND_DEFAULT_PLAY_LATENCY;
418 cfg->jb_init = cfg->jb_min_pre = cfg->jb_max_pre = cfg->jb_max = -1;
419 cfg->jb_discard_algo = PJMEDIA_JB_DISCARD_PROGRESSIVE;
420 cfg->snd_auto_close_time = 1;
421
422 cfg->ice_max_host_cands = -1;
423 cfg->ice_always_update = PJ_TRUE;
424 pj_ice_sess_options_default(&cfg->ice_opt);
425
426 cfg->turn_conn_type = PJ_TURN_TP_UDP;
427 #if PJ_HAS_SSL_SOCK
428 pj_turn_sock_tls_cfg_default(&cfg->turn_tls_setting);
429 #endif
430 cfg->vid_preview_enable_native = PJ_TRUE;
431 }
432
433 /*****************************************************************************
434 * This is a very simple PJSIP module, whose sole purpose is to display
435 * incoming and outgoing messages to log. This module will have priority
436 * higher than transport layer, which means:
437 *
438 * - incoming messages will come to this module first before reaching
439 * transaction layer.
440 *
441 * - outgoing messages will come to this module last, after the message
442 * has been 'printed' to contiguous buffer by transport layer and
443 * appropriate transport instance has been decided for this message.
444 *
445 */
446
447 /* Notification on incoming messages */
logging_on_rx_msg(pjsip_rx_data * rdata)448 static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
449 {
450 char addr[PJ_INET6_ADDRSTRLEN+10];
451 pj_str_t input_str = pj_str(rdata->pkt_info.src_name);
452
453 PJ_LOG(4,(THIS_FILE, "RX %d bytes %s from %s %s:\n"
454 "%.*s\n"
455 "--end msg--",
456 rdata->msg_info.len,
457 pjsip_rx_data_get_info(rdata),
458 rdata->tp_info.transport->type_name,
459 pj_addr_str_print(&input_str,
460 rdata->pkt_info.src_port,
461 addr,
462 sizeof(addr),
463 1),
464 (int)rdata->msg_info.len,
465 rdata->msg_info.msg_buf));
466
467 /* Always return false, otherwise messages will not get processed! */
468 return PJ_FALSE;
469 }
470
471 /* Notification on outgoing messages */
logging_on_tx_msg(pjsip_tx_data * tdata)472 static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
473 {
474 char addr[PJ_INET6_ADDRSTRLEN+10];
475 pj_str_t input_str = pj_str(tdata->tp_info.dst_name);
476
477 /* Important note:
478 * tp_info field is only valid after outgoing messages has passed
479 * transport layer. So don't try to access tp_info when the module
480 * has lower priority than transport layer.
481 */
482 PJ_LOG(4,(THIS_FILE, "TX %d bytes %s to %s %s:\n"
483 "%.*s\n"
484 "--end msg--",
485 (tdata->buf.cur - tdata->buf.start),
486 pjsip_tx_data_get_info(tdata),
487 tdata->tp_info.transport->type_name,
488 pj_addr_str_print(&input_str,
489 tdata->tp_info.dst_port,
490 addr,
491 sizeof(addr),
492 1),
493 (int)(tdata->buf.cur - tdata->buf.start),
494 tdata->buf.start));
495
496
497 /* Always return success, otherwise message will not get sent! */
498 return PJ_SUCCESS;
499 }
500
501 /* The module instance. */
502 static pjsip_module pjsua_msg_logger =
503 {
504 NULL, NULL, /* prev, next. */
505 { "mod-pjsua-log", 13 }, /* Name. */
506 -1, /* Id */
507 PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority */
508 NULL, /* load() */
509 NULL, /* start() */
510 NULL, /* stop() */
511 NULL, /* unload() */
512 &logging_on_rx_msg, /* on_rx_request() */
513 &logging_on_rx_msg, /* on_rx_response() */
514 &logging_on_tx_msg, /* on_tx_request. */
515 &logging_on_tx_msg, /* on_tx_response() */
516 NULL, /* on_tsx_state() */
517
518 };
519
520
521 /*****************************************************************************
522 * Another simple module to handle incoming OPTIONS request
523 */
524
525 /* Notification on incoming request */
options_on_rx_request(pjsip_rx_data * rdata)526 static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
527 {
528 pjsip_tx_data *tdata;
529 pjsip_response_addr res_addr;
530 const pjsip_hdr *cap_hdr;
531 pj_status_t status;
532
533 /* Only want to handle OPTIONS requests */
534 if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
535 pjsip_get_options_method()) != 0)
536 {
537 return PJ_FALSE;
538 }
539
540 /* Don't want to handle if shutdown is in progress */
541 if (pjsua_var.thread_quit_flag) {
542 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,
543 PJSIP_SC_TEMPORARILY_UNAVAILABLE, NULL,
544 NULL, NULL);
545 return PJ_TRUE;
546 }
547
548 /* Create basic response. */
549 status = pjsip_endpt_create_response(pjsua_var.endpt, rdata, 200, NULL,
550 &tdata);
551 if (status != PJ_SUCCESS) {
552 pjsua_perror(THIS_FILE, "Unable to create OPTIONS response", status);
553 return PJ_TRUE;
554 }
555
556 /* Add Allow header */
557 cap_hdr = pjsip_endpt_get_capability(pjsua_var.endpt, PJSIP_H_ALLOW, NULL);
558 if (cap_hdr) {
559 pjsip_msg_add_hdr(tdata->msg,
560 (pjsip_hdr*) pjsip_hdr_clone(tdata->pool, cap_hdr));
561 }
562
563 /* Add Accept header */
564 cap_hdr = pjsip_endpt_get_capability(pjsua_var.endpt, PJSIP_H_ACCEPT, NULL);
565 if (cap_hdr) {
566 pjsip_msg_add_hdr(tdata->msg,
567 (pjsip_hdr*) pjsip_hdr_clone(tdata->pool, cap_hdr));
568 }
569
570 /* Add Supported header */
571 cap_hdr = pjsip_endpt_get_capability(pjsua_var.endpt, PJSIP_H_SUPPORTED, NULL);
572 if (cap_hdr) {
573 pjsip_msg_add_hdr(tdata->msg,
574 (pjsip_hdr*) pjsip_hdr_clone(tdata->pool, cap_hdr));
575 }
576
577 /* Add Allow-Events header from the evsub module */
578 cap_hdr = pjsip_evsub_get_allow_events_hdr(NULL);
579 if (cap_hdr) {
580 pjsip_msg_add_hdr(tdata->msg,
581 (pjsip_hdr*) pjsip_hdr_clone(tdata->pool, cap_hdr));
582 }
583
584 /* Add User-Agent header */
585 if (pjsua_var.ua_cfg.user_agent.slen) {
586 const pj_str_t USER_AGENT = { "User-Agent", 10};
587 pjsip_hdr *h;
588
589 h = (pjsip_hdr*) pjsip_generic_string_hdr_create(tdata->pool,
590 &USER_AGENT,
591 &pjsua_var.ua_cfg.user_agent);
592 pjsip_msg_add_hdr(tdata->msg, h);
593 }
594
595 /* Get media socket info, make sure transport is ready */
596 #if DISABLED_FOR_TICKET_1185
597 if (pjsua_var.calls[0].med_tp) {
598 pjmedia_transport_info tpinfo;
599 pjmedia_sdp_session *sdp;
600
601 pjmedia_transport_info_init(&tpinfo);
602 pjmedia_transport_get_info(pjsua_var.calls[0].med_tp, &tpinfo);
603
604 /* Add SDP body, using call0's RTP address */
605 status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, tdata->pool, 1,
606 &tpinfo.sock_info, &sdp);
607 if (status == PJ_SUCCESS) {
608 pjsip_create_sdp_body(tdata->pool, sdp, &tdata->msg->body);
609 }
610 }
611 #endif
612
613 /* Send response */
614 pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
615 status = pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, tdata, NULL, NULL);
616 if (status != PJ_SUCCESS)
617 pjsip_tx_data_dec_ref(tdata);
618
619 return PJ_TRUE;
620 }
621
622
623 /* The module instance. */
624 static pjsip_module pjsua_options_handler =
625 {
626 NULL, NULL, /* prev, next. */
627 { "mod-pjsua-options", 17 }, /* Name. */
628 -1, /* Id */
629 PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
630 NULL, /* load() */
631 NULL, /* start() */
632 NULL, /* stop() */
633 NULL, /* unload() */
634 &options_on_rx_request, /* on_rx_request() */
635 NULL, /* on_rx_response() */
636 NULL, /* on_tx_request. */
637 NULL, /* on_tx_response() */
638 NULL, /* on_tsx_state() */
639
640 };
641
642
643 /*****************************************************************************
644 * These two functions are the main callbacks registered to PJSIP stack
645 * to receive SIP request and response messages that are outside any
646 * dialogs and any transactions.
647 */
648
649 /*
650 * Handler for receiving incoming requests.
651 *
652 * This handler serves multiple purposes:
653 * - it receives requests outside dialogs.
654 * - it receives requests inside dialogs, when the requests are
655 * unhandled by other dialog usages. Example of these
656 * requests are: MESSAGE.
657 */
mod_pjsua_on_rx_request(pjsip_rx_data * rdata)658 static pj_bool_t mod_pjsua_on_rx_request(pjsip_rx_data *rdata)
659 {
660 pj_bool_t processed = PJ_FALSE;
661
662 PJSUA_LOCK();
663
664 if (rdata->msg_info.msg->line.req.method.id == PJSIP_INVITE_METHOD) {
665
666 processed = pjsua_call_on_incoming(rdata);
667 }
668
669 PJSUA_UNLOCK();
670
671 return processed;
672 }
673
674
675 /*
676 * Handler for receiving incoming responses.
677 *
678 * This handler serves multiple purposes:
679 * - it receives strayed responses (i.e. outside any dialog and
680 * outside any transactions).
681 * - it receives responses coming to a transaction, when pjsua
682 * module is set as transaction user for the transaction.
683 * - it receives responses inside a dialog, when these responses
684 * are unhandled by other dialog usages.
685 */
mod_pjsua_on_rx_response(pjsip_rx_data * rdata)686 static pj_bool_t mod_pjsua_on_rx_response(pjsip_rx_data *rdata)
687 {
688 PJ_UNUSED_ARG(rdata);
689 return PJ_FALSE;
690 }
691
692
693 /*****************************************************************************
694 * Logging.
695 */
696
697 /* Log callback */
log_writer(int level,const char * buffer,int len)698 static void log_writer(int level, const char *buffer, int len)
699 {
700 /* Write to file, stdout or application callback. */
701
702 if (pjsua_var.log_file) {
703 pj_ssize_t size = len;
704 pj_file_write(pjsua_var.log_file, buffer, &size);
705 /* This will slow things down considerably! Don't do it!
706 pj_file_flush(pjsua_var.log_file);
707 */
708 }
709
710 if (level <= (int)pjsua_var.log_cfg.console_level) {
711 if (pjsua_var.log_cfg.cb)
712 (*pjsua_var.log_cfg.cb)(level, buffer, len);
713 else
714 pj_log_write(level, buffer, len);
715 }
716 }
717
718
719 /*
720 * Application can call this function at any time (after pjsua_create(), of
721 * course) to change logging settings.
722 */
pjsua_reconfigure_logging(const pjsua_logging_config * cfg)723 PJ_DEF(pj_status_t) pjsua_reconfigure_logging(const pjsua_logging_config *cfg)
724 {
725 pj_status_t status;
726
727 /* Save config. */
728 pjsua_logging_config_dup(pjsua_var.pool, &pjsua_var.log_cfg, cfg);
729
730 /* Redirect log function to ours */
731 pj_log_set_log_func( &log_writer );
732
733 /* Set decor */
734 pj_log_set_decor(pjsua_var.log_cfg.decor);
735
736 /* Set log level */
737 pj_log_set_level(pjsua_var.log_cfg.level);
738
739 /* Close existing file, if any */
740 if (pjsua_var.log_file) {
741 pj_file_close(pjsua_var.log_file);
742 pjsua_var.log_file = NULL;
743 }
744
745 /* If output log file is desired, create the file: */
746 if (pjsua_var.log_cfg.log_filename.slen) {
747 unsigned flags = PJ_O_WRONLY;
748 flags |= pjsua_var.log_cfg.log_file_flags;
749 status = pj_file_open(pjsua_var.pool,
750 pjsua_var.log_cfg.log_filename.ptr,
751 flags,
752 &pjsua_var.log_file);
753
754 if (status != PJ_SUCCESS) {
755 pjsua_perror(THIS_FILE, "Error creating log file", status);
756 return status;
757 }
758 }
759
760 /* Unregister msg logging if it's previously registered */
761 if (pjsua_msg_logger.id >= 0) {
762 pjsip_endpt_unregister_module(pjsua_var.endpt, &pjsua_msg_logger);
763 pjsua_msg_logger.id = -1;
764 }
765
766 /* Enable SIP message logging */
767 if (pjsua_var.log_cfg.msg_logging)
768 pjsip_endpt_register_module(pjsua_var.endpt, &pjsua_msg_logger);
769
770 return PJ_SUCCESS;
771 }
772
773
774 /*****************************************************************************
775 * PJSUA Base API.
776 */
777
778 /* Worker thread function. */
worker_thread(void * arg)779 static int worker_thread(void *arg)
780 {
781 enum { TIMEOUT = 10 };
782
783 PJ_UNUSED_ARG(arg);
784
785 while (!pjsua_var.thread_quit_flag) {
786 int count;
787
788 count = pjsua_handle_events(TIMEOUT);
789 if (count < 0)
790 pj_thread_sleep(TIMEOUT);
791 }
792
793 return 0;
794 }
795
796 #if PJSUA_SEPARATE_WORKER_FOR_TIMER
797
798 /* Timer heap worker thread function. */
worker_thread_timer(void * arg)799 static int worker_thread_timer(void *arg)
800 {
801 pj_timer_heap_t *th;
802
803 PJ_UNUSED_ARG(arg);
804
805 th = pjsip_endpt_get_timer_heap(pjsua_var.endpt);
806 while (!pjsua_var.thread_quit_flag) {
807 pj_time_val timeout = {0, 0};
808 int c;
809
810 c = pj_timer_heap_poll(th, &timeout);
811 if (c == 0) {
812 /* Sleep if no event */
813 enum { MAX_SLEEP_MS = 100 };
814 if (PJ_TIME_VAL_MSEC(timeout) < MAX_SLEEP_MS)
815 pj_thread_sleep(PJ_TIME_VAL_MSEC(timeout));
816 else
817 pj_thread_sleep(MAX_SLEEP_MS);
818 }
819 }
820 return 0;
821 }
822
823 /* Ioqueue worker thread function. */
worker_thread_ioqueue(void * arg)824 static int worker_thread_ioqueue(void *arg)
825 {
826 pj_ioqueue_t *ioq;
827
828 PJ_UNUSED_ARG(arg);
829
830 ioq = pjsip_endpt_get_ioqueue(pjsua_var.endpt);
831 while (!pjsua_var.thread_quit_flag) {
832 pj_time_val timeout = {0, 100};
833 pj_ioqueue_poll(ioq, &timeout);
834 }
835 return 0;
836 }
837
838 #endif
839
pjsua_stop_worker_threads(void)840 PJ_DEF(void) pjsua_stop_worker_threads(void)
841 {
842 unsigned i;
843
844 pjsua_var.thread_quit_flag = 1;
845
846 /* Wait worker threads to quit: */
847 for (i=0; i<(int)pjsua_var.ua_cfg.thread_cnt; ++i) {
848 if (pjsua_var.thread[i]) {
849 pj_status_t status;
850 status = pj_thread_join(pjsua_var.thread[i]);
851 if (status != PJ_SUCCESS) {
852 PJ_PERROR(4,(THIS_FILE, status, "Error joining worker thread"));
853 pj_thread_sleep(1000);
854 }
855 pj_thread_destroy(pjsua_var.thread[i]);
856 pjsua_var.thread[i] = NULL;
857 }
858 }
859 }
860
861 /* Init random seed */
init_random_seed(void)862 static void init_random_seed(void)
863 {
864 pj_sockaddr addr;
865 const pj_str_t *hostname;
866 pj_uint32_t pid;
867 pj_time_val t;
868 unsigned seed=0;
869
870 /* Add hostname */
871 hostname = pj_gethostname();
872 seed = pj_hash_calc(seed, hostname->ptr, (int)hostname->slen);
873
874 /* Add primary IP address */
875 if (pj_gethostip(pj_AF_INET(), &addr)==PJ_SUCCESS)
876 seed = pj_hash_calc(seed, &addr.ipv4.sin_addr, 4);
877
878 /* Get timeofday */
879 pj_gettimeofday(&t);
880 seed = pj_hash_calc(seed, &t, sizeof(t));
881
882 /* Add PID */
883 pid = pj_getpid();
884 seed = pj_hash_calc(seed, &pid, sizeof(pid));
885
886 /* Init random seed */
887 pj_srand(seed);
888 }
889
890 /*
891 * Instantiate pjsua application.
892 */
pjsua_create(void)893 PJ_DEF(pj_status_t) pjsua_create(void)
894 {
895 pj_status_t status;
896
897 /* Init pjsua data */
898 init_data();
899
900 /* Set default logging settings */
901 pjsua_logging_config_default(&pjsua_var.log_cfg);
902
903 /* Init PJLIB: */
904 status = pj_init();
905 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
906
907 pj_log_push_indent();
908
909 /* Init random seed */
910 init_random_seed();
911
912 /* Init PJLIB-UTIL: */
913 status = pjlib_util_init();
914 if (status != PJ_SUCCESS) {
915 pj_log_pop_indent();
916 pjsua_perror(THIS_FILE, "Failed in initializing pjlib-util", status);
917 pj_shutdown();
918 return status;
919 }
920
921 /* Init PJNATH */
922 status = pjnath_init();
923 if (status != PJ_SUCCESS) {
924 pj_log_pop_indent();
925 pjsua_perror(THIS_FILE, "Failed in initializing pjnath", status);
926 pj_shutdown();
927 return status;
928 }
929
930 /* Set default sound device ID */
931 pjsua_var.cap_dev = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV;
932 pjsua_var.play_dev = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV;
933
934 /* Set default video device ID */
935 pjsua_var.vcap_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;
936 pjsua_var.vrdr_dev = PJMEDIA_VID_DEFAULT_RENDER_DEV;
937
938 /* Init caching pool. */
939 pj_caching_pool_init(&pjsua_var.cp, NULL, 0);
940
941 /* Create memory pools for application and internal use. */
942 pjsua_var.pool = pjsua_pool_create("pjsua", PJSUA_POOL_LEN, PJSUA_POOL_INC);
943 pjsua_var.timer_pool = pjsua_pool_create("pjsua_timer", 500, 500);
944 if (pjsua_var.pool == NULL || pjsua_var.timer_pool == NULL) {
945 pj_log_pop_indent();
946 status = PJ_ENOMEM;
947 pjsua_perror(THIS_FILE, "Unable to create pjsua/timer pool", status);
948 pj_shutdown();
949 return status;
950 }
951
952 /* Create mutex */
953 status = pj_mutex_create_recursive(pjsua_var.pool, "pjsua",
954 &pjsua_var.mutex);
955 if (status != PJ_SUCCESS) {
956 pj_log_pop_indent();
957 pjsua_perror(THIS_FILE, "Unable to create mutex", status);
958 pjsua_destroy();
959 return status;
960 }
961
962 /* Must create SIP endpoint to initialize SIP parser. The parser
963 * is needed for example when application needs to call pjsua_verify_url().
964 */
965 status = pjsip_endpt_create(&pjsua_var.cp.factory,
966 pj_gethostname()->ptr,
967 &pjsua_var.endpt);
968 if (status != PJ_SUCCESS) {
969 pj_log_pop_indent();
970 pjsua_perror(THIS_FILE, "Unable to create endpoint", status);
971 pjsua_destroy();
972 return status;
973 }
974
975 /* Init timer entry and event list */
976 pj_list_init(&pjsua_var.active_timer_list);
977 pj_list_init(&pjsua_var.timer_list);
978 pj_list_init(&pjsua_var.event_list);
979
980 /* Create timer mutex */
981 status = pj_mutex_create_recursive(pjsua_var.pool, "pjsua_timer",
982 &pjsua_var.timer_mutex);
983 if (status != PJ_SUCCESS) {
984 pj_log_pop_indent();
985 pjsua_perror(THIS_FILE, "Unable to create mutex", status);
986 pjsua_destroy();
987 return status;
988 }
989
990 pjsua_set_state(PJSUA_STATE_CREATED);
991 pj_log_pop_indent();
992 return PJ_SUCCESS;
993 }
994
995
996 /*
997 * Initialize pjsua with the specified settings. All the settings are
998 * optional, and the default values will be used when the config is not
999 * specified.
1000 */
pjsua_init(const pjsua_config * ua_cfg,const pjsua_logging_config * log_cfg,const pjsua_media_config * media_cfg)1001 PJ_DEF(pj_status_t) pjsua_init( const pjsua_config *ua_cfg,
1002 const pjsua_logging_config *log_cfg,
1003 const pjsua_media_config *media_cfg)
1004 {
1005 pjsua_config default_cfg;
1006 pjsua_media_config default_media_cfg;
1007 const pj_str_t STR_OPTIONS = { "OPTIONS", 7 };
1008 pjsip_ua_init_param ua_init_param;
1009 unsigned i;
1010 pj_status_t status;
1011
1012 pj_log_push_indent();
1013
1014 /* Create default configurations when the config is not supplied */
1015
1016 if (ua_cfg == NULL) {
1017 pjsua_config_default(&default_cfg);
1018 ua_cfg = &default_cfg;
1019 }
1020
1021 if (media_cfg == NULL) {
1022 pjsua_media_config_default(&default_media_cfg);
1023 media_cfg = &default_media_cfg;
1024 }
1025
1026 /* Initialize logging first so that info/errors can be captured */
1027 if (log_cfg) {
1028 status = pjsua_reconfigure_logging(log_cfg);
1029 if (status != PJ_SUCCESS)
1030 goto on_error;
1031 }
1032
1033 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
1034 PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT != 0
1035 if (!(pj_get_sys_info()->flags & PJ_SYS_HAS_IOS_BG)) {
1036 PJ_LOG(5, (THIS_FILE, "Device does not support "
1037 "background mode"));
1038 pj_activesock_enable_iphone_os_bg(PJ_FALSE);
1039 }
1040 #endif
1041
1042 /* If nameserver is configured, create DNS resolver instance and
1043 * set it to be used by SIP resolver.
1044 */
1045 if (ua_cfg->nameserver_count) {
1046 #if PJSIP_HAS_RESOLVER
1047 unsigned ii;
1048
1049 /* Create DNS resolver */
1050 status = pjsip_endpt_create_resolver(pjsua_var.endpt,
1051 &pjsua_var.resolver);
1052 if (status != PJ_SUCCESS) {
1053 pjsua_perror(THIS_FILE, "Error creating resolver", status);
1054 goto on_error;
1055 }
1056
1057 /* Configure nameserver for the DNS resolver */
1058 status = pj_dns_resolver_set_ns(pjsua_var.resolver,
1059 ua_cfg->nameserver_count,
1060 ua_cfg->nameserver, NULL);
1061 if (status != PJ_SUCCESS) {
1062 pjsua_perror(THIS_FILE, "Error setting nameserver", status);
1063 goto on_error;
1064 }
1065
1066 /* Set this DNS resolver to be used by the SIP resolver */
1067 status = pjsip_endpt_set_resolver(pjsua_var.endpt, pjsua_var.resolver);
1068 if (status != PJ_SUCCESS) {
1069 pjsua_perror(THIS_FILE, "Error setting DNS resolver", status);
1070 goto on_error;
1071 }
1072
1073 /* Print nameservers */
1074 for (ii=0; ii<ua_cfg->nameserver_count; ++ii) {
1075 PJ_LOG(4,(THIS_FILE, "Nameserver %.*s added",
1076 (int)ua_cfg->nameserver[ii].slen,
1077 ua_cfg->nameserver[ii].ptr));
1078 }
1079 #else
1080 PJ_LOG(2,(THIS_FILE,
1081 "DNS resolver is disabled (PJSIP_HAS_RESOLVER==0)"));
1082 #endif
1083 }
1084
1085 /* Init SIP UA: */
1086
1087 /* Initialize transaction layer: */
1088 status = pjsip_tsx_layer_init_module(pjsua_var.endpt);
1089 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
1090
1091
1092 /* Initialize UA layer module: */
1093 pj_bzero(&ua_init_param, sizeof(ua_init_param));
1094 if (ua_cfg->hangup_forked_call) {
1095 ua_init_param.on_dlg_forked = &on_dlg_forked;
1096 }
1097 status = pjsip_ua_init_module( pjsua_var.endpt, &ua_init_param);
1098 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
1099
1100
1101 /* Initialize Replaces support. */
1102 status = pjsip_replaces_init_module( pjsua_var.endpt );
1103 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
1104
1105 /* Initialize 100rel support */
1106 status = pjsip_100rel_init_module(pjsua_var.endpt);
1107 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
1108
1109 /* Initialize session timer support */
1110 status = pjsip_timer_init_module(pjsua_var.endpt);
1111 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
1112
1113 /* Initialize and register PJSUA application module. */
1114 {
1115 const pjsip_module mod_initializer =
1116 {
1117 NULL, NULL, /* prev, next. */
1118 { "mod-pjsua", 9 }, /* Name. */
1119 -1, /* Id */
1120 PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
1121 NULL, /* load() */
1122 NULL, /* start() */
1123 NULL, /* stop() */
1124 NULL, /* unload() */
1125 &mod_pjsua_on_rx_request, /* on_rx_request() */
1126 &mod_pjsua_on_rx_response, /* on_rx_response() */
1127 NULL, /* on_tx_request. */
1128 NULL, /* on_tx_response() */
1129 NULL, /* on_tsx_state() */
1130 };
1131
1132 pjsua_var.mod = mod_initializer;
1133
1134 status = pjsip_endpt_register_module(pjsua_var.endpt, &pjsua_var.mod);
1135 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
1136 }
1137
1138 /* Parse outbound proxies */
1139 for (i=0; i<ua_cfg->outbound_proxy_cnt; ++i) {
1140 pj_str_t tmp;
1141 pj_str_t hname = { "Route", 5};
1142 pjsip_route_hdr *r;
1143
1144 pj_strdup_with_null(pjsua_var.pool, &tmp, &ua_cfg->outbound_proxy[i]);
1145
1146 r = (pjsip_route_hdr*)
1147 pjsip_parse_hdr(pjsua_var.pool, &hname, tmp.ptr,
1148 (unsigned)tmp.slen, NULL);
1149 if (r == NULL) {
1150 pjsua_perror(THIS_FILE, "Invalid outbound proxy URI",
1151 PJSIP_EINVALIDURI);
1152 status = PJSIP_EINVALIDURI;
1153 goto on_error;
1154 }
1155
1156 if (pjsua_var.ua_cfg.force_lr) {
1157 pjsip_sip_uri *sip_url;
1158 if (!PJSIP_URI_SCHEME_IS_SIP(r->name_addr.uri) &&
1159 !PJSIP_URI_SCHEME_IS_SIPS(r->name_addr.uri))
1160 {
1161 status = PJSIP_EINVALIDSCHEME;
1162 goto on_error;
1163 }
1164 sip_url = (pjsip_sip_uri*)r->name_addr.uri;
1165 sip_url->lr_param = 1;
1166 }
1167
1168 pj_list_push_back(&pjsua_var.outbound_proxy, r);
1169 }
1170
1171
1172 /* Initialize PJSUA call subsystem: */
1173 status = pjsua_call_subsys_init(ua_cfg);
1174 if (status != PJ_SUCCESS)
1175 goto on_error;
1176
1177 /* Convert deprecated STUN settings */
1178 if (pjsua_var.ua_cfg.stun_srv_cnt==0) {
1179 if (pjsua_var.ua_cfg.stun_domain.slen) {
1180 pjsua_var.ua_cfg.stun_srv[pjsua_var.ua_cfg.stun_srv_cnt++] =
1181 pjsua_var.ua_cfg.stun_domain;
1182 }
1183 if (pjsua_var.ua_cfg.stun_host.slen) {
1184 pjsua_var.ua_cfg.stun_srv[pjsua_var.ua_cfg.stun_srv_cnt++] =
1185 pjsua_var.ua_cfg.stun_host;
1186 }
1187 }
1188
1189 /* Start resolving STUN server */
1190 status = resolve_stun_server(PJ_FALSE, PJ_FALSE, 0);
1191 if (status != PJ_SUCCESS && status != PJ_EPENDING) {
1192 pjsua_perror(THIS_FILE, "Error resolving STUN server", status);
1193 goto on_error;
1194 }
1195
1196 /* Initialize PJSUA media subsystem */
1197 status = pjsua_media_subsys_init(media_cfg);
1198 if (status != PJ_SUCCESS)
1199 goto on_error;
1200
1201
1202 /* Init core SIMPLE module : */
1203 status = pjsip_evsub_init_module(pjsua_var.endpt);
1204 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
1205
1206
1207 /* Init presence module: */
1208 status = pjsip_pres_init_module( pjsua_var.endpt, pjsip_evsub_instance());
1209 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
1210
1211 /* Initialize MWI support */
1212 status = pjsip_mwi_init_module(pjsua_var.endpt, pjsip_evsub_instance());
1213
1214 /* Init PUBLISH module */
1215 pjsip_publishc_init_module(pjsua_var.endpt);
1216
1217 /* Init xfer/REFER module */
1218 status = pjsip_xfer_init_module( pjsua_var.endpt );
1219 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
1220
1221 /* Init pjsua presence handler: */
1222 status = pjsua_pres_init();
1223 if (status != PJ_SUCCESS)
1224 goto on_error;
1225
1226 /* Init out-of-dialog MESSAGE request handler. */
1227 status = pjsua_im_init();
1228 if (status != PJ_SUCCESS)
1229 goto on_error;
1230
1231 /* Register OPTIONS handler */
1232 pjsip_endpt_register_module(pjsua_var.endpt, &pjsua_options_handler);
1233
1234 /* Add OPTIONS in Allow header */
1235 pjsip_endpt_add_capability(pjsua_var.endpt, NULL, PJSIP_H_ALLOW,
1236 NULL, 1, &STR_OPTIONS);
1237
1238 /* Start worker thread if needed. */
1239 if (pjsua_var.ua_cfg.thread_cnt) {
1240 unsigned ii;
1241
1242 if (pjsua_var.ua_cfg.thread_cnt > PJ_ARRAY_SIZE(pjsua_var.thread))
1243 pjsua_var.ua_cfg.thread_cnt = PJ_ARRAY_SIZE(pjsua_var.thread);
1244
1245 #if PJSUA_SEPARATE_WORKER_FOR_TIMER
1246 if (pjsua_var.ua_cfg.thread_cnt < 2)
1247 pjsua_var.ua_cfg.thread_cnt = 2;
1248 #endif
1249
1250 for (ii=0; ii<pjsua_var.ua_cfg.thread_cnt; ++ii) {
1251 char tname[16];
1252
1253 pj_ansi_snprintf(tname, sizeof(tname), "pjsua_%d", ii);
1254
1255 #if PJSUA_SEPARATE_WORKER_FOR_TIMER
1256 if (ii == 0) {
1257 status = pj_thread_create(pjsua_var.pool, tname,
1258 &worker_thread_timer,
1259 NULL, 0, 0, &pjsua_var.thread[ii]);
1260 } else {
1261 status = pj_thread_create(pjsua_var.pool, tname,
1262 &worker_thread_ioqueue,
1263 NULL, 0, 0, &pjsua_var.thread[ii]);
1264 }
1265 #else
1266 status = pj_thread_create(pjsua_var.pool, tname, &worker_thread,
1267 NULL, 0, 0, &pjsua_var.thread[ii]);
1268 #endif
1269 if (status != PJ_SUCCESS)
1270 goto on_error;
1271 }
1272 PJ_LOG(4,(THIS_FILE, "%d SIP worker threads created",
1273 pjsua_var.ua_cfg.thread_cnt));
1274 } else {
1275 PJ_LOG(4,(THIS_FILE, "No SIP worker threads created"));
1276 }
1277
1278 /* Done! */
1279
1280 PJ_LOG(3,(THIS_FILE, "pjsua version %s for %s initialized",
1281 pj_get_version(), pj_get_sys_info()->info.ptr));
1282
1283 pjsua_set_state(PJSUA_STATE_INIT);
1284 pj_log_pop_indent();
1285 return PJ_SUCCESS;
1286
1287 on_error:
1288 pj_log_pop_indent();
1289 return status;
1290 }
1291
1292
1293 /* Sleep with polling */
busy_sleep(unsigned msec)1294 static void busy_sleep(unsigned msec)
1295 {
1296 pj_time_val timeout, now;
1297
1298 pj_gettickcount(&timeout);
1299 timeout.msec += msec;
1300 pj_time_val_normalize(&timeout);
1301
1302 do {
1303 int i;
1304 i = msec / 10;
1305 while (pjsua_handle_events(10) > 0 && i > 0)
1306 --i;
1307 pj_gettickcount(&now);
1308 } while (PJ_TIME_VAL_LT(now, timeout));
1309 }
1310
stun_resolve_add_ref(pjsua_stun_resolve * sess)1311 static void stun_resolve_add_ref(pjsua_stun_resolve *sess)
1312 {
1313 ++sess->ref_cnt;
1314 }
1315
1316
release_stun_session(pjsua_stun_resolve * sess)1317 static void release_stun_session(pjsua_stun_resolve *sess)
1318 {
1319 PJSUA_LOCK();
1320 pj_list_erase(sess);
1321 PJSUA_UNLOCK();
1322
1323 pj_assert(sess->stun_sock==NULL);
1324 pj_pool_release(sess->pool);
1325 }
1326
destroy_stun_resolve_cb(pj_timer_heap_t * t,pj_timer_entry * e)1327 static void destroy_stun_resolve_cb(pj_timer_heap_t *t, pj_timer_entry *e)
1328 {
1329 pjsua_stun_resolve *sess = (pjsua_stun_resolve*)e->user_data;
1330 PJ_UNUSED_ARG(t);
1331
1332 release_stun_session(sess);
1333 }
1334
1335
destroy_stun_resolve(pjsua_stun_resolve * sess,pj_bool_t forced)1336 static void destroy_stun_resolve(pjsua_stun_resolve *sess, pj_bool_t forced)
1337 {
1338 pj_time_val timeout = {0, 0};
1339
1340 if (sess->destroy_flag)
1341 return;
1342
1343 sess->destroy_flag = PJ_TRUE;
1344 if (sess->stun_sock) {
1345 pj_stun_sock_destroy(sess->stun_sock);
1346 sess->stun_sock = NULL;
1347 }
1348
1349 if (pjsua_var.stun_status == PJ_EUNKNOWN ||
1350 pjsua_var.stun_status == PJ_EPENDING)
1351 {
1352 pjsua_var.stun_status = PJNATH_ESTUNDESTROYED;
1353 }
1354
1355 if (forced) {
1356 release_stun_session(sess);
1357 } else {
1358 /* Schedule session clean up, it needs PJSUA lock and locking it here
1359 * may cause deadlock as this function may be called by STUN socket
1360 * while holding STUN socket lock, while application may wait for STUN
1361 * resolution while holding PJSUA lock.
1362 */
1363 pj_timer_entry_init(&sess->timer, 0, (void*)sess,
1364 &destroy_stun_resolve_cb);
1365 pjsua_schedule_timer(&sess->timer, &timeout);
1366 }
1367 }
1368
stun_resolve_dec_ref(pjsua_stun_resolve * sess)1369 static void stun_resolve_dec_ref(pjsua_stun_resolve *sess)
1370 {
1371 int ref_cnt = --sess->ref_cnt;
1372 /* If the STUN resolution session is blocking, only the waiting thread
1373 * is allowed to destroy the session, otherwise it may cause deadlock.
1374 */
1375 if ((ref_cnt > 0) ||
1376 (sess->blocking && (sess->waiter != pj_thread_this())))
1377 {
1378 return;
1379 }
1380
1381 destroy_stun_resolve(sess, PJ_FALSE);
1382 }
1383
1384
1385 /* This is the internal function to be called when STUN resolution
1386 * session (pj_stun_resolve) has completed.
1387 */
stun_resolve_complete(pjsua_stun_resolve * sess)1388 static void stun_resolve_complete(pjsua_stun_resolve *sess)
1389 {
1390 pj_stun_resolve_result result;
1391
1392 if (sess->has_result)
1393 goto on_return;
1394
1395 pj_bzero(&result, sizeof(result));
1396 result.token = sess->token;
1397 result.status = sess->status;
1398 result.name = sess->srv[sess->idx];
1399 result.index = sess->idx;
1400 pj_memcpy(&result.addr, &sess->addr, sizeof(result.addr));
1401 sess->has_result = PJ_TRUE;
1402
1403 if (result.status == PJ_SUCCESS) {
1404 char addr[PJ_INET6_ADDRSTRLEN+10];
1405 pj_sockaddr_print(&result.addr, addr, sizeof(addr), 3);
1406 PJ_LOG(4,(THIS_FILE,
1407 "STUN resolution success, using %.*s, address is %s",
1408 (int)sess->srv[sess->idx].slen,
1409 sess->srv[sess->idx].ptr,
1410 addr));
1411 } else {
1412 char errmsg[PJ_ERR_MSG_SIZE];
1413 pj_strerror(result.status, errmsg, sizeof(errmsg));
1414 PJ_LOG(1,(THIS_FILE, "STUN resolution failed: %s", errmsg));
1415 }
1416
1417 sess->cb(&result);
1418
1419 on_return:
1420 if (!sess->blocking) {
1421 stun_resolve_dec_ref(sess);
1422 }
1423 }
1424
1425 /* This is the callback called by the STUN socket (pj_stun_sock)
1426 * to report it's state. We use this as part of testing the
1427 * STUN server.
1428 */
test_stun_on_status(pj_stun_sock * stun_sock,pj_stun_sock_op op,pj_status_t status)1429 static pj_bool_t test_stun_on_status(pj_stun_sock *stun_sock,
1430 pj_stun_sock_op op,
1431 pj_status_t status)
1432 {
1433 pjsua_stun_resolve *sess;
1434
1435 sess = (pjsua_stun_resolve*) pj_stun_sock_get_user_data(stun_sock);
1436 pj_assert(stun_sock == sess->stun_sock);
1437
1438 if (status != PJ_SUCCESS) {
1439 char errmsg[PJ_ERR_MSG_SIZE];
1440 pj_strerror(status, errmsg, sizeof(errmsg));
1441
1442 PJ_LOG(4,(THIS_FILE, "STUN resolution for %.*s failed: %s",
1443 (int)sess->srv[sess->idx].slen,
1444 sess->srv[sess->idx].ptr, errmsg));
1445
1446 if (op == PJ_STUN_SOCK_BINDING_OP && !sess->async_wait) {
1447 /* Just return here, we will destroy the STUN socket and
1448 * continue the STUN resolution later in resolve_stun_entry().
1449 * For more details, please refer to ticket #1962.
1450 */
1451 return PJ_FALSE;
1452 }
1453
1454 pj_stun_sock_destroy(stun_sock);
1455 sess->stun_sock = NULL;
1456
1457 stun_resolve_add_ref(sess);
1458
1459 if (pjsua_var.ua_cfg.stun_try_ipv6 && sess->af == pj_AF_INET()) {
1460 sess->af = pj_AF_INET6();
1461 } else {
1462 ++sess->idx;
1463 sess->af = pj_AF_INET();
1464 if (sess->idx >= sess->count)
1465 sess->status = status;
1466 }
1467
1468 resolve_stun_entry(sess);
1469
1470 stun_resolve_dec_ref(sess);
1471
1472 return PJ_FALSE;
1473
1474 } else if (op == PJ_STUN_SOCK_BINDING_OP) {
1475 pj_stun_sock_info ssi;
1476
1477 pj_stun_sock_get_info(stun_sock, &ssi);
1478 pj_memcpy(&sess->addr, &ssi.srv_addr, sizeof(sess->addr));
1479
1480 stun_resolve_add_ref(sess);
1481
1482 sess->status = PJ_SUCCESS;
1483 pj_stun_sock_destroy(stun_sock);
1484 sess->stun_sock = NULL;
1485
1486 stun_resolve_complete(sess);
1487
1488 stun_resolve_dec_ref(sess);
1489
1490 return PJ_FALSE;
1491
1492 } else
1493 return PJ_TRUE;
1494
1495 }
1496
1497 /* This is an internal function to resolve and test current
1498 * server entry in pj_stun_resolve session. It is called by
1499 * pjsua_resolve_stun_servers() and test_stun_on_status() above
1500 */
resolve_stun_entry(pjsua_stun_resolve * sess)1501 static void resolve_stun_entry(pjsua_stun_resolve *sess)
1502 {
1503 pj_status_t status = PJ_EUNKNOWN;
1504
1505 /* Loop while we have entry to try */
1506 for (; sess->idx < sess->count;
1507 (pjsua_var.ua_cfg.stun_try_ipv6 && sess->af == pj_AF_INET())?
1508 sess->af = pj_AF_INET6(): (++sess->idx, sess->af = pj_AF_INET()))
1509 {
1510 int af;
1511 char target[64];
1512 pj_str_t hostpart;
1513 pj_uint16_t port;
1514 pj_stun_sock_cb stun_sock_cb;
1515
1516 pj_assert(sess->idx < sess->count);
1517
1518 if (pjsua_var.ua_cfg.stun_try_ipv6 &&
1519 pjsua_var.stun_opt != PJSUA_NAT64_DISABLED &&
1520 sess->af == pj_AF_INET())
1521 {
1522 /* Skip IPv4 STUN resolution if NAT64 is not disabled. */
1523 PJ_LOG(4,(THIS_FILE, "Skipping IPv4 resolution of STUN server "
1524 "%s (%d of %d)", target,
1525 sess->idx+1, sess->count));
1526 continue;
1527 }
1528
1529 pj_ansi_snprintf(target, sizeof(target), "%.*s",
1530 (int)sess->srv[sess->idx].slen,
1531 sess->srv[sess->idx].ptr);
1532
1533 /* Parse the server entry into host:port */
1534 status = pj_sockaddr_parse2(pj_AF_UNSPEC(), 0, &sess->srv[sess->idx],
1535 &hostpart, &port, &af);
1536 if (status != PJ_SUCCESS) {
1537 PJ_LOG(2,(THIS_FILE, "Invalid STUN server entry %s", target));
1538 continue;
1539 }
1540
1541 /* Use default port if not specified */
1542 if (port == 0)
1543 port = PJ_STUN_PORT;
1544
1545 pj_assert(sess->stun_sock == NULL);
1546
1547 PJ_LOG(4,(THIS_FILE, "Trying STUN server %s %s (%d of %d)..",
1548 target, (sess->af == pj_AF_INET()? "IPv4": "IPv6"),
1549 sess->idx+1, sess->count));
1550
1551 /* Use STUN_sock to test this entry */
1552 pj_bzero(&stun_sock_cb, sizeof(stun_sock_cb));
1553 stun_sock_cb.on_status = &test_stun_on_status;
1554 sess->async_wait = PJ_FALSE;
1555 status = pj_stun_sock_create(&pjsua_var.stun_cfg, "stunresolve",
1556 sess->af, &stun_sock_cb,
1557 NULL, sess, &sess->stun_sock);
1558 if (status != PJ_SUCCESS) {
1559 char errmsg[PJ_ERR_MSG_SIZE];
1560 pj_strerror(status, errmsg, sizeof(errmsg));
1561 PJ_LOG(4,(THIS_FILE,
1562 "Error creating STUN socket for %s: %s",
1563 target, errmsg));
1564
1565 continue;
1566 }
1567
1568 status = pj_stun_sock_start(sess->stun_sock, &hostpart, port,
1569 pjsua_var.resolver);
1570 if (status != PJ_SUCCESS) {
1571 char errmsg[PJ_ERR_MSG_SIZE];
1572 pj_strerror(status, errmsg, sizeof(errmsg));
1573 PJ_LOG(4,(THIS_FILE,
1574 "Error starting STUN socket for %s: %s",
1575 target, errmsg));
1576
1577 if (sess->stun_sock) {
1578 pj_stun_sock_destroy(sess->stun_sock);
1579 sess->stun_sock = NULL;
1580 }
1581 continue;
1582 }
1583
1584 /* Done for now, testing will resume/complete asynchronously in
1585 * stun_sock_cb()
1586 */
1587 sess->async_wait = PJ_TRUE;
1588 return;
1589 }
1590
1591 if (sess->idx >= sess->count) {
1592 /* No more entries to try */
1593 stun_resolve_add_ref(sess);
1594 pj_assert(status != PJ_SUCCESS || sess->status != PJ_EPENDING);
1595 if (sess->status == PJ_EPENDING)
1596 sess->status = status;
1597 stun_resolve_complete(sess);
1598 stun_resolve_dec_ref(sess);
1599 }
1600 }
1601
1602
1603 /*
1604 * Update STUN servers.
1605 */
pjsua_update_stun_servers(unsigned count,pj_str_t srv[],pj_bool_t wait)1606 PJ_DEF(pj_status_t) pjsua_update_stun_servers(unsigned count, pj_str_t srv[],
1607 pj_bool_t wait)
1608 {
1609 unsigned i;
1610 pj_status_t status;
1611
1612 PJ_ASSERT_RETURN(count && srv, PJ_EINVAL);
1613
1614 PJSUA_LOCK();
1615
1616 pjsua_var.ua_cfg.stun_srv_cnt = count;
1617 for (i = 0; i < count; i++) {
1618 if (pj_strcmp(&pjsua_var.ua_cfg.stun_srv[i], &srv[i]))
1619 pj_strdup(pjsua_var.pool, &pjsua_var.ua_cfg.stun_srv[i], &srv[i]);
1620 }
1621 pjsua_var.stun_status = PJ_EUNKNOWN;
1622
1623 PJSUA_UNLOCK();
1624
1625 status = resolve_stun_server(wait, PJ_FALSE, 0);
1626 if (wait == PJ_FALSE && status == PJ_EPENDING)
1627 status = PJ_SUCCESS;
1628
1629 return status;
1630 }
1631
1632
1633 /*
1634 * Resolve STUN server.
1635 */
pjsua_resolve_stun_servers(unsigned count,pj_str_t srv[],pj_bool_t wait,void * token,pj_stun_resolve_cb cb)1636 PJ_DEF(pj_status_t) pjsua_resolve_stun_servers( unsigned count,
1637 pj_str_t srv[],
1638 pj_bool_t wait,
1639 void *token,
1640 pj_stun_resolve_cb cb)
1641 {
1642 pj_pool_t *pool;
1643 pjsua_stun_resolve *sess;
1644 pj_status_t status;
1645 unsigned i, max_wait_ms;
1646 pj_timestamp start, now;
1647
1648 PJ_ASSERT_RETURN(count && srv && cb, PJ_EINVAL);
1649
1650 pool = pjsua_pool_create("stunres", 256, 256);
1651 if (!pool)
1652 return PJ_ENOMEM;
1653
1654 sess = PJ_POOL_ZALLOC_T(pool, pjsua_stun_resolve);
1655 sess->pool = pool;
1656 sess->token = token;
1657 sess->cb = cb;
1658 sess->count = count;
1659 sess->blocking = wait;
1660 sess->waiter = pj_thread_this();
1661 sess->status = PJ_EPENDING;
1662 sess->af = pj_AF_INET();
1663 stun_resolve_add_ref(sess);
1664 sess->srv = (pj_str_t*) pj_pool_calloc(pool, count, sizeof(pj_str_t));
1665 for (i=0; i<count; ++i) {
1666 pj_strdup(pool, &sess->srv[i], &srv[i]);
1667 }
1668
1669 PJSUA_LOCK();
1670 pj_list_push_back(&pjsua_var.stun_res, sess);
1671 PJSUA_UNLOCK();
1672
1673 resolve_stun_entry(sess);
1674
1675 if (!wait)
1676 return PJ_SUCCESS;
1677
1678 /* Should limit the wait time to avoid deadlock. For example,
1679 * if app holds dlg/tsx lock, pjsua worker thread will block on
1680 * any dlg/tsx state change.
1681 */
1682 max_wait_ms = count * pjsua_var.stun_cfg.rto_msec * (1 << 7);
1683 pj_get_timestamp(&start);
1684
1685 while ((sess->status == PJ_EPENDING) && (!sess->destroy_flag)) {
1686 /* If there is no worker thread or
1687 * the function is called from the only worker thread,
1688 * we have to handle the events here.
1689 */
1690 if (pjsua_var.thread[0] == NULL ||
1691 (pj_thread_this() == pjsua_var.thread[0] &&
1692 pjsua_var.ua_cfg.thread_cnt == 1))
1693 {
1694 pjsua_handle_events(50);
1695 } else {
1696 pj_thread_sleep(20);
1697 }
1698
1699 pj_get_timestamp(&now);
1700 if (pj_elapsed_msec(&start, &now) > max_wait_ms)
1701 sess->status = PJ_ETIMEDOUT;
1702 }
1703
1704 status = sess->status;
1705 stun_resolve_dec_ref(sess);
1706
1707 return status;
1708 }
1709
1710 /*
1711 * Cancel pending STUN resolution.
1712 */
pjsua_cancel_stun_resolution(void * token,pj_bool_t notify_cb)1713 PJ_DEF(pj_status_t) pjsua_cancel_stun_resolution( void *token,
1714 pj_bool_t notify_cb)
1715 {
1716 pjsua_stun_resolve *sess;
1717 unsigned cancelled_count = 0;
1718
1719 PJSUA_LOCK();
1720 sess = pjsua_var.stun_res.next;
1721 while (sess != &pjsua_var.stun_res) {
1722 pjsua_stun_resolve *next = sess->next;
1723
1724 if (sess->token == token) {
1725 sess->has_result = PJ_TRUE;
1726 sess->status = PJ_ECANCELLED;
1727 if (notify_cb) {
1728 pj_stun_resolve_result result;
1729
1730 pj_bzero(&result, sizeof(result));
1731 result.token = token;
1732 result.status = PJ_ECANCELLED;
1733
1734 sess->cb(&result);
1735 }
1736 ++cancelled_count;
1737 }
1738
1739 sess = next;
1740 }
1741 PJSUA_UNLOCK();
1742
1743 return cancelled_count ? PJ_SUCCESS : PJ_ENOTFOUND;
1744 }
1745
internal_stun_resolve_cb(const pj_stun_resolve_result * result)1746 static void internal_stun_resolve_cb(const pj_stun_resolve_result *result)
1747 {
1748 pjsua_var.stun_status = result->status;
1749 if ((result->status == PJ_SUCCESS) && (pjsua_var.ua_cfg.stun_srv_cnt>0)) {
1750 pj_memcpy(&pjsua_var.stun_srv, &result->addr, sizeof(result->addr));
1751 pjsua_var.stun_srv_idx = result->index;
1752
1753 /* Perform NAT type detection if not yet */
1754 if (pjsua_var.nat_type == PJ_STUN_NAT_TYPE_UNKNOWN &&
1755 !pjsua_var.nat_in_progress &&
1756 pjsua_var.ua_cfg.nat_type_in_sdp)
1757 {
1758 pjsua_detect_nat_type();
1759 }
1760 }
1761
1762 if (pjsua_var.ua_cfg.cb.on_stun_resolution_complete)
1763 (*pjsua_var.ua_cfg.cb.on_stun_resolution_complete)(result);
1764 }
1765
1766 /*
1767 * Resolve STUN server.
1768 */
resolve_stun_server(pj_bool_t wait,pj_bool_t retry_if_cur_error,unsigned options)1769 pj_status_t resolve_stun_server(pj_bool_t wait, pj_bool_t retry_if_cur_error,
1770 unsigned options)
1771 {
1772 pjsua_var.stun_opt = options;
1773
1774 /* Retry resolving if currently the STUN status is error */
1775 if (pjsua_var.stun_status != PJ_EPENDING &&
1776 pjsua_var.stun_status != PJ_SUCCESS &&
1777 retry_if_cur_error)
1778 {
1779 pjsua_var.stun_status = PJ_EUNKNOWN;
1780 }
1781
1782 if (pjsua_var.stun_status == PJ_EUNKNOWN) {
1783 pj_status_t status;
1784
1785 /* Initialize STUN configuration */
1786 pj_stun_config_init(&pjsua_var.stun_cfg, &pjsua_var.cp.factory, 0,
1787 pjsip_endpt_get_ioqueue(pjsua_var.endpt),
1788 pjsip_endpt_get_timer_heap(pjsua_var.endpt));
1789
1790 /* Start STUN server resolution */
1791 if (pjsua_var.ua_cfg.stun_srv_cnt) {
1792 pjsua_var.stun_status = PJ_EPENDING;
1793 status = pjsua_resolve_stun_servers(pjsua_var.ua_cfg.stun_srv_cnt,
1794 pjsua_var.ua_cfg.stun_srv,
1795 wait, NULL,
1796 &internal_stun_resolve_cb);
1797 if (wait || status != PJ_SUCCESS) {
1798 pjsua_var.stun_status = status;
1799 }
1800 } else {
1801 pjsua_var.stun_status = PJ_SUCCESS;
1802 }
1803
1804 } else if (pjsua_var.stun_status == PJ_EPENDING) {
1805 /* STUN server resolution has been started, wait for the
1806 * result.
1807 */
1808 if (wait) {
1809 unsigned max_wait_ms;
1810 pj_timestamp start, now;
1811
1812 /* Should limit the wait time to avoid deadlock. For example,
1813 * if app holds dlg/tsx lock, pjsua worker thread will block on
1814 * any dlg/tsx state change.
1815 */
1816 max_wait_ms = pjsua_var.ua_cfg.stun_srv_cnt *
1817 pjsua_var.stun_cfg.rto_msec * (1 << 7);
1818 pj_get_timestamp(&start);
1819
1820 while (pjsua_var.stun_status == PJ_EPENDING) {
1821 /* If there is no worker thread or
1822 * the function is called from the only worker thread,
1823 * we have to handle the events here.
1824 */
1825 if (pjsua_var.thread[0] == NULL ||
1826 (pj_thread_this() == pjsua_var.thread[0] &&
1827 pjsua_var.ua_cfg.thread_cnt == 1))
1828 {
1829 pjsua_handle_events(10);
1830 } else {
1831 pj_thread_sleep(10);
1832 }
1833
1834 pj_get_timestamp(&now);
1835 if (pj_elapsed_msec(&start, &now) > max_wait_ms)
1836 return PJ_ETIMEDOUT;
1837 }
1838 }
1839 }
1840
1841 if (pjsua_var.stun_status != PJ_EPENDING &&
1842 pjsua_var.stun_status != PJ_SUCCESS &&
1843 pjsua_var.ua_cfg.stun_ignore_failure)
1844 {
1845 PJ_LOG(2,(THIS_FILE,
1846 "Ignoring STUN resolution failure (by setting)"));
1847 //pjsua_var.stun_status = PJ_SUCCESS;
1848 return PJ_SUCCESS;
1849 }
1850
1851 return pjsua_var.stun_status;
1852 }
1853
1854 /*
1855 * Destroy pjsua.
1856 */
pjsua_destroy2(unsigned flags)1857 PJ_DEF(pj_status_t) pjsua_destroy2(unsigned flags)
1858 {
1859 int i; /* Must be signed */
1860
1861 if (pjsua_var.endpt) {
1862 PJ_LOG(4,(THIS_FILE, "Shutting down, flags=%d...", flags));
1863 }
1864
1865 if (pjsua_var.state > PJSUA_STATE_NULL &&
1866 pjsua_var.state < PJSUA_STATE_CLOSING)
1867 {
1868 pjsua_set_state(PJSUA_STATE_CLOSING);
1869 }
1870
1871 /* Signal threads to quit: */
1872 pjsua_stop_worker_threads();
1873
1874 if (pjsua_var.endpt) {
1875 unsigned max_wait;
1876
1877 pj_log_push_indent();
1878
1879 /* Terminate all calls. */
1880 if ((flags & PJSUA_DESTROY_NO_TX_MSG) == 0) {
1881 pjsua_call_hangup_all();
1882 }
1883
1884 /* Deinit media channel of all calls (see #1717) */
1885 for (i=0; i<(int)pjsua_var.ua_cfg.max_calls; ++i) {
1886 /* TODO: check if we're not allowed to send to network in the
1887 * "flags", and if so do not do TURN allocation...
1888 */
1889 pjsua_media_channel_deinit(i);
1890 }
1891
1892 /* Set all accounts to offline */
1893 for (i=0; i<(int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
1894 if (!pjsua_var.acc[i].valid)
1895 continue;
1896 pjsua_var.acc[i].online_status = PJ_FALSE;
1897 pj_bzero(&pjsua_var.acc[i].rpid, sizeof(pjrpid_element));
1898 }
1899
1900 /* Terminate all presence subscriptions. */
1901 pjsua_pres_shutdown(flags);
1902
1903 /* Wait for sometime until all publish client sessions are done
1904 * (ticket #364)
1905 */
1906 /* First stage, get the maximum wait time */
1907 max_wait = 100;
1908 for (i=0; i<(int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
1909 if (!pjsua_var.acc[i].valid)
1910 continue;
1911 if (pjsua_var.acc[i].cfg.unpublish_max_wait_time_msec > max_wait)
1912 max_wait = pjsua_var.acc[i].cfg.unpublish_max_wait_time_msec;
1913 }
1914
1915 /* No waiting if RX is disabled */
1916 if (flags & PJSUA_DESTROY_NO_RX_MSG) {
1917 max_wait = 0;
1918 }
1919
1920 /* Second stage, wait for unpublications to complete */
1921 for (i=0; i<(int)(max_wait/50); ++i) {
1922 unsigned j;
1923 for (j=0; j<PJ_ARRAY_SIZE(pjsua_var.acc); ++j) {
1924 if (!pjsua_var.acc[j].valid)
1925 continue;
1926
1927 if (pjsua_var.acc[j].publish_sess)
1928 break;
1929 }
1930 if (j != PJ_ARRAY_SIZE(pjsua_var.acc))
1931 busy_sleep(50);
1932 else
1933 break;
1934 }
1935
1936 /* Third stage, forcefully destroy unfinished unpublications */
1937 for (i=0; i<(int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
1938 if (pjsua_var.acc[i].publish_sess) {
1939 pjsip_publishc_destroy(pjsua_var.acc[i].publish_sess);
1940 pjsua_var.acc[i].publish_sess = NULL;
1941 }
1942 }
1943
1944 /* Unregister all accounts */
1945 for (i=0; i<(int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
1946 if (!pjsua_var.acc[i].valid)
1947 continue;
1948
1949 if (pjsua_var.acc[i].regc && (flags & PJSUA_DESTROY_NO_TX_MSG)==0)
1950 {
1951 pjsua_acc_set_registration(i, PJ_FALSE);
1952 }
1953 #if PJ_HAS_SSL_SOCK
1954 pj_turn_sock_tls_cfg_wipe_keys(
1955 &pjsua_var.acc[i].cfg.turn_cfg.turn_tls_setting);
1956 #endif
1957 }
1958
1959 /* Wait until all unregistrations are done (ticket #364) */
1960 /* First stage, get the maximum wait time */
1961 max_wait = 100;
1962 for (i=0; i<(int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
1963 if (!pjsua_var.acc[i].valid)
1964 continue;
1965 if (pjsua_var.acc[i].cfg.unreg_timeout > max_wait)
1966 max_wait = pjsua_var.acc[i].cfg.unreg_timeout;
1967 }
1968
1969 /* No waiting if RX is disabled */
1970 if (flags & PJSUA_DESTROY_NO_RX_MSG) {
1971 max_wait = 0;
1972 }
1973
1974 /* Second stage, wait for unregistrations to complete */
1975 for (i=0; i<(int)(max_wait/50); ++i) {
1976 unsigned j;
1977 for (j=0; j<PJ_ARRAY_SIZE(pjsua_var.acc); ++j) {
1978 if (!pjsua_var.acc[j].valid)
1979 continue;
1980
1981 if (pjsua_var.acc[j].regc)
1982 break;
1983 }
1984 if (j != PJ_ARRAY_SIZE(pjsua_var.acc))
1985 busy_sleep(50);
1986 else
1987 break;
1988 }
1989 /* Note variable 'i' is used below */
1990
1991 /* Wait for some time to allow unregistration and ICE/TURN
1992 * transports shutdown to complete:
1993 */
1994 if (i < 20 && (flags & PJSUA_DESTROY_NO_RX_MSG) == 0) {
1995 busy_sleep(1000 - i*50);
1996 }
1997
1998 PJ_LOG(4,(THIS_FILE, "Destroying..."));
1999
2000 /* Terminate any pending STUN resolution */
2001 if (!pj_list_empty(&pjsua_var.stun_res)) {
2002 pjsua_stun_resolve *sess = pjsua_var.stun_res.next;
2003 while (sess != &pjsua_var.stun_res) {
2004 pjsua_stun_resolve *next = sess->next;
2005 destroy_stun_resolve(sess, PJ_TRUE);
2006 sess = next;
2007 }
2008 }
2009
2010 /* Destroy media (to shutdown media endpoint, etc) */
2011 pjsua_media_subsys_destroy(flags);
2012
2013 /* Must destroy endpoint first before destroying pools in
2014 * buddies or accounts, since shutting down transaction layer
2015 * may emit events which trigger some buddy or account callbacks
2016 * to be called.
2017 */
2018 pjsip_endpt_destroy(pjsua_var.endpt);
2019 pjsua_var.endpt = NULL;
2020
2021 /* Destroy pool in the buddy object */
2022 for (i=0; i<(int)PJ_ARRAY_SIZE(pjsua_var.buddy); ++i) {
2023 if (pjsua_var.buddy[i].pool) {
2024 pj_pool_release(pjsua_var.buddy[i].pool);
2025 pjsua_var.buddy[i].pool = NULL;
2026 }
2027 }
2028
2029 /* Destroy accounts */
2030 for (i=0; i<(int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
2031 if (pjsua_var.acc[i].pool) {
2032 pj_pool_release(pjsua_var.acc[i].pool);
2033 pjsua_var.acc[i].pool = NULL;
2034 }
2035 }
2036 }
2037
2038 /* Destroy mutex */
2039 if (pjsua_var.mutex) {
2040 pj_mutex_destroy(pjsua_var.mutex);
2041 pjsua_var.mutex = NULL;
2042 }
2043
2044 if (pjsua_var.timer_mutex) {
2045 pj_mutex_destroy(pjsua_var.timer_mutex);
2046 pjsua_var.timer_mutex = NULL;
2047 }
2048
2049 /* Destroy pools and pool factory. */
2050 if (pjsua_var.timer_pool) {
2051 pj_pool_release(pjsua_var.timer_pool);
2052 pjsua_var.timer_pool = NULL;
2053 }
2054 if (pjsua_var.pool) {
2055 pj_pool_release(pjsua_var.pool);
2056 pjsua_var.pool = NULL;
2057 pj_caching_pool_destroy(&pjsua_var.cp);
2058
2059 pjsua_set_state(PJSUA_STATE_NULL);
2060
2061 PJ_LOG(4,(THIS_FILE, "PJSUA destroyed..."));
2062
2063 /* End logging */
2064 if (pjsua_var.log_file) {
2065 pj_file_close(pjsua_var.log_file);
2066 pjsua_var.log_file = NULL;
2067 }
2068
2069 pj_log_pop_indent();
2070
2071 /* Shutdown PJLIB */
2072 pj_shutdown();
2073 }
2074
2075 /* Clear pjsua_var */
2076 pj_bzero(&pjsua_var, sizeof(pjsua_var));
2077
2078 /* Done. */
2079 return PJ_SUCCESS;
2080 }
2081
pjsua_set_state(pjsua_state new_state)2082 void pjsua_set_state(pjsua_state new_state)
2083 {
2084 const char *state_name[] = {
2085 "NULL",
2086 "CREATED",
2087 "INIT",
2088 "STARTING",
2089 "RUNNING",
2090 "CLOSING"
2091 };
2092 pjsua_state old_state = pjsua_var.state;
2093
2094 pjsua_var.state = new_state;
2095 PJ_LOG(4,(THIS_FILE, "PJSUA state changed: %s --> %s",
2096 state_name[old_state], state_name[new_state]));
2097 }
2098
2099 /* Get state */
pjsua_get_state(void)2100 PJ_DEF(pjsua_state) pjsua_get_state(void)
2101 {
2102 return pjsua_var.state;
2103 }
2104
pjsua_destroy(void)2105 PJ_DEF(pj_status_t) pjsua_destroy(void)
2106 {
2107 return pjsua_destroy2(0);
2108 }
2109
2110
2111 /**
2112 * Application is recommended to call this function after all initialization
2113 * is done, so that the library can do additional checking set up
2114 * additional
2115 *
2116 * @return PJ_SUCCESS on success, or the appropriate error code.
2117 */
pjsua_start(void)2118 PJ_DEF(pj_status_t) pjsua_start(void)
2119 {
2120 pj_status_t status;
2121
2122 pjsua_set_state(PJSUA_STATE_STARTING);
2123 pj_log_push_indent();
2124
2125 status = pjsua_call_subsys_start();
2126 if (status != PJ_SUCCESS)
2127 goto on_return;
2128
2129 status = pjsua_media_subsys_start();
2130 if (status != PJ_SUCCESS)
2131 goto on_return;
2132
2133 status = pjsua_pres_start();
2134 if (status != PJ_SUCCESS)
2135 goto on_return;
2136
2137 pjsua_set_state(PJSUA_STATE_RUNNING);
2138
2139 on_return:
2140 pj_log_pop_indent();
2141 return status;
2142 }
2143
2144
2145 /**
2146 * Poll pjsua for events, and if necessary block the caller thread for
2147 * the specified maximum interval (in miliseconds).
2148 */
pjsua_handle_events(unsigned msec_timeout)2149 PJ_DEF(int) pjsua_handle_events(unsigned msec_timeout)
2150 {
2151 #if defined(PJ_SYMBIAN) && PJ_SYMBIAN != 0
2152
2153 return pj_symbianos_poll(-1, msec_timeout);
2154
2155 #else
2156
2157 unsigned count = 0;
2158 pj_time_val tv;
2159 pj_status_t status;
2160
2161 tv.sec = 0;
2162 tv.msec = msec_timeout;
2163 pj_time_val_normalize(&tv);
2164
2165 status = pjsip_endpt_handle_events2(pjsua_var.endpt, &tv, &count);
2166
2167 if (status != PJ_SUCCESS)
2168 return -status;
2169
2170 return count;
2171
2172 #endif
2173 }
2174
2175
2176 /*
2177 * Create memory pool.
2178 */
pjsua_pool_create(const char * name,pj_size_t init_size,pj_size_t increment)2179 PJ_DEF(pj_pool_t*) pjsua_pool_create( const char *name, pj_size_t init_size,
2180 pj_size_t increment)
2181 {
2182 /* Pool factory is thread safe, no need to lock */
2183 return pj_pool_create(&pjsua_var.cp.factory, name, init_size, increment,
2184 NULL);
2185 }
2186
2187
2188 /*
2189 * Internal function to get SIP endpoint instance of pjsua, which is
2190 * needed for example to register module, create transports, etc.
2191 * Probably is only valid after #pjsua_init() is called.
2192 */
pjsua_get_pjsip_endpt(void)2193 PJ_DEF(pjsip_endpoint*) pjsua_get_pjsip_endpt(void)
2194 {
2195 return pjsua_var.endpt;
2196 }
2197
2198 /*
2199 * Internal function to get media endpoint instance.
2200 * Only valid after #pjsua_init() is called.
2201 */
pjsua_get_pjmedia_endpt(void)2202 PJ_DEF(pjmedia_endpt*) pjsua_get_pjmedia_endpt(void)
2203 {
2204 return pjsua_var.med_endpt;
2205 }
2206
2207 /*
2208 * Internal function to get PJSUA pool factory.
2209 */
pjsua_get_pool_factory(void)2210 PJ_DEF(pj_pool_factory*) pjsua_get_pool_factory(void)
2211 {
2212 return &pjsua_var.cp.factory;
2213 }
2214
2215 /*****************************************************************************
2216 * PJSUA SIP Transport API.
2217 */
2218
2219 /*
2220 * Tools to get address string.
2221 */
addr_string(const pj_sockaddr_t * addr)2222 static const char *addr_string(const pj_sockaddr_t *addr)
2223 {
2224 static char str[128];
2225 str[0] = '\0';
2226 pj_inet_ntop(((const pj_sockaddr*)addr)->addr.sa_family,
2227 pj_sockaddr_get_addr(addr),
2228 str, sizeof(str));
2229 return str;
2230 }
2231
2232 void pjsua_acc_on_tp_state_changed(pjsip_transport *tp,
2233 pjsip_transport_state state,
2234 const pjsip_transport_state_info *info);
2235
2236 /* Callback to receive transport state notifications */
on_tp_state_callback(pjsip_transport * tp,pjsip_transport_state state,const pjsip_transport_state_info * info)2237 static void on_tp_state_callback(pjsip_transport *tp,
2238 pjsip_transport_state state,
2239 const pjsip_transport_state_info *info)
2240 {
2241 if (pjsua_var.ua_cfg.cb.on_transport_state) {
2242 (*pjsua_var.ua_cfg.cb.on_transport_state)(tp, state, info);
2243 }
2244 if (pjsua_var.old_tp_cb) {
2245 (*pjsua_var.old_tp_cb)(tp, state, info);
2246 }
2247 pjsua_acc_on_tp_state_changed(tp, state, info);
2248 }
2249
2250 /* Set transport state callback */
set_tp_state_cb()2251 static void set_tp_state_cb()
2252 {
2253 pjsip_tp_state_callback tpcb;
2254 pjsip_tpmgr *tpmgr;
2255
2256 tpmgr = pjsip_endpt_get_tpmgr(pjsua_var.endpt);
2257 tpcb = pjsip_tpmgr_get_state_cb(tpmgr);
2258
2259 if (tpcb != &on_tp_state_callback) {
2260 pjsua_var.old_tp_cb = tpcb;
2261 pjsip_tpmgr_set_state_cb(tpmgr, &on_tp_state_callback);
2262 }
2263 }
2264
2265 /*
2266 * Create and initialize SIP socket (and possibly resolve public
2267 * address via STUN, depending on config).
2268 */
create_sip_udp_sock(int af,const pjsua_transport_config * cfg,pj_sock_t * p_sock,pj_sockaddr * p_pub_addr)2269 static pj_status_t create_sip_udp_sock(int af,
2270 const pjsua_transport_config *cfg,
2271 pj_sock_t *p_sock,
2272 pj_sockaddr *p_pub_addr)
2273 {
2274 char stun_ip_addr[PJ_INET6_ADDRSTRLEN];
2275 unsigned port = cfg->port;
2276 pj_str_t stun_srv;
2277 pj_sock_t sock;
2278 pj_sockaddr bind_addr;
2279 pj_status_t status;
2280
2281 /* Make sure STUN server resolution has completed */
2282 status = resolve_stun_server(PJ_TRUE, PJ_TRUE, 0);
2283 if (status != PJ_SUCCESS) {
2284 pjsua_perror(THIS_FILE, "Error resolving STUN server", status);
2285 return status;
2286 }
2287
2288 /* Initialize bound address */
2289 if (cfg->bound_addr.slen) {
2290 status = pj_sockaddr_init(af, &bind_addr, &cfg->bound_addr,
2291 (pj_uint16_t)port);
2292 if (status != PJ_SUCCESS) {
2293 pjsua_perror(THIS_FILE,
2294 "Unable to resolve transport bound address",
2295 status);
2296 return status;
2297 }
2298 } else {
2299 pj_sockaddr_init(af, &bind_addr, NULL, (pj_uint16_t)port);
2300 }
2301
2302 /* Create socket */
2303 status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &sock);
2304 if (status != PJ_SUCCESS) {
2305 pjsua_perror(THIS_FILE, "socket() error", status);
2306 return status;
2307 }
2308
2309 /* Apply QoS, if specified */
2310 status = pj_sock_apply_qos2(sock, cfg->qos_type,
2311 &cfg->qos_params,
2312 2, THIS_FILE, "SIP UDP socket");
2313
2314 /* Apply sockopt, if specified */
2315 if (cfg->sockopt_params.cnt)
2316 status = pj_sock_setsockopt_params(sock, &cfg->sockopt_params);
2317
2318 /* Bind socket */
2319 status = pj_sock_bind(sock, &bind_addr, pj_sockaddr_get_len(&bind_addr));
2320 if (status != PJ_SUCCESS) {
2321 pjsua_perror(THIS_FILE, "bind() error", status);
2322 pj_sock_close(sock);
2323 return status;
2324 }
2325
2326 /* If port is zero, get the bound port */
2327 if (port == 0) {
2328 pj_sockaddr bound_addr;
2329 int namelen = sizeof(bound_addr);
2330 status = pj_sock_getsockname(sock, &bound_addr, &namelen);
2331 if (status != PJ_SUCCESS) {
2332 pjsua_perror(THIS_FILE, "getsockname() error", status);
2333 pj_sock_close(sock);
2334 return status;
2335 }
2336
2337 port = pj_sockaddr_get_port(&bound_addr);
2338 }
2339
2340 if (pjsua_var.stun_srv.addr.sa_family != 0) {
2341 pj_sockaddr_print(&pjsua_var.stun_srv,
2342 stun_ip_addr, sizeof(stun_ip_addr), 0);
2343 stun_srv = pj_str(stun_ip_addr);
2344 } else {
2345 stun_srv.slen = 0;
2346 }
2347
2348 /* Get the published address, either by STUN or by resolving
2349 * the name of local host.
2350 */
2351 if (pj_sockaddr_has_addr(p_pub_addr)) {
2352 /*
2353 * Public address is already specified, no need to resolve the
2354 * address, only set the port.
2355 */
2356 if (pj_sockaddr_get_port(p_pub_addr) == 0)
2357 pj_sockaddr_set_port(p_pub_addr, (pj_uint16_t)port);
2358
2359 } else if (stun_srv.slen &&
2360 (af == pj_AF_INET() || pjsua_var.ua_cfg.stun_try_ipv6))
2361 {
2362 pjstun_setting stun_opt;
2363
2364 /*
2365 * STUN is specified, resolve the address with STUN.
2366 * Currently, this is only to get IPv4 mapped address
2367 * (does IPv6 still need a mapped address?).
2368 */
2369 pj_bzero(&stun_opt, sizeof(stun_opt));
2370 stun_opt.use_stun2 = pjsua_var.ua_cfg.stun_map_use_stun2;
2371 stun_opt.af = pjsua_var.stun_srv.addr.sa_family;
2372 stun_opt.srv1 = stun_opt.srv2 = stun_srv;
2373 stun_opt.port1 = stun_opt.port2 =
2374 pj_sockaddr_get_port(&pjsua_var.stun_srv);
2375 status = pjstun_get_mapped_addr2(&pjsua_var.cp.factory, &stun_opt,
2376 1, &sock, &p_pub_addr->ipv4);
2377 if (status != PJ_SUCCESS) {
2378 /* Failed getting mapped address via STUN */
2379 pjsua_perror(THIS_FILE, "Error contacting STUN server", status);
2380
2381 /* Return error if configured to not ignore STUN failure */
2382 if (!pjsua_var.ua_cfg.stun_ignore_failure) {
2383 pj_sock_close(sock);
2384 return status;
2385 }
2386
2387 /* Otherwise, just use host IP */
2388 pj_sockaddr_init(af, p_pub_addr, NULL, (pj_uint16_t)port);
2389 status = pj_gethostip(af, p_pub_addr);
2390 if (status != PJ_SUCCESS) {
2391 pjsua_perror(THIS_FILE, "Unable to get local host IP", status);
2392 pj_sock_close(sock);
2393 return status;
2394 }
2395 }
2396
2397 } else {
2398
2399 pj_bzero(p_pub_addr, sizeof(pj_sockaddr));
2400
2401 if (pj_sockaddr_has_addr(&bind_addr)) {
2402 pj_sockaddr_copy_addr(p_pub_addr, &bind_addr);
2403 } else {
2404 status = pj_gethostip(af, p_pub_addr);
2405 if (status != PJ_SUCCESS) {
2406 pjsua_perror(THIS_FILE, "Unable to get local host IP", status);
2407 pj_sock_close(sock);
2408 return status;
2409 }
2410 }
2411
2412 p_pub_addr->addr.sa_family = (pj_uint16_t)af;
2413 pj_sockaddr_set_port(p_pub_addr, (pj_uint16_t)port);
2414
2415 if (stun_srv.slen && af != pj_AF_INET()) {
2416 /* STUN is specified, but it is not IPv4, just print warning */
2417 PJ_PERROR(2, (THIS_FILE, PJ_EAFNOTSUP,
2418 "Cannot use STUN for SIP UDP socket %s:%d",
2419 addr_string(p_pub_addr),
2420 (int)pj_sockaddr_get_port(p_pub_addr)));
2421 }
2422
2423 }
2424
2425 *p_sock = sock;
2426
2427 PJ_LOG(4,(THIS_FILE, "SIP UDP socket reachable at %s:%d",
2428 addr_string(p_pub_addr),
2429 (int)pj_sockaddr_get_port(p_pub_addr)));
2430
2431 return PJ_SUCCESS;
2432 }
2433
2434
2435 /*
2436 * Create SIP transport.
2437 */
pjsua_transport_create(pjsip_transport_type_e type,const pjsua_transport_config * cfg,pjsua_transport_id * p_id)2438 PJ_DEF(pj_status_t) pjsua_transport_create( pjsip_transport_type_e type,
2439 const pjsua_transport_config *cfg,
2440 pjsua_transport_id *p_id)
2441 {
2442 pjsip_transport *tp;
2443 unsigned id;
2444 pj_status_t status;
2445
2446 PJSUA_LOCK();
2447
2448 /* Find empty transport slot */
2449 for (id=0; id < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++id) {
2450 if (pjsua_var.tpdata[id].data.ptr == NULL)
2451 break;
2452 }
2453
2454 if (id == PJ_ARRAY_SIZE(pjsua_var.tpdata)) {
2455 status = PJ_ETOOMANY;
2456 pjsua_perror(THIS_FILE, "Error creating transport", status);
2457 goto on_return;
2458 }
2459
2460 /* Create the transport */
2461 if (type==PJSIP_TRANSPORT_UDP || type==PJSIP_TRANSPORT_UDP6) {
2462 /*
2463 * Create UDP transport (IPv4 or IPv6).
2464 */
2465 pjsua_transport_config config;
2466 char hostbuf[PJ_INET6_ADDRSTRLEN];
2467 pj_sock_t sock = PJ_INVALID_SOCKET;
2468 pj_sockaddr pub_addr;
2469 pjsip_host_port addr_name;
2470
2471 /* Supply default config if it's not specified */
2472 if (cfg == NULL) {
2473 pjsua_transport_config_default(&config);
2474 cfg = &config;
2475 }
2476
2477 /* Initialize the public address from the config, if any */
2478 pj_sockaddr_init(pjsip_transport_type_get_af(type), &pub_addr,
2479 NULL, (pj_uint16_t)cfg->port);
2480 if (cfg->public_addr.slen) {
2481 status = pj_sockaddr_set_str_addr(pjsip_transport_type_get_af(type),
2482 &pub_addr, &cfg->public_addr);
2483 if (status != PJ_SUCCESS) {
2484 pjsua_perror(THIS_FILE,
2485 "Unable to resolve transport public address",
2486 status);
2487 goto on_return;
2488 }
2489 }
2490
2491 /* Create the socket and possibly resolve the address with STUN
2492 * (only when public address is not specified).
2493 */
2494 status = create_sip_udp_sock(pjsip_transport_type_get_af(type),
2495 cfg, &sock, &pub_addr);
2496 if (status != PJ_SUCCESS)
2497 goto on_return;
2498
2499 pj_ansi_strcpy(hostbuf, addr_string(&pub_addr));
2500 addr_name.host = pj_str(hostbuf);
2501 addr_name.port = pj_sockaddr_get_port(&pub_addr);
2502
2503 /* Create UDP transport */
2504 status = pjsip_udp_transport_attach2(pjsua_var.endpt, type, sock,
2505 &addr_name, 1, &tp);
2506 if (status != PJ_SUCCESS) {
2507 pjsua_perror(THIS_FILE, "Error creating SIP UDP transport",
2508 status);
2509 pj_sock_close(sock);
2510 goto on_return;
2511 }
2512
2513
2514 /* Save the transport */
2515 pjsua_var.tpdata[id].type = type;
2516 pjsua_var.tpdata[id].local_name = tp->local_name;
2517 pjsua_var.tpdata[id].data.tp = tp;
2518 if (cfg->bound_addr.slen)
2519 pjsua_var.tpdata[id].has_bound_addr = PJ_TRUE;
2520
2521 #if defined(PJ_HAS_TCP) && PJ_HAS_TCP!=0
2522
2523 } else if (type == PJSIP_TRANSPORT_TCP || type == PJSIP_TRANSPORT_TCP6) {
2524 /*
2525 * Create TCP transport.
2526 */
2527 pjsua_transport_config config;
2528 pjsip_tpfactory *tcp;
2529 pjsip_tcp_transport_cfg tcp_cfg;
2530 int af;
2531
2532 af = (type==PJSIP_TRANSPORT_TCP6) ? pj_AF_INET6() : pj_AF_INET();
2533 pjsip_tcp_transport_cfg_default(&tcp_cfg, af);
2534
2535 /* Supply default config if it's not specified */
2536 if (cfg == NULL) {
2537 pjsua_transport_config_default(&config);
2538 cfg = &config;
2539 }
2540
2541 /* Configure bind address */
2542 if (cfg->port)
2543 pj_sockaddr_set_port(&tcp_cfg.bind_addr, (pj_uint16_t)cfg->port);
2544
2545 if (cfg->bound_addr.slen) {
2546 status = pj_sockaddr_set_str_addr(tcp_cfg.af,
2547 &tcp_cfg.bind_addr,
2548 &cfg->bound_addr);
2549 if (status != PJ_SUCCESS) {
2550 pjsua_perror(THIS_FILE,
2551 "Unable to resolve transport bound address",
2552 status);
2553 goto on_return;
2554 }
2555 }
2556
2557 /* Set published name */
2558 if (cfg->public_addr.slen)
2559 tcp_cfg.addr_name.host = cfg->public_addr;
2560
2561 /* Copy the QoS settings */
2562 tcp_cfg.qos_type = cfg->qos_type;
2563 pj_memcpy(&tcp_cfg.qos_params, &cfg->qos_params,
2564 sizeof(cfg->qos_params));
2565
2566 /* Copy the sockopt */
2567 pj_memcpy(&tcp_cfg.sockopt_params, &cfg->sockopt_params,
2568 sizeof(tcp_cfg.sockopt_params));
2569
2570 /* Create the TCP transport */
2571 status = pjsip_tcp_transport_start3(pjsua_var.endpt, &tcp_cfg, &tcp);
2572
2573 if (status != PJ_SUCCESS) {
2574 pjsua_perror(THIS_FILE, "Error creating SIP TCP listener",
2575 status);
2576 goto on_return;
2577 }
2578
2579 /* Save the transport */
2580 pjsua_var.tpdata[id].type = type;
2581 pjsua_var.tpdata[id].local_name = tcp->addr_name;
2582 pjsua_var.tpdata[id].data.factory = tcp;
2583
2584 #endif /* PJ_HAS_TCP */
2585
2586 #if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0
2587 } else if (type == PJSIP_TRANSPORT_TLS || type == PJSIP_TRANSPORT_TLS6) {
2588 /*
2589 * Create TLS transport.
2590 */
2591 pjsua_transport_config config;
2592 pjsip_host_port a_name;
2593 pjsip_tpfactory *tls;
2594 pj_sockaddr local_addr;
2595 int af;
2596
2597 /* Supply default config if it's not specified */
2598 if (cfg == NULL) {
2599 pjsua_transport_config_default(&config);
2600 config.port = 5061;
2601 cfg = &config;
2602 }
2603
2604 /* Init local address */
2605 af = (type==PJSIP_TRANSPORT_TLS) ? pj_AF_INET() : pj_AF_INET6();
2606 pj_sockaddr_init(af, &local_addr, NULL, 0);
2607
2608 if (cfg->port)
2609 pj_sockaddr_set_port(&local_addr, (pj_uint16_t)cfg->port);
2610
2611 if (cfg->bound_addr.slen) {
2612 status = pj_sockaddr_set_str_addr(af, &local_addr,
2613 &cfg->bound_addr);
2614 if (status != PJ_SUCCESS) {
2615 pjsua_perror(THIS_FILE,
2616 "Unable to resolve transport bound address",
2617 status);
2618 goto on_return;
2619 }
2620 }
2621
2622 /* Init published name */
2623 pj_bzero(&a_name, sizeof(pjsip_host_port));
2624 if (cfg->public_addr.slen)
2625 a_name.host = cfg->public_addr;
2626
2627 status = pjsip_tls_transport_start2(pjsua_var.endpt, &cfg->tls_setting,
2628 &local_addr, &a_name, 1, &tls);
2629 if (status != PJ_SUCCESS) {
2630 pjsua_perror(THIS_FILE, "Error creating SIP TLS listener",
2631 status);
2632 goto on_return;
2633 }
2634
2635 /* Save the transport */
2636 pjsua_var.tpdata[id].type = type;
2637 pjsua_var.tpdata[id].local_name = tls->addr_name;
2638 pjsua_var.tpdata[id].data.factory = tls;
2639 #endif
2640
2641 } else {
2642 status = PJSIP_EUNSUPTRANSPORT;
2643 pjsua_perror(THIS_FILE, "Error creating transport", status);
2644 goto on_return;
2645 }
2646
2647 /* Set transport state callback */
2648 set_tp_state_cb();
2649
2650 /* Return the ID */
2651 if (p_id) *p_id = id;
2652
2653 status = PJ_SUCCESS;
2654
2655 on_return:
2656
2657 PJSUA_UNLOCK();
2658
2659 return status;
2660 }
2661
2662
2663 /*
2664 * Register transport that has been created by application.
2665 */
pjsua_transport_register(pjsip_transport * tp,pjsua_transport_id * p_id)2666 PJ_DEF(pj_status_t) pjsua_transport_register( pjsip_transport *tp,
2667 pjsua_transport_id *p_id)
2668 {
2669 unsigned id;
2670
2671 PJSUA_LOCK();
2672
2673 /* Find empty transport slot */
2674 for (id=0; id < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++id) {
2675 if (pjsua_var.tpdata[id].data.ptr == NULL)
2676 break;
2677 }
2678
2679 if (id == PJ_ARRAY_SIZE(pjsua_var.tpdata)) {
2680 pjsua_perror(THIS_FILE, "Error creating transport", PJ_ETOOMANY);
2681 PJSUA_UNLOCK();
2682 return PJ_ETOOMANY;
2683 }
2684
2685 /* Save the transport */
2686 pjsua_var.tpdata[id].type = (pjsip_transport_type_e) tp->key.type;
2687 pjsua_var.tpdata[id].local_name = tp->local_name;
2688 pjsua_var.tpdata[id].data.tp = tp;
2689
2690 /* Set transport state callback */
2691 set_tp_state_cb();
2692
2693 /* Return the ID */
2694 if (p_id) *p_id = id;
2695
2696 PJSUA_UNLOCK();
2697
2698 return PJ_SUCCESS;
2699 }
2700
2701
2702 /*
2703 * Register transport factory that has been created by application.
2704 */
pjsua_tpfactory_register(pjsip_tpfactory * tf,pjsua_transport_id * p_id)2705 PJ_DEF(pj_status_t) pjsua_tpfactory_register( pjsip_tpfactory *tf,
2706 pjsua_transport_id *p_id)
2707 {
2708 unsigned id;
2709
2710 PJSUA_LOCK();
2711
2712 /* Find empty transport slot */
2713 for (id=0; id < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++id) {
2714 if (pjsua_var.tpdata[id].data.ptr == NULL)
2715 break;
2716 }
2717
2718 if (id == PJ_ARRAY_SIZE(pjsua_var.tpdata)) {
2719 pjsua_perror(THIS_FILE, "Error creating transport", PJ_ETOOMANY);
2720 PJSUA_UNLOCK();
2721 return PJ_ETOOMANY;
2722 }
2723
2724 /* Save the transport */
2725 pjsua_var.tpdata[id].type = (pjsip_transport_type_e) tf->type;
2726 pjsua_var.tpdata[id].local_name = tf->addr_name;
2727 pjsua_var.tpdata[id].data.factory = tf;
2728
2729 /* Set transport state callback */
2730 set_tp_state_cb();
2731
2732 /* Return the ID */
2733 if (p_id) *p_id = id;
2734
2735 PJSUA_UNLOCK();
2736
2737 return PJ_SUCCESS;
2738 }
2739
2740
2741 /*
2742 * Enumerate all transports currently created in the system.
2743 */
pjsua_enum_transports(pjsua_transport_id id[],unsigned * p_count)2744 PJ_DEF(pj_status_t) pjsua_enum_transports( pjsua_transport_id id[],
2745 unsigned *p_count )
2746 {
2747 unsigned i, count;
2748
2749 PJSUA_LOCK();
2750
2751 for (i=0, count=0; i<PJ_ARRAY_SIZE(pjsua_var.tpdata) && count<*p_count;
2752 ++i)
2753 {
2754 if (!pjsua_var.tpdata[i].data.ptr)
2755 continue;
2756
2757 id[count++] = i;
2758 }
2759
2760 *p_count = count;
2761
2762 PJSUA_UNLOCK();
2763
2764 return PJ_SUCCESS;
2765 }
2766
2767
2768 /*
2769 * Get information about transports.
2770 */
pjsua_transport_get_info(pjsua_transport_id id,pjsua_transport_info * info)2771 PJ_DEF(pj_status_t) pjsua_transport_get_info( pjsua_transport_id id,
2772 pjsua_transport_info *info)
2773 {
2774 pjsua_transport_data *t = &pjsua_var.tpdata[id];
2775 pj_status_t status;
2776
2777 pj_bzero(info, sizeof(*info));
2778
2779 /* Make sure id is in range. */
2780 PJ_ASSERT_RETURN(id>=0 && id<(int)PJ_ARRAY_SIZE(pjsua_var.tpdata),
2781 PJ_EINVAL);
2782
2783 /* Make sure that transport exists */
2784 PJ_ASSERT_RETURN(pjsua_var.tpdata[id].data.ptr != NULL, PJ_EINVAL);
2785
2786 PJSUA_LOCK();
2787
2788 if ((t->type & ~PJSIP_TRANSPORT_IPV6) == PJSIP_TRANSPORT_UDP) {
2789
2790 pjsip_transport *tp = t->data.tp;
2791
2792 if (tp == NULL) {
2793 PJSUA_UNLOCK();
2794 return PJ_EINVALIDOP;
2795 }
2796
2797 info->id = id;
2798 info->type = (pjsip_transport_type_e) tp->key.type;
2799 info->type_name = pj_str(tp->type_name);
2800 info->info = pj_str(tp->info);
2801 info->flag = tp->flag;
2802 info->addr_len = tp->addr_len;
2803 info->local_addr = tp->local_addr;
2804 info->local_name = tp->local_name;
2805 info->usage_count = pj_atomic_get(tp->ref_cnt);
2806
2807 status = PJ_SUCCESS;
2808
2809 } else if ((t->type & ~PJSIP_TRANSPORT_IPV6) == PJSIP_TRANSPORT_TCP ||
2810 (t->type & ~PJSIP_TRANSPORT_IPV6) == PJSIP_TRANSPORT_TLS)
2811 {
2812
2813 pjsip_tpfactory *factory = t->data.factory;
2814
2815 if (factory == NULL) {
2816 PJSUA_UNLOCK();
2817 return PJ_EINVALIDOP;
2818 }
2819
2820 info->id = id;
2821 info->type = t->type;
2822 info->type_name = pj_str(factory->type_name);
2823 info->info = pj_str(factory->info);
2824 info->flag = factory->flag;
2825 info->addr_len = sizeof(factory->local_addr);
2826 info->local_addr = factory->local_addr;
2827 info->local_name = factory->addr_name;
2828 info->usage_count = 0;
2829
2830 status = PJ_SUCCESS;
2831
2832 } else {
2833 pj_assert(!"Unsupported transport");
2834 status = PJ_EINVALIDOP;
2835 }
2836
2837
2838 PJSUA_UNLOCK();
2839
2840 return status;
2841 }
2842
2843
2844 /*
2845 * Disable a transport or re-enable it.
2846 */
pjsua_transport_set_enable(pjsua_transport_id id,pj_bool_t enabled)2847 PJ_DEF(pj_status_t) pjsua_transport_set_enable( pjsua_transport_id id,
2848 pj_bool_t enabled)
2849 {
2850 /* Make sure id is in range. */
2851 PJ_ASSERT_RETURN(id>=0 && id<(int)PJ_ARRAY_SIZE(pjsua_var.tpdata),
2852 PJ_EINVAL);
2853
2854 /* Make sure that transport exists */
2855 PJ_ASSERT_RETURN(pjsua_var.tpdata[id].data.ptr != NULL, PJ_EINVAL);
2856
2857
2858 /* To be done!! */
2859 PJ_TODO(pjsua_transport_set_enable);
2860 PJ_UNUSED_ARG(enabled);
2861
2862 return PJ_EINVALIDOP;
2863 }
2864
2865
2866 /*
2867 * Close the transport.
2868 */
pjsua_transport_close(pjsua_transport_id id,pj_bool_t force)2869 PJ_DEF(pj_status_t) pjsua_transport_close( pjsua_transport_id id,
2870 pj_bool_t force )
2871 {
2872 pj_status_t status;
2873 pjsip_transport_type_e tp_type;
2874
2875 /* Make sure id is in range. */
2876 PJ_ASSERT_RETURN(id>=0 && id<(int)PJ_ARRAY_SIZE(pjsua_var.tpdata),
2877 PJ_EINVAL);
2878
2879 /* Make sure that transport exists */
2880 PJ_ASSERT_RETURN(pjsua_var.tpdata[id].data.ptr != NULL, PJ_EINVAL);
2881
2882 tp_type = pjsua_var.tpdata[id].type & ~PJSIP_TRANSPORT_IPV6;
2883
2884 if (force) {
2885 /* Forcefully closing transport is deprecated, since any pending
2886 * transactions that are using the transport may not terminate
2887 * properly and can even crash.
2888 */
2889 PJ_LOG(1, (THIS_FILE, "pjsua_transport_close(force=PJ_TRUE) is "
2890 "deprecated."));
2891
2892 /* To minimize the effect to users, we shouldn't hard-deprecate this
2893 * and let it continue as if force is false.
2894 */
2895 // return PJ_EINVAL;
2896 }
2897
2898 /* If force is not specified, transports will be closed at their
2899 * convenient time.
2900 */
2901 switch (tp_type) {
2902 case PJSIP_TRANSPORT_UDP:
2903 status = pjsip_transport_shutdown(pjsua_var.tpdata[id].data.tp);
2904 break;
2905 case PJSIP_TRANSPORT_TLS:
2906 case PJSIP_TRANSPORT_TCP:
2907 /* This will close the TCP listener, but existing TCP/TLS
2908 * connections (if any) will still linger
2909 */
2910 status = (*pjsua_var.tpdata[id].data.factory->destroy)
2911 (pjsua_var.tpdata[id].data.factory);
2912 break;
2913 default:
2914 return PJ_EINVAL;
2915 }
2916
2917 /* Cleanup pjsua data. We don't need to keep the transport
2918 * descriptor, the transport will be destroyed later by the last user
2919 * which decrements the transport's reference.
2920 */
2921 if (status == PJ_SUCCESS) {
2922 pjsua_var.tpdata[id].type = PJSIP_TRANSPORT_UNSPECIFIED;
2923 pjsua_var.tpdata[id].data.ptr = NULL;
2924 }
2925
2926 return status;
2927 }
2928
2929
pjsua_transport_lis_start(pjsua_transport_id id,const pjsua_transport_config * cfg)2930 PJ_DEF(pj_status_t) pjsua_transport_lis_start(pjsua_transport_id id,
2931 const pjsua_transport_config *cfg)
2932 {
2933 pj_status_t status = PJ_SUCCESS;
2934 pjsip_transport_type_e tp_type;
2935
2936 /* Make sure id is in range. */
2937 PJ_ASSERT_RETURN(id>=0 && id<(int)PJ_ARRAY_SIZE(pjsua_var.tpdata),
2938 PJ_EINVAL);
2939
2940 /* Make sure that transport exists */
2941 PJ_ASSERT_RETURN(pjsua_var.tpdata[id].data.ptr != NULL, PJ_EINVAL);
2942
2943 tp_type = pjsua_var.tpdata[id].type & ~PJSIP_TRANSPORT_IPV6;
2944
2945 if ((tp_type == PJSIP_TRANSPORT_TLS) || (tp_type == PJSIP_TRANSPORT_TCP)) {
2946 pj_sockaddr bind_addr;
2947 pjsip_host_port addr_name;
2948 pjsip_tpfactory *factory = pjsua_var.tpdata[id].data.factory;
2949
2950 int af = pjsip_transport_type_get_af(factory->type);
2951
2952 if (cfg->port)
2953 pj_sockaddr_set_port(&bind_addr, (pj_uint16_t)cfg->port);
2954
2955 if (cfg->bound_addr.slen) {
2956 status = pj_sockaddr_set_str_addr(af,
2957 &bind_addr,
2958 &cfg->bound_addr);
2959 if (status != PJ_SUCCESS) {
2960 pjsua_perror(THIS_FILE,
2961 "Unable to resolve transport bound address",
2962 status);
2963 return status;
2964 }
2965 }
2966
2967 /* Set published name */
2968 if (cfg->public_addr.slen)
2969 addr_name.host = cfg->public_addr;
2970
2971 if (tp_type == PJSIP_TRANSPORT_TCP) {
2972 status = pjsip_tcp_transport_lis_start(factory, &bind_addr,
2973 &addr_name);
2974 }
2975 #if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0
2976 else {
2977 status = pjsip_tls_transport_lis_start(factory, &bind_addr,
2978 &addr_name);
2979 }
2980 #endif
2981 } else if (tp_type == PJSIP_TRANSPORT_UDP) {
2982 status = PJ_SUCCESS;
2983 } else {
2984 status = PJ_EINVAL;
2985 }
2986 return status;
2987 }
2988
2989
2990 /*
2991 * Add additional headers etc in msg_data specified by application
2992 * when sending requests.
2993 */
pjsua_process_msg_data(pjsip_tx_data * tdata,const pjsua_msg_data * msg_data)2994 void pjsua_process_msg_data(pjsip_tx_data *tdata,
2995 const pjsua_msg_data *msg_data)
2996 {
2997 pj_bool_t allow_body;
2998 const pjsip_hdr *hdr;
2999
3000 /* Always add User-Agent */
3001 if (pjsua_var.ua_cfg.user_agent.slen &&
3002 tdata->msg->type == PJSIP_REQUEST_MSG)
3003 {
3004 const pj_str_t STR_USER_AGENT = { "User-Agent", 10 };
3005 pjsip_hdr *h;
3006 h = (pjsip_hdr*)pjsip_generic_string_hdr_create(tdata->pool,
3007 &STR_USER_AGENT,
3008 &pjsua_var.ua_cfg.user_agent);
3009 pjsip_msg_add_hdr(tdata->msg, h);
3010 }
3011
3012 if (!msg_data)
3013 return;
3014
3015 hdr = msg_data->hdr_list.next;
3016 while (hdr && hdr != &msg_data->hdr_list) {
3017 pjsip_hdr *new_hdr;
3018
3019 new_hdr = (pjsip_hdr*) pjsip_hdr_clone(tdata->pool, hdr);
3020 pjsip_msg_add_hdr(tdata->msg, new_hdr);
3021
3022 hdr = hdr->next;
3023 }
3024
3025 allow_body = (tdata->msg->body == NULL);
3026
3027 if (allow_body && msg_data->content_type.slen && msg_data->msg_body.slen) {
3028 pjsip_media_type ctype;
3029 pjsip_msg_body *body;
3030
3031 pjsua_parse_media_type(tdata->pool, &msg_data->content_type, &ctype);
3032 body = pjsip_msg_body_create(tdata->pool, &ctype.type, &ctype.subtype,
3033 &msg_data->msg_body);
3034 tdata->msg->body = body;
3035 }
3036
3037 /* Multipart */
3038 if (!pj_list_empty(&msg_data->multipart_parts) &&
3039 msg_data->multipart_ctype.type.slen)
3040 {
3041 pjsip_msg_body *bodies;
3042 pjsip_multipart_part *part;
3043 pj_str_t *boundary = NULL;
3044
3045 bodies = pjsip_multipart_create(tdata->pool,
3046 &msg_data->multipart_ctype,
3047 boundary);
3048 part = msg_data->multipart_parts.next;
3049 while (part != &msg_data->multipart_parts) {
3050 pjsip_multipart_part *part_copy;
3051
3052 part_copy = pjsip_multipart_clone_part(tdata->pool, part);
3053 pjsip_multipart_add_part(tdata->pool, bodies, part_copy);
3054 part = part->next;
3055 }
3056
3057 if (tdata->msg->body) {
3058 part = pjsip_multipart_create_part(tdata->pool);
3059 part->body = tdata->msg->body;
3060 pjsip_multipart_add_part(tdata->pool, bodies, part);
3061
3062 tdata->msg->body = NULL;
3063 }
3064
3065 tdata->msg->body = bodies;
3066 }
3067 }
3068
3069
3070 /*
3071 * Add route_set to outgoing requests
3072 */
pjsua_set_msg_route_set(pjsip_tx_data * tdata,const pjsip_route_hdr * route_set)3073 void pjsua_set_msg_route_set( pjsip_tx_data *tdata,
3074 const pjsip_route_hdr *route_set )
3075 {
3076 const pjsip_route_hdr *r;
3077
3078 r = route_set->next;
3079 while (r != route_set) {
3080 pjsip_route_hdr *new_r;
3081
3082 new_r = (pjsip_route_hdr*) pjsip_hdr_clone(tdata->pool, r);
3083 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)new_r);
3084
3085 r = r->next;
3086 }
3087 }
3088
3089
3090 /*
3091 * Simple version of MIME type parsing (it doesn't support parameters)
3092 */
pjsua_parse_media_type(pj_pool_t * pool,const pj_str_t * mime,pjsip_media_type * media_type)3093 void pjsua_parse_media_type( pj_pool_t *pool,
3094 const pj_str_t *mime,
3095 pjsip_media_type *media_type)
3096 {
3097 pj_str_t tmp;
3098 char *pos;
3099
3100 pj_bzero(media_type, sizeof(*media_type));
3101
3102 pj_strdup_with_null(pool, &tmp, mime);
3103
3104 pos = pj_strchr(&tmp, '/');
3105 if (pos) {
3106 media_type->type.ptr = tmp.ptr;
3107 media_type->type.slen = (pos-tmp.ptr);
3108 media_type->subtype.ptr = pos+1;
3109 media_type->subtype.slen = tmp.ptr+tmp.slen-pos-1;
3110 } else {
3111 media_type->type = tmp;
3112 }
3113 }
3114
3115
3116 /*
3117 * Internal function to init transport selector from transport id.
3118 */
pjsua_init_tpselector(pjsua_transport_id tp_id,pjsip_tpselector * sel)3119 void pjsua_init_tpselector(pjsua_transport_id tp_id,
3120 pjsip_tpselector *sel)
3121 {
3122 pjsua_transport_data *tpdata;
3123 unsigned flag;
3124
3125 pj_bzero(sel, sizeof(*sel));
3126 if (tp_id == PJSUA_INVALID_ID)
3127 return;
3128
3129 pj_assert(tp_id >= 0 && tp_id < (int)PJ_ARRAY_SIZE(pjsua_var.tpdata));
3130 tpdata = &pjsua_var.tpdata[tp_id];
3131
3132 flag = pjsip_transport_get_flag_from_type(tpdata->type);
3133
3134 if (flag & PJSIP_TRANSPORT_DATAGRAM) {
3135 sel->type = PJSIP_TPSELECTOR_TRANSPORT;
3136 sel->u.transport = tpdata->data.tp;
3137 } else {
3138 sel->type = PJSIP_TPSELECTOR_LISTENER;
3139 sel->u.listener = tpdata->data.factory;
3140 }
3141 }
3142
3143
pjsua_ip_change_param_default(pjsua_ip_change_param * param)3144 PJ_DEF(void) pjsua_ip_change_param_default(pjsua_ip_change_param *param)
3145 {
3146 pj_bzero(param, sizeof(*param));
3147 param->restart_listener = PJ_TRUE;
3148 param->restart_lis_delay = PJSUA_TRANSPORT_RESTART_DELAY_TIME;
3149 }
3150
3151
3152 /* Callback upon NAT detection completion */
nat_detect_cb(void * user_data,const pj_stun_nat_detect_result * res)3153 static void nat_detect_cb(void *user_data,
3154 const pj_stun_nat_detect_result *res)
3155 {
3156 PJ_UNUSED_ARG(user_data);
3157
3158 pjsua_var.nat_in_progress = PJ_FALSE;
3159 pjsua_var.nat_status = res->status;
3160 pjsua_var.nat_type = res->nat_type;
3161
3162 if (pjsua_var.ua_cfg.cb.on_nat_detect) {
3163 (*pjsua_var.ua_cfg.cb.on_nat_detect)(res);
3164 }
3165 }
3166
3167
3168 /*
3169 * Detect NAT type.
3170 */
pjsua_detect_nat_type()3171 PJ_DEF(pj_status_t) pjsua_detect_nat_type()
3172 {
3173 pj_status_t status;
3174
3175 if (pjsua_var.nat_in_progress)
3176 return PJ_SUCCESS;
3177
3178 /* Make sure STUN server resolution has completed */
3179 status = resolve_stun_server(PJ_TRUE, PJ_TRUE, 0);
3180 if (status != PJ_SUCCESS) {
3181 pjsua_var.nat_status = status;
3182 pjsua_var.nat_type = PJ_STUN_NAT_TYPE_ERR_UNKNOWN;
3183 return status;
3184 }
3185
3186 /* Make sure we have STUN */
3187 if (pjsua_var.stun_srv.addr.sa_family == 0) {
3188 pjsua_var.nat_status = PJNATH_ESTUNINSERVER;
3189 return PJNATH_ESTUNINSERVER;
3190 }
3191
3192 status = pj_stun_detect_nat_type2(&pjsua_var.stun_srv,
3193 &pjsua_var.stun_cfg,
3194 NULL, &nat_detect_cb);
3195
3196 if (status != PJ_SUCCESS) {
3197 pjsua_var.nat_status = status;
3198 pjsua_var.nat_type = PJ_STUN_NAT_TYPE_ERR_UNKNOWN;
3199 return status;
3200 }
3201
3202 pjsua_var.nat_in_progress = PJ_TRUE;
3203
3204 return PJ_SUCCESS;
3205 }
3206
3207
3208 /*
3209 * Get NAT type.
3210 */
pjsua_get_nat_type(pj_stun_nat_type * type)3211 PJ_DEF(pj_status_t) pjsua_get_nat_type(pj_stun_nat_type *type)
3212 {
3213 *type = pjsua_var.nat_type;
3214 return pjsua_var.nat_status;
3215 }
3216
3217 /*
3218 * Verify that valid url is given.
3219 */
pjsua_verify_url(const char * c_url)3220 PJ_DEF(pj_status_t) pjsua_verify_url(const char *c_url)
3221 {
3222 pjsip_uri *p;
3223 pj_pool_t *pool;
3224 char *url;
3225 pj_size_t len = (c_url ? pj_ansi_strlen(c_url) : 0);
3226
3227 if (!len) return PJSIP_EINVALIDURI;
3228
3229 pool = pj_pool_create(&pjsua_var.cp.factory, "check%p", 1024, 0, NULL);
3230 if (!pool) return PJ_ENOMEM;
3231
3232 url = (char*) pj_pool_alloc(pool, len+1);
3233 pj_ansi_strcpy(url, c_url);
3234
3235 p = pjsip_parse_uri(pool, url, len, 0);
3236
3237 pj_pool_release(pool);
3238 return p ? 0 : PJSIP_EINVALIDURI;
3239 }
3240
3241 /*
3242 * Verify that valid SIP url is given.
3243 */
pjsua_verify_sip_url(const char * c_url)3244 PJ_DEF(pj_status_t) pjsua_verify_sip_url(const char *c_url)
3245 {
3246 pjsip_uri *p;
3247 pj_pool_t *pool;
3248 char *url;
3249 pj_size_t len = (c_url ? pj_ansi_strlen(c_url) : 0);
3250
3251 if (!len) return PJSIP_EINVALIDURI;
3252
3253 pool = pj_pool_create(&pjsua_var.cp.factory, "check%p", 1024, 0, NULL);
3254 if (!pool) return PJ_ENOMEM;
3255
3256 url = (char*) pj_pool_alloc(pool, len+1);
3257 pj_ansi_strcpy(url, c_url);
3258
3259 p = pjsip_parse_uri(pool, url, len, 0);
3260 if (!p || (pj_stricmp2(pjsip_uri_get_scheme(p), "sip") != 0 &&
3261 pj_stricmp2(pjsip_uri_get_scheme(p), "sips") != 0))
3262 {
3263 p = NULL;
3264 }
3265
3266 pj_pool_release(pool);
3267 return p ? 0 : PJSIP_EINVALIDURI;
3268 }
3269
3270 /*
3271 * Schedule a timer entry.
3272 */
3273 #if PJ_TIMER_DEBUG
pjsua_schedule_timer_dbg(pj_timer_entry * entry,const pj_time_val * delay,const char * src_file,int src_line)3274 PJ_DEF(pj_status_t) pjsua_schedule_timer_dbg( pj_timer_entry *entry,
3275 const pj_time_val *delay,
3276 const char *src_file,
3277 int src_line)
3278 {
3279 return pjsip_endpt_schedule_timer_dbg(pjsua_var.endpt, entry, delay,
3280 src_file, src_line);
3281 }
3282 #else
pjsua_schedule_timer(pj_timer_entry * entry,const pj_time_val * delay)3283 PJ_DEF(pj_status_t) pjsua_schedule_timer( pj_timer_entry *entry,
3284 const pj_time_val *delay)
3285 {
3286 return pjsip_endpt_schedule_timer(pjsua_var.endpt, entry, delay);
3287 }
3288 #endif
3289
3290 /* Timer callback */
timer_cb(pj_timer_heap_t * th,pj_timer_entry * entry)3291 static void timer_cb( pj_timer_heap_t *th,
3292 pj_timer_entry *entry)
3293 {
3294 pjsua_timer_list *tmr = (pjsua_timer_list *)entry->user_data;
3295 void (*cb)(void *user_data) = tmr->cb;
3296 void *user_data = tmr->user_data;
3297
3298 PJ_UNUSED_ARG(th);
3299
3300 if (cb)
3301 (*cb)(user_data);
3302
3303 pj_mutex_lock(pjsua_var.timer_mutex);
3304 pj_list_erase(tmr);
3305 pj_list_push_back(&pjsua_var.timer_list, tmr);
3306 pj_mutex_unlock(pjsua_var.timer_mutex);
3307 }
3308
3309 /*
3310 * Schedule a timer callback.
3311 */
3312 #if PJ_TIMER_DEBUG
pjsua_schedule_timer2_dbg(void (* cb)(void * user_data),void * user_data,unsigned msec_delay,const char * src_file,int src_line)3313 PJ_DEF(pj_status_t) pjsua_schedule_timer2_dbg( void (*cb)(void *user_data),
3314 void *user_data,
3315 unsigned msec_delay,
3316 const char *src_file,
3317 int src_line)
3318 #else
3319 PJ_DEF(pj_status_t) pjsua_schedule_timer2( void (*cb)(void *user_data),
3320 void *user_data,
3321 unsigned msec_delay)
3322 #endif
3323 {
3324 pjsua_timer_list *tmr = NULL;
3325 pj_status_t status;
3326 pj_time_val delay;
3327
3328 pj_mutex_lock(pjsua_var.timer_mutex);
3329
3330 if (pj_list_empty(&pjsua_var.timer_list)) {
3331 tmr = PJ_POOL_ALLOC_T(pjsua_var.timer_pool, pjsua_timer_list);
3332 } else {
3333 tmr = pjsua_var.timer_list.next;
3334 pj_list_erase(tmr);
3335 }
3336 pj_timer_entry_init(&tmr->entry, 0, tmr, timer_cb);
3337 tmr->cb = cb;
3338 tmr->user_data = user_data;
3339 delay.sec = 0;
3340 delay.msec = msec_delay;
3341
3342 #if PJ_TIMER_DEBUG
3343 status = pjsip_endpt_schedule_timer_dbg(pjsua_var.endpt, &tmr->entry,
3344 &delay, src_file, src_line);
3345 #else
3346 status = pjsip_endpt_schedule_timer(pjsua_var.endpt, &tmr->entry, &delay);
3347 #endif
3348 if (status == PJ_SUCCESS) {
3349 pj_list_push_back(&pjsua_var.active_timer_list, tmr);
3350 } else {
3351 pj_list_push_back(&pjsua_var.timer_list, tmr);
3352 }
3353
3354 pj_mutex_unlock(pjsua_var.timer_mutex);
3355
3356 return status;
3357 }
3358
3359 /*
3360 * Cancel the previously scheduled timer.
3361 *
3362 */
pjsua_cancel_timer(pj_timer_entry * entry)3363 PJ_DEF(void) pjsua_cancel_timer(pj_timer_entry *entry)
3364 {
3365 pjsip_endpt_cancel_timer(pjsua_var.endpt, entry);
3366 }
3367
3368 /**
3369 * Normalize route URI (check for ";lr" and append one if it doesn't
3370 * exist and pjsua_config.force_lr is set.
3371 */
normalize_route_uri(pj_pool_t * pool,pj_str_t * uri)3372 pj_status_t normalize_route_uri(pj_pool_t *pool, pj_str_t *uri)
3373 {
3374 pj_str_t tmp_uri;
3375 pj_pool_t *tmp_pool;
3376 pjsip_uri *uri_obj;
3377 pjsip_sip_uri *sip_uri;
3378
3379 tmp_pool = pjsua_pool_create("tmplr%p", 512, 512);
3380 if (!tmp_pool)
3381 return PJ_ENOMEM;
3382
3383 pj_strdup_with_null(tmp_pool, &tmp_uri, uri);
3384
3385 uri_obj = pjsip_parse_uri(tmp_pool, tmp_uri.ptr, tmp_uri.slen, 0);
3386 if (!uri_obj) {
3387 PJ_LOG(1,(THIS_FILE, "Invalid route URI: %.*s",
3388 (int)uri->slen, uri->ptr));
3389 pj_pool_release(tmp_pool);
3390 return PJSIP_EINVALIDURI;
3391 }
3392
3393 if (!PJSIP_URI_SCHEME_IS_SIP(uri_obj) &&
3394 !PJSIP_URI_SCHEME_IS_SIPS(uri_obj))
3395 {
3396 PJ_LOG(1,(THIS_FILE, "Route URI must be SIP URI: %.*s",
3397 (int)uri->slen, uri->ptr));
3398 pj_pool_release(tmp_pool);
3399 return PJSIP_EINVALIDSCHEME;
3400 }
3401
3402 sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(uri_obj);
3403
3404 /* Done if force_lr is disabled or if lr parameter is present */
3405 if (!pjsua_var.ua_cfg.force_lr || sip_uri->lr_param) {
3406 pj_pool_release(tmp_pool);
3407 return PJ_SUCCESS;
3408 }
3409
3410 /* Set lr param */
3411 sip_uri->lr_param = 1;
3412
3413 /* Print the URI */
3414 tmp_uri.ptr = (char*) pj_pool_alloc(tmp_pool, PJSIP_MAX_URL_SIZE);
3415 tmp_uri.slen = pjsip_uri_print(PJSIP_URI_IN_ROUTING_HDR, uri_obj,
3416 tmp_uri.ptr, PJSIP_MAX_URL_SIZE);
3417 if (tmp_uri.slen < 1) {
3418 PJ_LOG(1,(THIS_FILE, "Route URI is too long: %.*s",
3419 (int)uri->slen, uri->ptr));
3420 pj_pool_release(tmp_pool);
3421 return PJSIP_EURITOOLONG;
3422 }
3423
3424 /* Clone the URI */
3425 pj_strdup_with_null(pool, uri, &tmp_uri);
3426
3427 pj_pool_release(tmp_pool);
3428 return PJ_SUCCESS;
3429 }
3430
3431 /*
3432 * This is a utility function to dump the stack states to log, using
3433 * verbosity level 3.
3434 */
pjsua_dump(pj_bool_t detail)3435 PJ_DEF(void) pjsua_dump(pj_bool_t detail)
3436 {
3437 unsigned old_decor;
3438 unsigned i;
3439
3440 PJ_LOG(3,(THIS_FILE, "Start dumping application states:"));
3441
3442 old_decor = pj_log_get_decor();
3443 pj_log_set_decor(old_decor & (PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_CR));
3444
3445 if (detail)
3446 pj_dump_config();
3447
3448 pjsip_endpt_dump(pjsua_get_pjsip_endpt(), detail);
3449
3450 pjmedia_endpt_dump(pjsua_get_pjmedia_endpt());
3451
3452 PJ_LOG(3,(THIS_FILE, "Dumping media transports:"));
3453 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
3454 pjsua_call *call = &pjsua_var.calls[i];
3455 pjsua_acc_config *acc_cfg;
3456 pjmedia_transport *tp[PJSUA_MAX_CALL_MEDIA*2];
3457 unsigned tp_cnt = 0;
3458 unsigned j;
3459
3460 /* Collect media transports in this call */
3461 for (j = 0; j < call->med_cnt; ++j) {
3462 if (call->media[j].tp != NULL)
3463 tp[tp_cnt++] = call->media[j].tp;
3464 }
3465 for (j = 0; j < call->med_prov_cnt; ++j) {
3466 pjmedia_transport *med_tp = call->media_prov[j].tp;
3467 if (med_tp) {
3468 unsigned k;
3469 pj_bool_t used = PJ_FALSE;
3470 for (k = 0; k < tp_cnt; ++k) {
3471 if (med_tp == tp[k]) {
3472 used = PJ_TRUE;
3473 break;
3474 }
3475 }
3476 if (!used)
3477 tp[tp_cnt++] = med_tp;
3478 }
3479 }
3480
3481 acc_cfg = &pjsua_var.acc[call->acc_id].cfg;
3482
3483 /* Dump the media transports in this call */
3484 for (j = 0; j < tp_cnt; ++j) {
3485 pjmedia_transport_info tpinfo;
3486 char addr_buf[80];
3487
3488 pjmedia_transport_info_init(&tpinfo);
3489 pjmedia_transport_get_info(tp[j], &tpinfo);
3490 PJ_LOG(3,(THIS_FILE, " %s: %s",
3491 (acc_cfg->ice_cfg.enable_ice ? "ICE" : "UDP"),
3492 pj_sockaddr_print(&tpinfo.sock_info.rtp_addr_name,
3493 addr_buf,
3494 sizeof(addr_buf), 3)));
3495 }
3496 }
3497
3498 pjsip_tsx_layer_dump(detail);
3499 pjsip_ua_dump(detail);
3500
3501 // Dumping complete call states may require a 'large' buffer
3502 // (about 3KB per call session, including RTCP XR).
3503 #if 0
3504 /* Dump all invite sessions: */
3505 PJ_LOG(3,(THIS_FILE, "Dumping invite sessions:"));
3506
3507 if (pjsua_call_get_count() == 0) {
3508
3509 PJ_LOG(3,(THIS_FILE, " - no sessions -"));
3510
3511 } else {
3512 unsigned i;
3513
3514 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
3515 if (pjsua_call_is_active(i)) {
3516 /* Tricky logging, since call states log string tends to be
3517 * longer than PJ_LOG_MAX_SIZE.
3518 */
3519 char buf[1024 * 3];
3520 unsigned call_dump_len;
3521 unsigned part_len;
3522 unsigned part_idx;
3523 unsigned log_decor;
3524
3525 pjsua_call_dump(i, detail, buf, sizeof(buf), " ");
3526 call_dump_len = strlen(buf);
3527
3528 log_decor = pj_log_get_decor();
3529 pj_log_set_decor(log_decor & ~(PJ_LOG_HAS_NEWLINE |
3530 PJ_LOG_HAS_CR));
3531 PJ_LOG(3,(THIS_FILE, "\n"));
3532 pj_log_set_decor(0);
3533
3534 part_idx = 0;
3535 part_len = PJ_LOG_MAX_SIZE-80;
3536 while (part_idx < call_dump_len) {
3537 char p_orig, *p;
3538
3539 p = &buf[part_idx];
3540 if (part_idx + part_len > call_dump_len)
3541 part_len = call_dump_len - part_idx;
3542 p_orig = p[part_len];
3543 p[part_len] = '\0';
3544 PJ_LOG(3,(THIS_FILE, "%s", p));
3545 p[part_len] = p_orig;
3546 part_idx += part_len;
3547 }
3548 pj_log_set_decor(log_decor);
3549 }
3550 }
3551 }
3552 #endif
3553
3554 /* Dump presence status */
3555 pjsua_pres_dump(detail);
3556
3557 pj_log_set_decor(old_decor);
3558 PJ_LOG(3,(THIS_FILE, "Dump complete"));
3559 }
3560
3561
3562 /* Forward declaration. */
3563 static void restart_listener_cb(void *user_data);
3564
3565
handle_ip_change_on_acc()3566 static pj_status_t handle_ip_change_on_acc()
3567 {
3568 int i = 0;
3569 pj_status_t status = PJ_SUCCESS;
3570 pj_bool_t acc_done[PJSUA_MAX_ACC];
3571
3572 PJSUA_LOCK();
3573
3574 if (pjsua_var.acc_cnt == 0) {
3575 PJ_LOG(3, (THIS_FILE,
3576 "No account is set, IP change handling will stop"));
3577 pjsua_acc_end_ip_change(NULL);
3578 PJSUA_UNLOCK();
3579 return status;
3580 }
3581
3582 /* Reset ip_change_active flag. */
3583 for (; i < (int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
3584 pjsua_var.acc[i].ip_change_op = PJSUA_IP_CHANGE_OP_NULL;
3585 acc_done[i] = PJ_FALSE;
3586 }
3587
3588 for (i = 0; i < (int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
3589 pj_bool_t shutdown_transport = PJ_FALSE;
3590 pjsip_regc_info regc_info;
3591 char acc_id[PJSUA_MAX_ACC * 4];
3592 pjsua_acc *acc = &pjsua_var.acc[i];
3593 pjsip_transport *transport = NULL;
3594 pjsua_acc_id shut_acc_ids[PJSUA_MAX_ACC];
3595 unsigned shut_acc_cnt = 0;
3596
3597 if (!acc->valid || (acc_done[i]))
3598 continue;
3599
3600 if (acc->regc) {
3601 int j = 0;
3602 pj_status_t found_restart_tp_fail = PJ_FALSE;
3603
3604 pjsip_regc_get_info(acc->regc, ®c_info);
3605
3606 /* Check if transport restart listener succeed. */
3607 for (; j < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++j) {
3608 if (pjsua_var.tpdata[j].data.ptr != NULL &&
3609 pjsua_var.tpdata[j].restart_status != PJ_SUCCESS &&
3610 pjsua_var.tpdata[j].type == regc_info.transport->key.type)
3611 {
3612 if ((pjsua_var.tpdata[j].data.factory
3613 == regc_info.transport->factory) ||
3614 (pjsua_var.tpdata[j].data.tp
3615 == regc_info.transport))
3616 {
3617 found_restart_tp_fail = PJ_TRUE;
3618 break;
3619 }
3620 }
3621 }
3622
3623 if (found_restart_tp_fail) {
3624 if (acc->ka_timer.id) {
3625 pjsip_endpt_cancel_timer(pjsua_var.endpt, &acc->ka_timer);
3626 acc->ka_timer.id = PJ_FALSE;
3627
3628 if (acc->ka_transport) {
3629 pjsip_transport_dec_ref(acc->ka_transport);
3630 acc->ka_transport = NULL;
3631 }
3632 }
3633 pjsua_acc_end_ip_change(acc);
3634 continue;
3635 }
3636
3637 if ((regc_info.transport) &&
3638 ((regc_info.transport->flag & PJSIP_TRANSPORT_DATAGRAM) == 0))
3639 {
3640 transport = regc_info.transport;
3641 shutdown_transport = acc->cfg.ip_change_cfg.shutdown_tp;
3642 shut_acc_ids[shut_acc_cnt++] = acc->index;
3643 }
3644 } else if (acc->cfg.reg_uri.slen &&
3645 acc->reg_last_code != PJSIP_SC_OK &&
3646 acc->reg_last_code != PJSIP_SC_REQUEST_TIMEOUT &&
3647 acc->reg_last_code != PJSIP_SC_INTERNAL_SERVER_ERROR &&
3648 acc->reg_last_code != PJSIP_SC_BAD_GATEWAY &&
3649 acc->reg_last_code != PJSIP_SC_SERVICE_UNAVAILABLE &&
3650 acc->reg_last_code != PJSIP_SC_SERVER_TIMEOUT &&
3651 acc->reg_last_code != PJSIP_SC_TEMPORARILY_UNAVAILABLE)
3652 {
3653 PJ_LOG(3, (THIS_FILE, "Permanent registration failure, "
3654 "IP change handling will stop for acc %d", acc->index));
3655
3656 pjsua_acc_end_ip_change(acc);
3657 continue;
3658 }
3659 pj_ansi_snprintf(acc_id, sizeof(acc_id), "#%d", i);
3660
3661 if (transport) {
3662 unsigned j = i + 1;
3663
3664 /* Find other account that uses the same transport. */
3665 for (; j < (int)PJ_ARRAY_SIZE(pjsua_var.acc); ++j) {
3666 pjsip_regc_info tmp_regc_info;
3667 pjsua_acc *next_acc = &pjsua_var.acc[j];
3668
3669 if (!next_acc->valid || !next_acc->regc ||
3670 (next_acc->ip_change_op > PJSUA_IP_CHANGE_OP_NULL))
3671 {
3672 continue;
3673 }
3674
3675 pjsip_regc_get_info(next_acc->regc, &tmp_regc_info);
3676 if (transport == tmp_regc_info.transport) {
3677 char tmp_buf[4];
3678
3679 pj_ansi_snprintf(tmp_buf, sizeof(tmp_buf), " #%d", j);
3680 if (pj_ansi_strlen(acc_id) + pj_ansi_strlen(tmp_buf) <
3681 sizeof(acc_id))
3682 {
3683 pj_ansi_strcat(acc_id, tmp_buf);
3684 }
3685
3686 shut_acc_ids[shut_acc_cnt++] = j;
3687 if (!shutdown_transport) {
3688 shutdown_transport =
3689 next_acc->cfg.ip_change_cfg.shutdown_tp;
3690 }
3691 }
3692 }
3693 }
3694
3695 if (shutdown_transport) {
3696 unsigned j;
3697 /* Shutdown the transport. */
3698 PJ_LOG(3, (THIS_FILE, "Shutdown transport %s used by account %s "
3699 "triggered by IP change", transport->obj_name, acc_id));
3700
3701 for (j = 0; j < shut_acc_cnt; ++j) {
3702 pjsua_acc *tmp_acc = &pjsua_var.acc[shut_acc_ids[j]];
3703 tmp_acc->ip_change_op = PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP;
3704 acc_done[shut_acc_ids[j]] = PJ_TRUE;
3705 }
3706
3707 status = pjsip_transport_shutdown2(transport, PJ_TRUE);
3708 } else {
3709 acc_done[i] = PJ_TRUE;
3710 if (acc->cfg.allow_contact_rewrite && acc->cfg.reg_uri.slen) {
3711 status = pjsua_acc_update_contact_on_ip_change(acc);
3712 } else {
3713 status = pjsua_acc_handle_call_on_ip_change(acc);
3714 }
3715 }
3716 }
3717 PJSUA_UNLOCK();
3718 return status;
3719 }
3720
3721
restart_listener(pjsua_transport_id id,unsigned restart_lis_delay)3722 static pj_status_t restart_listener(pjsua_transport_id id,
3723 unsigned restart_lis_delay)
3724 {
3725 pj_sockaddr bind_addr;
3726 pjsua_transport_info tp_info;
3727 pj_status_t status;
3728
3729 pjsua_transport_get_info(id, &tp_info);
3730 pj_sockaddr_init(pjsip_transport_type_get_af(tp_info.type),
3731 &bind_addr,
3732 NULL,
3733 pj_sockaddr_get_port(&tp_info.local_addr));
3734
3735 switch (tp_info.type) {
3736 case PJSIP_TRANSPORT_UDP:
3737 case PJSIP_TRANSPORT_UDP6:
3738 status = pjsip_udp_transport_restart2(
3739 pjsua_var.tpdata[id].data.tp,
3740 PJSIP_UDP_TRANSPORT_DESTROY_SOCKET,
3741 PJ_INVALID_SOCKET,
3742 &bind_addr,
3743 NULL);
3744 break;
3745
3746 #if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0
3747 case PJSIP_TRANSPORT_TLS:
3748 case PJSIP_TRANSPORT_TLS6:
3749 status = pjsip_tls_transport_restart(
3750 pjsua_var.tpdata[id].data.factory,
3751 &bind_addr,
3752 NULL);
3753 break;
3754 #endif
3755 case PJSIP_TRANSPORT_TCP:
3756 case PJSIP_TRANSPORT_TCP6:
3757 status = pjsip_tcp_transport_restart(
3758 pjsua_var.tpdata[id].data.factory,
3759 &bind_addr,
3760 NULL);
3761 break;
3762
3763 default:
3764 status = PJ_EINVAL;
3765 }
3766
3767 PJ_PERROR(3,(THIS_FILE, status, "Listener %.*s restart",
3768 tp_info.info.slen, tp_info.info.ptr));
3769
3770 if (status != PJ_SUCCESS && (restart_lis_delay > 0)) {
3771 /* Try restarting again, with delay. */
3772 pjsua_schedule_timer2(&restart_listener_cb,
3773 (void*)(pj_size_t)id,
3774 restart_lis_delay);
3775
3776 PJ_LOG(3,(THIS_FILE, "Retry listener %.*s restart in %d ms",
3777 tp_info.info.slen, tp_info.info.ptr, restart_lis_delay));
3778
3779 status = PJ_SUCCESS;
3780 } else {
3781 int i = 0;
3782 pj_bool_t all_done = PJ_TRUE;
3783
3784 pjsua_var.tpdata[id].is_restarting = PJ_FALSE;
3785 pjsua_var.tpdata[id].restart_status = status;
3786 if (pjsua_var.ua_cfg.cb.on_ip_change_progress) {
3787 pjsua_ip_change_op_info info;
3788
3789 pj_bzero(&info, sizeof(info));
3790 info.lis_restart.transport_id = id;
3791 pjsua_var.ua_cfg.cb.on_ip_change_progress(
3792 PJSUA_IP_CHANGE_OP_RESTART_LIS,
3793 status,
3794 &info);
3795 }
3796
3797 /* Move forward if all listener has been restarted. */
3798 for (; i < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) {
3799 if (pjsua_var.tpdata[i].data.ptr != NULL &&
3800 pjsua_var.tpdata[i].is_restarting)
3801 {
3802 all_done = PJ_FALSE;
3803 break;
3804 }
3805 }
3806 if (all_done)
3807 status = handle_ip_change_on_acc();
3808 }
3809 return status;
3810 }
3811
3812
restart_listener_cb(void * user_data)3813 static void restart_listener_cb(void *user_data)
3814 {
3815 pjsua_transport_id transport_id = (pjsua_transport_id)(pj_size_t)user_data;
3816 restart_listener(transport_id, 0);
3817 }
3818
3819
pjsua_handle_ip_change(const pjsua_ip_change_param * param)3820 PJ_DEF(pj_status_t) pjsua_handle_ip_change(const pjsua_ip_change_param *param)
3821 {
3822 pj_status_t status = PJ_SUCCESS;
3823 int i = 0;
3824
3825 PJ_ASSERT_RETURN(param, PJ_EINVAL);
3826
3827 for (; i < (int)PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
3828 if (pjsua_var.acc[i].valid &&
3829 pjsua_var.acc[i].ip_change_op != PJSUA_IP_CHANGE_OP_NULL &&
3830 pjsua_var.acc[i].ip_change_op != PJSUA_IP_CHANGE_OP_COMPLETED)
3831 {
3832 PJ_LOG(2, (THIS_FILE,
3833 "Previous IP address change handling still in progress"));
3834 }
3835 }
3836
3837 PJ_LOG(3, (THIS_FILE, "Start handling IP address change"));
3838 if (param->restart_listener) {
3839 PJSUA_LOCK();
3840 /* Restart listener/transport, handle_ip_change_on_acc() will
3841 * be called after listener restart is completed successfully.
3842 */
3843 for (i = 0; i < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) {
3844 if (pjsua_var.tpdata[i].data.ptr != NULL) {
3845 pjsua_var.tpdata[i].is_restarting = PJ_TRUE;
3846 pjsua_var.tpdata[i].restart_status = PJ_EUNKNOWN;
3847 }
3848 }
3849 for (i = 0; i < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) {
3850 if (pjsua_var.tpdata[i].data.ptr != NULL) {
3851 status = restart_listener(i, param->restart_lis_delay);
3852 }
3853 }
3854 PJSUA_UNLOCK();
3855 } else {
3856 for (i = 0; i < PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) {
3857 if (pjsua_var.tpdata[i].data.ptr != NULL) {
3858 pjsua_var.tpdata[i].restart_status = PJ_SUCCESS;
3859 }
3860 }
3861 status = handle_ip_change_on_acc();
3862 }
3863
3864 return status;
3865 }
3866