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, &regc_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