Changeset 476 for pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
- Timestamp:
- May 26, 2006 12:17:46 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
r452 r476 18 18 */ 19 19 #include <pjsua-lib/pjsua.h> 20 #include "pjsua_imp.h" 20 21 21 22 /* … … 44 45 * Init default application parameters. 45 46 */ 46 void pjsua_default(void)47 PJ_DEF(void) pjsua_default_config(pjsua_config *cfg) 47 48 { 48 49 unsigned i; 49 50 50 51 /* Normally need another thread for console application, because main 52 * thread will be blocked in fgets(). 53 */ 54 pjsua.thread_cnt = 1; 55 56 57 /* Default transport settings: */ 58 pjsua.sip_port = 5060; 59 60 61 /* Default we start RTP at port 4000 */ 62 pjsua.start_rtp_port = 4000; 63 64 65 /* Default logging settings: */ 66 pjsua.log_level = 5; 67 pjsua.app_log_level = 4; 68 pjsua.log_decor = PJ_LOG_HAS_SENDER | PJ_LOG_HAS_TIME | 69 PJ_LOG_HAS_MICRO_SEC | PJ_LOG_HAS_NEWLINE; 70 71 72 /* Default call settings. */ 73 pjsua.uas_refresh = -1; 74 pjsua.uas_duration = -1; 75 76 /* Default: do not use STUN: */ 77 pjsua.stun_port1 = pjsua.stun_port2 = 0; 78 79 /* Default for media: */ 51 pj_memset(cfg, 0, sizeof(pjsua_config)); 52 53 cfg->thread_cnt = 1; 54 cfg->udp_port = 5060; 55 cfg->start_rtp_port = 4000; 56 cfg->max_calls = 4; 57 cfg->conf_ports = 0; 58 80 59 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 81 60 pjsua.clock_rate = 44100; 82 61 #endif 83 pjsua.complexity = -1; 84 pjsua.quality = 4; 62 63 cfg->complexity = 10; 64 cfg->quality = 10; 65 66 cfg->auto_answer = 100; 67 cfg->uas_duration = 3600; 68 69 /* Default logging settings: */ 70 cfg->log_level = 5; 71 cfg->app_log_level = 4; 72 cfg->log_decor = PJ_LOG_HAS_SENDER | PJ_LOG_HAS_TIME | 73 PJ_LOG_HAS_MICRO_SEC | PJ_LOG_HAS_NEWLINE; 74 75 76 /* Also init logging settings in pjsua.config, because log 77 * may be written before pjsua_init() is called. 78 */ 79 pjsua.config.log_level = 5; 80 pjsua.config.app_log_level = 4; 85 81 86 82 87 83 /* Init accounts: */ 88 pjsua.acc_cnt = 1;89 84 for (i=0; i<PJ_ARRAY_SIZE(pjsua.acc); ++i) { 90 pjsua.acc[i].index = i; 91 pjsua.acc[i].local_uri = pj_str(PJSUA_LOCAL_URI); 92 pjsua.acc[i].reg_timeout = 55; 93 pjsua.acc[i].online_status = PJ_TRUE; 94 pj_list_init(&pjsua.acc[i].route_set); 95 pj_list_init(&pjsua.acc[i].pres_srv_list); 96 } 97 98 /* Init call array: */ 99 for (i=0; i<PJ_ARRAY_SIZE(pjsua.calls); ++i) { 100 pjsua.calls[i].index = i; 101 pjsua.calls[i].refresh_tm._timer_id = -1; 102 pjsua.calls[i].hangup_tm._timer_id = -1; 103 pjsua.calls[i].conf_slot = 0; 104 } 105 106 /* Default max nb of calls. */ 107 pjsua.max_calls = 4; 108 109 /* Init server presence subscription list: */ 110 111 112 } 113 85 cfg->acc_config[i].reg_timeout = 55; 86 } 87 } 88 89 90 #define strncpy_with_null(dst,src,len) \ 91 do { \ 92 strncpy(dst, src, len); \ 93 dst[len-1] = '\0'; \ 94 } while (0) 95 96 97 98 PJ_DEF(pj_status_t) pjsua_test_config( const pjsua_config *cfg, 99 char *errmsg, 100 int len) 101 { 102 unsigned i; 103 104 /* If UDP port is zero, then sip_host and sip_port must be specified */ 105 if (cfg->udp_port == 0) { 106 if (cfg->sip_host.slen==0 || cfg->sip_port==0) { 107 strncpy_with_null(errmsg, 108 "sip_host and sip_port must be specified", 109 len); 110 return -1; 111 } 112 } 113 114 if (cfg->max_calls < 1) { 115 strncpy_with_null(errmsg, 116 "max_calls needs to be at least 1", 117 len); 118 return -1; 119 } 120 121 /* STUN */ 122 if (cfg->stun_srv1.slen || cfg->stun_port1 || cfg->stun_port2 || 123 cfg->stun_srv2.slen) 124 { 125 if (cfg->stun_port1 == 0) { 126 strncpy_with_null(errmsg, "stun_port1 required", len); 127 return -1; 128 } 129 if (cfg->stun_srv1.slen == 0) { 130 strncpy_with_null(errmsg, "stun_srv1 required", len); 131 return -1; 132 } 133 if (cfg->stun_port2 == 0) { 134 strncpy_with_null(errmsg, "stun_port2 required", len); 135 return -1; 136 } 137 if (cfg->stun_srv2.slen == 0) { 138 strncpy_with_null(errmsg, "stun_srv2 required", len); 139 return -1; 140 } 141 } 142 143 /* Verify accounts */ 144 for (i=0; i<cfg->acc_cnt; ++i) { 145 const pjsua_acc_config *acc_cfg = &cfg->acc_config[i]; 146 unsigned j; 147 148 if (acc_cfg->id.slen == 0) { 149 strncpy_with_null(errmsg, "missing account ID", len); 150 return -1; 151 } 152 153 if (acc_cfg->id.slen == 0) { 154 strncpy_with_null(errmsg, "missing registrar URI", len); 155 return -1; 156 } 157 158 if (acc_cfg->reg_timeout == 0) { 159 strncpy_with_null(errmsg, "missing registration timeout", len); 160 return -1; 161 } 162 163 164 for (j=0; j<acc_cfg->cred_count; ++j) { 165 166 if (acc_cfg->cred_info[j].scheme.slen == 0) { 167 strncpy_with_null(errmsg, "missing auth scheme in account", 168 len); 169 return -1; 170 } 171 172 if (acc_cfg->cred_info[j].realm.slen == 0) { 173 strncpy_with_null(errmsg, "missing realm in account", len); 174 return -1; 175 } 176 177 if (acc_cfg->cred_info[j].username.slen == 0) { 178 strncpy_with_null(errmsg, "missing username in account", len); 179 return -1; 180 } 181 182 } 183 } 184 185 return PJ_SUCCESS; 186 } 114 187 115 188 … … 153 226 154 227 228 static int PJ_THREAD_FUNC pjsua_poll(void *arg) 229 { 230 pj_status_t last_err = 0; 231 232 PJ_UNUSED_ARG(arg); 233 234 do { 235 pj_time_val timeout = { 0, 10 }; 236 pj_status_t status; 237 238 status = pjsip_endpt_handle_events (pjsua.endpt, &timeout); 239 if (status != PJ_SUCCESS && status != last_err) { 240 last_err = status; 241 pjsua_perror(THIS_FILE, "handle_events() returned error", status); 242 } 243 } while (!pjsua.quit_flag); 244 245 return 0; 246 } 247 248 249 250 #define pjsua_has_stun() (pjsua.config.stun_port1 && \ 251 pjsua.config.stun_port2) 252 253 254 /* 255 * Create and initialize SIP socket (and possibly resolve public 256 * address via STUN, depending on config). 257 */ 258 static pj_status_t create_sip_udp_sock(int port, 259 pj_sock_t *p_sock, 260 pj_sockaddr_in *p_pub_addr) 261 { 262 pj_sock_t sock; 263 pj_status_t status; 264 265 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock); 266 if (status != PJ_SUCCESS) { 267 pjsua_perror(THIS_FILE, "socket() error", status); 268 return status; 269 } 270 271 status = pj_sock_bind_in(sock, 0, (pj_uint16_t)port); 272 if (status != PJ_SUCCESS) { 273 pjsua_perror(THIS_FILE, "bind() error", status); 274 pj_sock_close(sock); 275 return status; 276 } 277 278 if (pjsua_has_stun()) { 279 status = pj_stun_get_mapped_addr(&pjsua.cp.factory, 1, &sock, 280 &pjsua.config.stun_srv1, 281 pjsua.config.stun_port1, 282 &pjsua.config.stun_srv2, 283 pjsua.config.stun_port2, 284 p_pub_addr); 285 if (status != PJ_SUCCESS) { 286 pjsua_perror(THIS_FILE, "STUN resolve error", status); 287 pj_sock_close(sock); 288 return status; 289 } 290 291 } else { 292 293 const pj_str_t *hostname = pj_gethostname(); 294 struct pj_hostent he; 295 296 status = pj_gethostbyname(hostname, &he); 297 if (status != PJ_SUCCESS) { 298 pjsua_perror(THIS_FILE, "Unable to resolve local host", status); 299 pj_sock_close(sock); 300 return status; 301 } 302 303 pj_memset(p_pub_addr, 0, sizeof(pj_sockaddr_in)); 304 p_pub_addr->sin_family = PJ_AF_INET; 305 p_pub_addr->sin_port = pj_htons((pj_uint16_t)port); 306 p_pub_addr->sin_addr = *(pj_in_addr*)he.h_addr; 307 } 308 309 *p_sock = sock; 310 return PJ_SUCCESS; 311 } 312 313 155 314 /* 156 * Initialize sockets and optionally get the public address via STUN.157 * /158 static pj_status_t init_sockets(pj_bool_t sip, 159 315 * Create RTP and RTCP socket pair, and possibly resolve their public 316 * address via STUN. 317 */ 318 static pj_status_t create_rtp_rtcp_sock(pjmedia_sock_info *skinfo) 160 319 { 161 320 enum { 162 321 RTP_RETRY = 100 163 322 }; 164 enum {165 SIP_SOCK,166 RTP_SOCK,167 RTCP_SOCK,168 };169 323 int i; 170 324 static pj_uint16_t rtp_port; 171 pj_sock_t sock[3]; 172 pj_sockaddr_in mapped_addr[3]; 325 pj_sockaddr_in mapped_addr[2]; 173 326 pj_status_t status = PJ_SUCCESS; 327 pj_sock_t sock[2]; 174 328 175 329 if (rtp_port == 0) 176 rtp_port = (pj_uint16_t)pjsua. start_rtp_port;177 178 for (i=0; i< 3; ++i)330 rtp_port = (pj_uint16_t)pjsua.config.start_rtp_port; 331 332 for (i=0; i<2; ++i) 179 333 sock[i] = PJ_INVALID_SOCKET; 180 181 /* Create and bind SIP UDP socket. */182 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[SIP_SOCK]);183 if (status != PJ_SUCCESS) {184 pjsua_perror(THIS_FILE, "socket() error", status);185 goto on_error;186 }187 188 if (sip) {189 status = pj_sock_bind_in(sock[SIP_SOCK], 0, pjsua.sip_port);190 if (status != PJ_SUCCESS) {191 pjsua_perror(THIS_FILE, "bind() error", status);192 goto on_error;193 }194 } else {195 status = pj_sock_bind_in(sock[SIP_SOCK], 0, 0);196 if (status != PJ_SUCCESS) {197 pjsua_perror(THIS_FILE, "bind() error", status);198 goto on_error;199 }200 }201 334 202 335 … … 205 338 206 339 /* Create and bind RTP socket. */ 207 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[ RTP_SOCK]);340 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[0]); 208 341 if (status != PJ_SUCCESS) { 209 342 pjsua_perror(THIS_FILE, "socket() error", status); 210 goto on_error;211 } 212 213 status = pj_sock_bind_in(sock[ RTP_SOCK], 0, rtp_port);343 return status; 344 } 345 346 status = pj_sock_bind_in(sock[0], 0, rtp_port); 214 347 if (status != PJ_SUCCESS) { 215 pj_sock_close(sock[ RTP_SOCK]);216 sock[ RTP_SOCK] = PJ_INVALID_SOCKET;348 pj_sock_close(sock[0]); 349 sock[0] = PJ_INVALID_SOCKET; 217 350 continue; 218 351 } 219 352 220 353 /* Create and bind RTCP socket. */ 221 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[ RTCP_SOCK]);354 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[1]); 222 355 if (status != PJ_SUCCESS) { 223 356 pjsua_perror(THIS_FILE, "socket() error", status); 224 goto on_error; 225 } 226 227 status = pj_sock_bind_in(sock[RTCP_SOCK], 0, (pj_uint16_t)(rtp_port+1)); 357 pj_sock_close(sock[0]); 358 return status; 359 } 360 361 status = pj_sock_bind_in(sock[1], 0, (pj_uint16_t)(rtp_port+1)); 228 362 if (status != PJ_SUCCESS) { 229 pj_sock_close(sock[ RTP_SOCK]);230 sock[ RTP_SOCK] = PJ_INVALID_SOCKET;231 232 pj_sock_close(sock[ RTCP_SOCK]);233 sock[ RTCP_SOCK] = PJ_INVALID_SOCKET;363 pj_sock_close(sock[0]); 364 sock[0] = PJ_INVALID_SOCKET; 365 366 pj_sock_close(sock[1]); 367 sock[1] = PJ_INVALID_SOCKET; 234 368 continue; 235 369 } … … 239 373 * and make sure that the mapped RTCP port is adjacent with the RTP. 240 374 */ 241 if (pjsua.stun_port1 == 0) { 375 if (pjsua_has_stun()) { 376 status=pj_stun_get_mapped_addr(&pjsua.cp.factory, 2, sock, 377 &pjsua.config.stun_srv1, 378 pjsua.config.stun_port1, 379 &pjsua.config.stun_srv2, 380 pjsua.config.stun_port2, 381 mapped_addr); 382 if (status != PJ_SUCCESS) { 383 pjsua_perror(THIS_FILE, "STUN resolve error", status); 384 goto on_error; 385 } 386 387 if (pj_ntohs(mapped_addr[1].sin_port) == 388 pj_ntohs(mapped_addr[0].sin_port)+1) 389 { 390 /* Success! */ 391 break; 392 } 393 394 pj_sock_close(sock[0]); 395 sock[0] = PJ_INVALID_SOCKET; 396 397 pj_sock_close(sock[1]); 398 sock[1] = PJ_INVALID_SOCKET; 399 400 } else { 242 401 const pj_str_t *hostname; 243 402 pj_sockaddr_in addr; … … 255 414 } 256 415 257 for (i=0; i< 3; ++i)416 for (i=0; i<2; ++i) 258 417 pj_memcpy(&mapped_addr[i], &addr, sizeof(addr)); 259 418 260 if (sip) { 261 mapped_addr[SIP_SOCK].sin_port = 262 pj_htons((pj_uint16_t)pjsua.sip_port); 263 } 264 mapped_addr[RTP_SOCK].sin_port=pj_htons((pj_uint16_t)rtp_port); 265 mapped_addr[RTCP_SOCK].sin_port=pj_htons((pj_uint16_t)(rtp_port+1)); 419 mapped_addr[0].sin_port=pj_htons((pj_uint16_t)rtp_port); 420 mapped_addr[1].sin_port=pj_htons((pj_uint16_t)(rtp_port+1)); 266 421 break; 267 268 } else { 269 status=pj_stun_get_mapped_addr(&pjsua.cp.factory, 3, sock, 270 &pjsua.stun_srv1, pjsua.stun_port1, 271 &pjsua.stun_srv2, pjsua.stun_port2, 272 mapped_addr); 273 if (status != PJ_SUCCESS) { 274 pjsua_perror(THIS_FILE, "STUN error", status); 275 goto on_error; 276 } 277 278 if (pj_ntohs(mapped_addr[2].sin_port) == 279 pj_ntohs(mapped_addr[1].sin_port)+1) 280 { 281 break; 282 } 283 284 pj_sock_close(sock[RTP_SOCK]); 285 sock[RTP_SOCK] = PJ_INVALID_SOCKET; 286 287 pj_sock_close(sock[RTCP_SOCK]); 288 sock[RTCP_SOCK] = PJ_INVALID_SOCKET; 289 } 290 } 291 292 if (sock[RTP_SOCK] == PJ_INVALID_SOCKET) { 422 } 423 } 424 425 if (sock[0] == PJ_INVALID_SOCKET) { 293 426 PJ_LOG(1,(THIS_FILE, 294 427 "Unable to find appropriate RTP/RTCP ports combination")); … … 296 429 } 297 430 298 if (sip) { 299 pjsua.sip_sock = sock[SIP_SOCK]; 300 pj_memcpy(&pjsua.sip_sock_name, 301 &mapped_addr[SIP_SOCK], 302 sizeof(pj_sockaddr_in)); 303 } else { 304 pj_sock_close(sock[0]); 305 } 306 307 skinfo->rtp_sock = sock[RTP_SOCK]; 431 432 skinfo->rtp_sock = sock[0]; 308 433 pj_memcpy(&skinfo->rtp_addr_name, 309 &mapped_addr[ RTP_SOCK], sizeof(pj_sockaddr_in));310 311 skinfo->rtcp_sock = sock[ RTCP_SOCK];434 &mapped_addr[0], sizeof(pj_sockaddr_in)); 435 436 skinfo->rtcp_sock = sock[1]; 312 437 pj_memcpy(&skinfo->rtcp_addr_name, 313 &mapped_addr[RTCP_SOCK], sizeof(pj_sockaddr_in)); 314 315 if (sip) { 316 PJ_LOG(4,(THIS_FILE, "SIP UDP socket reachable at %s:%d", 317 pj_inet_ntoa(pjsua.sip_sock_name.sin_addr), 318 pj_ntohs(pjsua.sip_sock_name.sin_port))); 319 } 438 &mapped_addr[1], sizeof(pj_sockaddr_in)); 439 320 440 PJ_LOG(4,(THIS_FILE, "RTP socket reachable at %s:%d", 321 441 pj_inet_ntoa(skinfo->rtp_addr_name.sin_addr), … … 329 449 330 450 on_error: 331 for (i=0; i<3; ++i) { 332 if (sip && i==0) 333 continue; 451 for (i=0; i<2; ++i) { 334 452 if (sock[i] != PJ_INVALID_SOCKET) 335 453 pj_sock_close(sock[i]); … … 340 458 341 459 342 /* 343 * Initialize stack. 344 */ 345 static pj_status_t init_stack(void) 460 /** 461 * Create pjsua application. 462 * This initializes pjlib/pjlib-util, and creates memory pool factory to 463 * be used by application. 464 */ 465 PJ_DEF(pj_status_t) pjsua_create(void) 346 466 { 347 467 pj_status_t status; 348 468 469 /* Init PJLIB: */ 470 471 status = pj_init(); 472 if (status != PJ_SUCCESS) { 473 pjsua_perror(THIS_FILE, "pj_init() error", status); 474 return status; 475 } 476 477 /* Init PJLIB-UTIL: */ 478 479 status = pjlib_util_init(); 480 if (status != PJ_SUCCESS) { 481 pjsua_perror(THIS_FILE, "pjlib_util_init() error", status); 482 return status; 483 } 484 485 /* Init memory pool: */ 486 487 /* Init caching pool. */ 488 pj_caching_pool_init(&pjsua.cp, &pj_pool_factory_default_policy, 0); 489 490 /* Create memory pool for application. */ 491 pjsua.pool = pj_pool_create(&pjsua.cp.factory, "pjsua", 4000, 4000, NULL); 492 493 /* Must create endpoint to initialize SIP parser. */ 349 494 /* Create global endpoint: */ 350 495 351 { 352 const pj_str_t *hostname; 353 const char *endpt_name; 354 355 /* Endpoint MUST be assigned a globally unique name. 356 * The name will be used as the hostname in Warning header. 357 */ 358 359 /* For this implementation, we'll use hostname for simplicity */ 360 hostname = pj_gethostname(); 361 endpt_name = hostname->ptr; 362 363 /* Create the endpoint: */ 364 365 status = pjsip_endpt_create(&pjsua.cp.factory, endpt_name, 366 &pjsua.endpt); 496 status = pjsip_endpt_create(&pjsua.cp.factory, 497 pj_gethostname()->ptr, 498 &pjsua.endpt); 499 if (status != PJ_SUCCESS) { 500 pjsua_perror(THIS_FILE, "Unable to create SIP endpoint", status); 501 return status; 502 } 503 504 /* Must create media endpoint too */ 505 status = pjmedia_endpt_create(&pjsua.cp.factory, 506 pjsip_endpt_get_ioqueue(pjsua.endpt), 0, 507 &pjsua.med_endpt); 508 if (status != PJ_SUCCESS) { 509 pjsua_perror(THIS_FILE, 510 "Media stack initialization has returned error", 511 status); 512 return status; 513 } 514 515 516 return PJ_SUCCESS; 517 } 518 519 520 521 /* 522 * Init media. 523 */ 524 static pj_status_t init_media(void) 525 { 526 int i; 527 unsigned options; 528 unsigned clock_rate; 529 unsigned samples_per_frame; 530 pj_str_t codec_id; 531 pj_status_t status; 532 533 /* Register all codecs */ 534 #if PJMEDIA_HAS_SPEEX_CODEC 535 /* Register speex. */ 536 status = pjmedia_codec_speex_init(pjsua.med_endpt, 537 PJMEDIA_SPEEX_NO_UWB, 538 pjsua.config.quality, 539 pjsua.config.complexity ); 540 if (status != PJ_SUCCESS) { 541 pjsua_perror(THIS_FILE, "Error initializing Speex codec", 542 status); 543 return status; 544 } 545 546 /* Set "speex/16000/1" to have highest priority */ 547 codec_id = pj_str("speex/16000/1"); 548 pjmedia_codec_mgr_set_codec_priority( 549 pjmedia_endpt_get_codec_mgr(pjsua.med_endpt), 550 &codec_id, 551 PJMEDIA_CODEC_PRIO_HIGHEST); 552 553 #endif /* PJMEDIA_HAS_SPEEX_CODEC */ 554 555 #if PJMEDIA_HAS_GSM_CODEC 556 /* Register GSM */ 557 status = pjmedia_codec_gsm_init(pjsua.med_endpt); 558 if (status != PJ_SUCCESS) { 559 pjsua_perror(THIS_FILE, "Error initializing GSM codec", 560 status); 561 return status; 562 } 563 #endif /* PJMEDIA_HAS_GSM_CODEC */ 564 565 #if PJMEDIA_HAS_G711_CODEC 566 /* Register PCMA and PCMU */ 567 status = pjmedia_codec_g711_init(pjsua.med_endpt); 568 if (status != PJ_SUCCESS) { 569 pjsua_perror(THIS_FILE, "Error initializing G711 codec", 570 status); 571 return status; 572 } 573 #endif /* PJMEDIA_HAS_G711_CODEC */ 574 575 #if PJMEDIA_HAS_L16_CODEC 576 /* Register L16 family codecs, but disable all */ 577 status = pjmedia_codec_l16_init(pjsua.med_endpt, 0); 578 if (status != PJ_SUCCESS) { 579 pjsua_perror(THIS_FILE, "Error initializing L16 codecs", 580 status); 581 return status; 582 } 583 584 /* Disable ALL L16 codecs */ 585 codec_id = pj_str("L16"); 586 pjmedia_codec_mgr_set_codec_priority( 587 pjmedia_endpt_get_codec_mgr(pjsua.med_endpt), 588 &codec_id, 589 PJMEDIA_CODEC_PRIO_DISABLED); 590 591 #endif /* PJMEDIA_HAS_L16_CODEC */ 592 593 594 /* Enable those codecs that user put with "--add-codec", and move 595 * the priority to top 596 */ 597 for (i=0; i<(int)pjsua.config.codec_cnt; ++i) { 598 pjmedia_codec_mgr_set_codec_priority( 599 pjmedia_endpt_get_codec_mgr(pjsua.med_endpt), 600 &pjsua.config.codec_arg[i], 601 PJMEDIA_CODEC_PRIO_HIGHEST); 602 } 603 604 605 /* Init options for conference bridge. */ 606 options = 0; 607 608 /* Calculate maximum number of ports, if it's not specified */ 609 if (pjsua.config.conf_ports == 0) { 610 pjsua.config.conf_ports = 3 * pjsua.config.max_calls; 611 } 612 613 /* Init conference bridge. */ 614 clock_rate = pjsua.config.clock_rate ? pjsua.config.clock_rate : 16000; 615 samples_per_frame = clock_rate * 10 / 1000; 616 status = pjmedia_conf_create(pjsua.pool, 617 pjsua.config.conf_ports, 618 clock_rate, 619 1, /* mono */ 620 samples_per_frame, 621 16, 622 options, 623 &pjsua.mconf); 624 if (status != PJ_SUCCESS) { 625 pjsua_perror(THIS_FILE, 626 "Media stack initialization has returned error", 627 status); 628 return status; 629 } 630 631 /* Create WAV file player if required: */ 632 633 if (pjsua.config.wav_file.slen) { 634 pj_str_t port_name; 635 636 /* Create the file player port. */ 637 status = pjmedia_wav_player_port_create( pjsua.pool, 638 pjsua.config.wav_file.ptr, 639 0, 0, -1, NULL, 640 &pjsua.file_port); 367 641 if (status != PJ_SUCCESS) { 368 pjsua_perror(THIS_FILE, "Unable to create SIP endpoint", status); 642 pjsua_perror(THIS_FILE, 643 "Error playing media file", 644 status); 369 645 return status; 370 646 } 371 } 372 647 648 /* Add port to conference bridge: */ 649 port_name = pjsua.config.wav_file; 650 status = pjmedia_conf_add_port(pjsua.mconf, pjsua.pool, 651 pjsua.file_port, 652 &port_name, 653 &pjsua.wav_slot); 654 if (status != PJ_SUCCESS) { 655 pjsua_perror(THIS_FILE, 656 "Unable to add file player to conference bridge", 657 status); 658 return status; 659 } 660 } 661 662 663 return PJ_SUCCESS; 664 } 665 666 667 /* 668 * Copy configuration. 669 */ 670 static void copy_config(pj_pool_t *pool, pjsua_config *dst, 671 const pjsua_config *src) 672 { 673 unsigned i; 674 675 /* Plain memcpy */ 676 pj_memcpy(dst, src, sizeof(pjsua_config)); 677 678 /* Duplicate strings */ 679 pj_strdup_with_null(pool, &dst->sip_host, &src->sip_host); 680 pj_strdup_with_null(pool, &dst->stun_srv1, &src->stun_srv1); 681 pj_strdup_with_null(pool, &dst->stun_srv2, &src->stun_srv2); 682 pj_strdup_with_null(pool, &dst->wav_file, &src->wav_file); 683 684 for (i=0; i<src->codec_cnt; ++i) { 685 pj_strdup_with_null(pool, &dst->codec_arg[i], &src->codec_arg[i]); 686 } 687 688 pj_strdup_with_null(pool, &dst->outbound_proxy, &src->outbound_proxy); 689 pj_strdup_with_null(pool, &dst->uri_to_call, &src->uri_to_call); 690 691 for (i=0; i<src->acc_cnt; ++i) { 692 pjsua_acc_config *dst_acc = &dst->acc_config[i]; 693 const pjsua_acc_config *src_acc = &src->acc_config[i]; 694 unsigned j; 695 696 pj_strdup_with_null(pool, &dst_acc->id, &src_acc->id); 697 pj_strdup_with_null(pool, &dst_acc->reg_uri, &src_acc->reg_uri); 698 pj_strdup_with_null(pool, &dst_acc->contact, &src_acc->contact); 699 pj_strdup_with_null(pool, &dst_acc->proxy, &src_acc->proxy); 700 701 for (j=0; j<src_acc->cred_count; ++j) { 702 pj_strdup_with_null(pool, &dst_acc->cred_info[j].realm, 703 &src_acc->cred_info[j].realm); 704 pj_strdup_with_null(pool, &dst_acc->cred_info[j].scheme, 705 &src_acc->cred_info[j].scheme); 706 pj_strdup_with_null(pool, &dst_acc->cred_info[j].username, 707 &src_acc->cred_info[j].username); 708 pj_strdup_with_null(pool, &dst_acc->cred_info[j].data, 709 &src_acc->cred_info[j].data); 710 } 711 } 712 713 pj_strdup_with_null(pool, &dst->log_filename, &src->log_filename); 714 715 for (i=0; i<src->buddy_cnt; ++i) { 716 pj_strdup_with_null(pool, &dst->buddy_uri[i], &src->buddy_uri[i]); 717 } 718 } 719 720 721 /* 722 * Initialize pjsua application. 723 * This will initialize all libraries, create endpoint instance, and register 724 * pjsip modules. 725 */ 726 PJ_DECL(pj_status_t) pjsua_init(const pjsua_config *cfg, 727 const pjsua_callback *cb) 728 { 729 char errmsg[80]; 730 unsigned i; 731 pj_status_t status; 732 733 734 /* Init accounts: */ 735 for (i=0; i<PJ_ARRAY_SIZE(pjsua.acc); ++i) { 736 pjsua.acc[i].index = i; 737 pjsua.acc[i].online_status = PJ_TRUE; 738 pj_list_init(&pjsua.acc[i].route_set); 739 pj_list_init(&pjsua.acc[i].pres_srv_list); 740 } 741 742 /* Init call array: */ 743 for (i=0; i<PJ_ARRAY_SIZE(pjsua.calls); ++i) { 744 pjsua.calls[i].index = i; 745 pjsua.calls[i].refresh_tm._timer_id = -1; 746 pjsua.calls[i].hangup_tm._timer_id = -1; 747 pjsua.calls[i].conf_slot = 0; 748 } 749 750 /* Copy configuration */ 751 copy_config(pjsua.pool, &pjsua.config, cfg); 752 753 /* Copy callback */ 754 pj_memcpy(&pjsua.cb, cb, sizeof(pjsua_callback)); 755 756 /* Test configuration */ 757 if (pjsua_test_config(&pjsua.config, errmsg, sizeof(errmsg))) { 758 PJ_LOG(1,(THIS_FILE, "Error in configuration: %s", errmsg)); 759 return -1; 760 } 761 762 763 /* Init PJLIB logging: */ 764 765 pj_log_set_level(pjsua.config.log_level); 766 pj_log_set_decor(pjsua.config.log_decor); 767 768 769 /* Create SIP UDP socket */ 770 if (pjsua.config.udp_port) { 771 772 status = create_sip_udp_sock( pjsua.config.udp_port, 773 &pjsua.sip_sock, 774 &pjsua.sip_sock_name); 775 if (status != PJ_SUCCESS) 776 return status; 777 778 pj_strdup2_with_null(pjsua.pool, &pjsua.config.sip_host, 779 pj_inet_ntoa(pjsua.sip_sock_name.sin_addr)); 780 pjsua.config.sip_port = pj_ntohs(pjsua.sip_sock_name.sin_port); 781 782 } else { 783 784 /* Check that SIP host and port is configured */ 785 if (cfg->sip_host.slen == 0 || cfg->sip_port == 0) { 786 PJ_LOG(1,(THIS_FILE, 787 "Error: sip_host and sip_port must be specified")); 788 return PJ_EINVAL; 789 } 790 791 pjsua.sip_sock = PJ_INVALID_SOCKET; 792 } 793 794 795 /* Init media endpoint */ 796 status = init_media(); 797 if (status != PJ_SUCCESS) 798 return status; 799 800 801 /* Init RTP sockets, only when UDP transport is enabled */ 802 for (i=0; pjsua.config.start_rtp_port && i<pjsua.config.max_calls; ++i) { 803 status = create_rtp_rtcp_sock(&pjsua.calls[i].skinfo); 804 if (status != PJ_SUCCESS) { 805 unsigned j; 806 for (j=0; j<i; ++j) { 807 pjmedia_transport_udp_close(pjsua.calls[j].med_tp); 808 } 809 return status; 810 } 811 status = pjmedia_transport_udp_attach(pjsua.med_endpt, NULL, 812 &pjsua.calls[i].skinfo, 813 &pjsua.calls[i].med_tp); 814 } 815 816 /* Init PJSIP : */ 373 817 374 818 /* Initialize transaction layer: */ … … 428 872 } 429 873 430 /* Done */431 432 return PJ_SUCCESS;433 434 435 on_error:436 pjsip_endpt_destroy(pjsua.endpt);437 pjsua.endpt = NULL;438 return status;439 }440 441 442 static int PJ_THREAD_FUNC pjsua_poll(void *arg)443 {444 pj_status_t last_err = 0;445 446 PJ_UNUSED_ARG(arg);447 448 do {449 pj_time_val timeout = { 0, 10 };450 pj_status_t status;451 452 status = pjsip_endpt_handle_events (pjsua.endpt, &timeout);453 if (status != PJ_SUCCESS && status != last_err) {454 last_err = status;455 pjsua_perror(THIS_FILE, "handle_events() returned error", status);456 }457 } while (!pjsua.quit_flag);458 459 return 0;460 }461 462 /*463 * Initialize pjsua application.464 * This will initialize all libraries, create endpoint instance, and register465 * pjsip modules.466 */467 pj_status_t pjsua_init(void)468 {469 pj_status_t status;470 471 /* Init PJLIB logging: */472 473 pj_log_set_level(pjsua.log_level);474 pj_log_set_decor(pjsua.log_decor);475 476 477 /* Init PJLIB: */478 479 status = pj_init();480 if (status != PJ_SUCCESS) {481 pjsua_perror(THIS_FILE, "pj_init() error", status);482 return status;483 }484 485 /* Init PJLIB-UTIL: */486 487 status = pjlib_util_init();488 if (status != PJ_SUCCESS) {489 pjsua_perror(THIS_FILE, "pjlib_util_init() error", status);490 return status;491 }492 493 /* Init memory pool: */494 495 /* Init caching pool. */496 pj_caching_pool_init(&pjsua.cp, &pj_pool_factory_default_policy, 0);497 498 /* Create memory pool for application. */499 pjsua.pool = pj_pool_create(&pjsua.cp.factory, "pjsua", 4000, 4000, NULL);500 501 502 /* Init PJSIP : */503 504 status = init_stack();505 if (status != PJ_SUCCESS) {506 pj_caching_pool_destroy(&pjsua.cp);507 pjsua_perror(THIS_FILE, "Stack initialization has returned error",508 status);509 return status;510 }511 512 513 874 /* Init core SIMPLE module : */ 514 875 … … 531 892 pjsua_im_init(); 532 893 533 534 /* Init media endpoint: */535 536 status = pjmedia_endpt_create(&pjsua.cp.factory,537 pjsip_endpt_get_ioqueue(pjsua.endpt), 0,538 &pjsua.med_endpt);539 if (status != PJ_SUCCESS) {540 pj_caching_pool_destroy(&pjsua.cp);541 pjsua_perror(THIS_FILE,542 "Media stack initialization has returned error",543 status);544 return status;545 }546 894 547 895 /* Done. */ 548 896 return PJ_SUCCESS; 897 898 on_error: 899 pj_caching_pool_destroy(&pjsua.cp); 900 return status; 549 901 } 550 902 … … 557 909 pjsip_uri *uri; 558 910 pjsip_sip_uri *sip_uri; 559 intacc_index;911 unsigned acc_index; 560 912 561 913 uri = rdata->msg_info.to->uri; 562 914 563 /* Just return account #0if To URI is not SIP: */915 /* Just return last account if To URI is not SIP: */ 564 916 if (!PJSIP_URI_SCHEME_IS_SIP(uri) && 565 917 !PJSIP_URI_SCHEME_IS_SIPS(uri)) 566 918 { 567 return 0;919 return pjsua.config.acc_cnt; 568 920 } 569 921 … … 572 924 573 925 /* Find account which has matching username and domain. */ 574 for (acc_index=0; acc_index < pjsua. acc_cnt; ++acc_index) {926 for (acc_index=0; acc_index < pjsua.config.acc_cnt; ++acc_index) { 575 927 576 928 pjsua_acc *acc = &pjsua.acc[acc_index]; … … 585 937 586 938 /* No matching, try match domain part only. */ 587 for (acc_index=0; acc_index < pjsua. acc_cnt; ++acc_index) {939 for (acc_index=0; acc_index < pjsua.config.acc_cnt; ++acc_index) { 588 940 589 941 pjsua_acc *acc = &pjsua.acc[acc_index]; … … 595 947 } 596 948 597 /* Still no match, just return account #0*/598 return 0;949 /* Still no match, just return last account */ 950 return pjsua.config.acc_cnt; 599 951 } 600 952 … … 611 963 } 612 964 613 614 /*615 * Init media.616 */617 static pj_status_t init_media(void)618 {619 int i;620 unsigned options;621 unsigned clock_rate;622 unsigned samples_per_frame;623 pj_str_t codec_id;624 pj_status_t status;625 626 /* Register all codecs */627 #if PJMEDIA_HAS_SPEEX_CODEC628 /* Register speex. */629 status = pjmedia_codec_speex_init(pjsua.med_endpt,630 PJMEDIA_SPEEX_NO_UWB,631 pjsua.quality, pjsua.complexity );632 if (status != PJ_SUCCESS) {633 pjsua_perror(THIS_FILE, "Error initializing Speex codec",634 status);635 return status;636 }637 638 /* Set "speex/16000/1" to have highest priority */639 codec_id = pj_str("speex/16000/1");640 pjmedia_codec_mgr_set_codec_priority(641 pjmedia_endpt_get_codec_mgr(pjsua.med_endpt),642 &codec_id,643 PJMEDIA_CODEC_PRIO_HIGHEST);644 645 #endif /* PJMEDIA_HAS_SPEEX_CODEC */646 647 #if PJMEDIA_HAS_GSM_CODEC648 /* Register GSM */649 status = pjmedia_codec_gsm_init(pjsua.med_endpt);650 if (status != PJ_SUCCESS) {651 pjsua_perror(THIS_FILE, "Error initializing GSM codec",652 status);653 return status;654 }655 #endif /* PJMEDIA_HAS_GSM_CODEC */656 657 #if PJMEDIA_HAS_G711_CODEC658 /* Register PCMA and PCMU */659 status = pjmedia_codec_g711_init(pjsua.med_endpt);660 if (status != PJ_SUCCESS) {661 pjsua_perror(THIS_FILE, "Error initializing G711 codec",662 status);663 return status;664 }665 #endif /* PJMEDIA_HAS_G711_CODEC */666 667 #if PJMEDIA_HAS_L16_CODEC668 /* Register L16 family codecs, but disable all */669 status = pjmedia_codec_l16_init(pjsua.med_endpt, 0);670 if (status != PJ_SUCCESS) {671 pjsua_perror(THIS_FILE, "Error initializing L16 codecs",672 status);673 return status;674 }675 676 /* Disable ALL L16 codecs */677 codec_id = pj_str("L16");678 pjmedia_codec_mgr_set_codec_priority(679 pjmedia_endpt_get_codec_mgr(pjsua.med_endpt),680 &codec_id,681 PJMEDIA_CODEC_PRIO_DISABLED);682 683 #endif /* PJMEDIA_HAS_L16_CODEC */684 685 686 /* Enable those codecs that user put with "--add-codec", and move687 * the priority to top688 */689 for (i=0; i<pjsua.codec_cnt; ++i) {690 pjmedia_codec_mgr_set_codec_priority(691 pjmedia_endpt_get_codec_mgr(pjsua.med_endpt),692 &pjsua.codec_arg[i],693 PJMEDIA_CODEC_PRIO_HIGHEST);694 }695 696 697 /* Init options for conference bridge. */698 options = 0;699 if (pjsua.no_mic)700 options |= PJMEDIA_CONF_NO_MIC;701 702 /* Init conference bridge. */703 clock_rate = pjsua.clock_rate ? pjsua.clock_rate : 16000;704 samples_per_frame = clock_rate * 10 / 1000;705 status = pjmedia_conf_create(pjsua.pool,706 pjsua.max_calls+PJSUA_CONF_MORE_PORTS,707 clock_rate,708 1, /* mono */709 samples_per_frame,710 16,711 options,712 &pjsua.mconf);713 if (status != PJ_SUCCESS) {714 pjsua_perror(THIS_FILE,715 "Media stack initialization has returned error",716 status);717 return status;718 }719 720 /* Add NULL port to the bridge. */721 status = pjmedia_null_port_create( pjsua.pool, clock_rate,722 1, /* mono */723 samples_per_frame, 16,724 &pjsua.null_port);725 pjmedia_conf_add_port( pjsua.mconf, pjsua.pool, pjsua.null_port,726 &pjsua.null_port->info.name, NULL );727 728 /* Create WAV file player if required: */729 730 if (pjsua.wav_file) {731 pj_str_t port_name;732 733 /* Create the file player port. */734 status = pjmedia_wav_player_port_create( pjsua.pool, pjsua.wav_file,735 0, 0, -1, NULL,736 &pjsua.file_port);737 if (status != PJ_SUCCESS) {738 pjsua_perror(THIS_FILE,739 "Error playing media file",740 status);741 return status;742 }743 744 /* Add port to conference bridge: */745 status = pjmedia_conf_add_port(pjsua.mconf, pjsua.pool,746 pjsua.file_port,747 pj_cstr(&port_name, pjsua.wav_file),748 &pjsua.wav_slot);749 if (status != PJ_SUCCESS) {750 pjsua_perror(THIS_FILE,751 "Unable to add file player to conference bridge",752 status);753 return status;754 }755 }756 757 758 return PJ_SUCCESS;759 }760 965 761 966 … … 764 969 * This will start the registration process, if registration is configured. 765 970 */ 766 pj_status_tpjsua_start(void)971 PJ_DEF(pj_status_t) pjsua_start(void) 767 972 { 768 973 int i; /* Must be signed */ 769 pjsip_transport *udp_transport;770 974 pj_status_t status = PJ_SUCCESS; 771 975 772 /*773 * Init media subsystem (codecs, conference bridge, et all).774 */775 status = init_media();776 if (status != PJ_SUCCESS)777 return status;778 779 /* Init sockets (STUN etc): */780 for (i=0; i<(int)pjsua.max_calls; ++i) {781 status = init_sockets(i==0, &pjsua.calls[i].skinfo);782 if (status == PJ_SUCCESS)783 status = pjmedia_transport_udp_attach(pjsua.med_endpt, NULL,784 &pjsua.calls[i].skinfo,785 &pjsua.calls[i].med_tp);786 if (status != PJ_SUCCESS) {787 pjsua_perror(THIS_FILE, "init_sockets() has returned error",788 status);789 --i;790 if (i >= 0)791 pj_sock_close(pjsua.sip_sock);792 while (i >= 0) {793 pjmedia_transport_udp_close(pjsua.calls[i].med_tp);794 }795 return status;796 }797 }798 976 799 977 /* Add UDP transport: */ 800 801 { 978 if (pjsua.sip_sock > 0) { 979 802 980 /* Init the published name for the transport. 803 981 * Depending whether STUN is used, this may be the STUN mapped … … 806 984 pjsip_host_port addr_name; 807 985 808 addr_name.host.ptr = pj_inet_ntoa(pjsua.sip_sock_name.sin_addr); 809 addr_name.host.slen = pj_ansi_strlen(addr_name.host.ptr); 810 addr_name.port = pj_ntohs(pjsua.sip_sock_name.sin_port); 986 addr_name.host = pjsua.config.sip_host; 987 addr_name.port = pjsua.config.sip_port; 811 988 812 989 /* Create UDP transport from previously created UDP socket: */ … … 814 991 status = pjsip_udp_transport_attach( pjsua.endpt, pjsua.sip_sock, 815 992 &addr_name, 1, 816 &udp_transport);993 NULL); 817 994 if (status != PJ_SUCCESS) { 818 995 pjsua_perror(THIS_FILE, "Unable to start UDP transport", … … 822 999 } 823 1000 824 /* Initialize Contact URI, if one is not specified: */ 825 for (i=0; i<pjsua.acc_cnt; ++i) { 826 1001 /* The last account is default account to be used when nothing match 1002 * any configured accounts. 1003 */ 1004 { 1005 char buf[80]; 1006 pj_str_t tmp; 1007 pjsua_acc_config *acc_cfg = 1008 &pjsua.config.acc_config[pjsua.config.acc_cnt]; 1009 1010 tmp.ptr = buf; 1011 tmp.slen = pj_ansi_sprintf(tmp.ptr, "<sip:%s:%d>", 1012 pjsua.config.sip_host.ptr, 1013 pjsua.config.sip_port); 1014 1015 pj_strdup_with_null( pjsua.pool, &acc_cfg->id, &tmp); 1016 acc_cfg->contact = acc_cfg->id; 1017 } 1018 1019 1020 /* Initialize accounts: */ 1021 for (i=0; i<(int)pjsua.config.acc_cnt; ++i) { 1022 1023 pjsua_acc_config *acc_cfg = &pjsua.config.acc_config[i]; 1024 pjsua_acc *acc = &pjsua.acc[i]; 827 1025 pjsip_uri *uri; 828 1026 pjsip_sip_uri *sip_uri; … … 830 1028 /* Need to parse local_uri to get the elements: */ 831 1029 832 uri = pjsip_parse_uri(pjsua.pool, pjsua.acc[i].local_uri.ptr,833 pjsua.acc[i].local_uri.slen, 0);1030 uri = pjsip_parse_uri(pjsua.pool, acc_cfg->id.ptr, 1031 acc_cfg->id.slen, 0); 834 1032 if (uri == NULL) { 835 1033 pjsua_perror(THIS_FILE, "Invalid local URI", … … 853 1051 sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(uri); 854 1052 855 pjsua.acc[i].user_part = sip_uri->user;856 pjsua.acc[i].host_part = sip_uri->host;857 858 if (pjsua.acc[i].contact_uri.slen == 0 &&859 pjsua.acc[i].local_uri.slen) 860 {1053 acc->user_part = sip_uri->user; 1054 acc->host_part = sip_uri->host; 1055 1056 /* Build Contact header */ 1057 1058 if (acc_cfg->contact.slen == 0) { 861 1059 char contact[128]; 1060 const char *addr; 1061 int port; 862 1062 int len; 1063 1064 addr = pjsua.config.sip_host.ptr; 1065 port = pjsua.config.sip_port; 863 1066 864 1067 /* The local Contact is the username@ip-addr, where … … 874 1077 /* With the user part. */ 875 1078 len = pj_ansi_snprintf(contact, sizeof(contact), 876 "<sip:%.*s@% .*s:%d>",1079 "<sip:%.*s@%s:%d>", 877 1080 (int)sip_uri->user.slen, 878 1081 sip_uri->user.ptr, 879 (int)udp_transport->local_name.host.slen, 880 udp_transport->local_name.host.ptr, 881 udp_transport->local_name.port); 1082 addr, port); 882 1083 } else { 883 1084 … … 885 1086 886 1087 len = pj_ansi_snprintf(contact, sizeof(contact), 887 "<sip:%.*s:%d>", 888 (int)udp_transport->local_name.host.slen, 889 udp_transport->local_name.host.ptr, 890 udp_transport->local_name.port); 1088 "<sip:%s:%d>", 1089 addr, port); 891 1090 } 892 1091 … … 898 1097 /* Duplicate Contact uri. */ 899 1098 900 pj_strdup2(pjsua.pool, &pjsua.acc[i].contact_uri, contact); 901 902 } 903 } 904 905 /* If outbound_proxy is specified, put it in the route_set: */ 906 907 if (pjsua.outbound_proxy.slen) { 908 909 pjsip_route_hdr *route; 910 const pj_str_t hname = { "Route", 5 }; 911 int parsed_len; 912 913 route = pjsip_parse_hdr( pjsua.pool, &hname, 914 pjsua.outbound_proxy.ptr, 915 pjsua.outbound_proxy.slen, 916 &parsed_len); 917 if (route == NULL) { 918 pjsua_perror(THIS_FILE, "Invalid outbound proxy URL", 919 PJSIP_EINVALIDURI); 920 return PJSIP_EINVALIDURI; 921 } 922 923 for (i=0; i<pjsua.acc_cnt; ++i) { 924 pj_list_push_front(&pjsua.acc[i].route_set, route); 925 } 926 } 1099 pj_strdup2(pjsua.pool, &acc_cfg->contact, contact); 1100 1101 } 1102 1103 1104 /* Build route-set for this account */ 1105 if (pjsua.config.outbound_proxy.slen) { 1106 pj_str_t hname = { "Route", 5}; 1107 pjsip_route_hdr *r; 1108 pj_str_t tmp; 1109 1110 pj_strdup_with_null(pjsua.pool, &tmp, &pjsua.config.outbound_proxy); 1111 r = pjsip_parse_hdr(pjsua.pool, &hname, tmp.ptr, tmp.slen, NULL); 1112 pj_list_push_back(&acc->route_set, r); 1113 } 1114 1115 if (acc_cfg->proxy.slen) { 1116 pj_str_t hname = { "Route", 5}; 1117 pjsip_route_hdr *r; 1118 pj_str_t tmp; 1119 1120 pj_strdup_with_null(pjsua.pool, &tmp, &acc_cfg->proxy); 1121 r = pjsip_parse_hdr(pjsua.pool, &hname, tmp.ptr, tmp.slen, NULL); 1122 pj_list_push_back(&acc->route_set, r); 1123 } 1124 } 1125 1126 927 1127 928 1128 929 1129 /* Create worker thread(s), if required: */ 930 1130 931 for (i=0; i< pjsua.thread_cnt; ++i) {1131 for (i=0; i<(int)pjsua.config.thread_cnt; ++i) { 932 1132 status = pj_thread_create( pjsua.pool, "pjsua", &pjsua_poll, 933 1133 NULL, 0, 0, &pjsua.threads[i]); … … 945 1145 946 1146 /* Create client registration session: */ 947 for (i=0; i< pjsua.acc_cnt; ++i) {1147 for (i=0; i<(int)pjsua.config.acc_cnt; ++i) { 948 1148 status = pjsua_regc_init(i); 949 1149 if (status != PJ_SUCCESS) … … 956 1156 } 957 1157 1158 1159 /* Init buddies */ 1160 for (i=0; i<(int)pjsua.config.buddy_cnt; ++i) { 1161 pjsua.buddies[i].uri = pjsua.config.buddy_uri[i]; 1162 } 1163 pjsua.buddy_cnt = pjsua.config.buddy_cnt; 958 1164 959 1165 /* Find account for outgoing preence subscription */ … … 987 1193 * Destroy pjsua. 988 1194 */ 989 pj_status_tpjsua_destroy(void)1195 PJ_DEF(pj_status_t) pjsua_destroy(void) 990 1196 { 991 1197 int i; /* Must be signed */ … … 1001 1207 1002 1208 /* Unregister, if required: */ 1003 for (i=0; i< pjsua.acc_cnt; ++i) {1209 for (i=0; i<(int)pjsua.config.acc_cnt; ++i) { 1004 1210 if (pjsua.acc[i].regc) { 1005 1211 pjsua_regc_update(i, 0); … … 1008 1214 1009 1215 /* Wait worker threads to quit: */ 1010 for (i=0; i< pjsua.thread_cnt; ++i) {1216 for (i=0; i<(int)pjsua.config.thread_cnt; ++i) { 1011 1217 1012 1218 if (pjsua.threads[i]) { … … 1030 1236 pjmedia_port_destroy(pjsua.file_port); 1031 1237 1032 /* Destroy null port. */1033 if (pjsua.null_port)1034 pjmedia_port_destroy(pjsua.null_port);1035 1036 1238 1037 1239 /* Shutdown all codecs: */ … … 1054 1256 1055 1257 /* Close transports */ 1056 for (i=0; i<pjsua.call_cnt; ++i) {1258 for (i=0; pjsua.config.start_rtp_port && i<(int)pjsua.config.max_calls; ++i) { 1057 1259 pjmedia_transport_udp_close(pjsua.calls[i].med_tp); 1058 1260 }
Note: See TracChangeset
for help on using the changeset viewer.