Changeset 1098 for pjproject/trunk
- Timestamp:
- Mar 23, 2007 4:34:20 PM (18 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia.h
r974 r1098 55 55 #include <pjmedia/tonegen.h> 56 56 #include <pjmedia/transport.h> 57 #include <pjmedia/transport_ice.h> 57 58 #include <pjmedia/transport_udp.h> 58 59 #include <pjmedia/wav_playlist.h> -
pjproject/trunk/pjmedia/include/pjmedia/transport.h
r1097 r1098 179 179 struct pjmedia_transport_op 180 180 { 181 /** 182 * Get media socket info from the specified transport. 183 * 184 * Application should call #pjmedia_transport_get_info() instead 185 */ 181 186 pj_status_t (*get_info)(pjmedia_transport *tp, 182 187 pjmedia_sock_info *info); … … 255 260 256 261 262 /** 263 * Media transport type. 264 */ 265 typedef enum pjmedia_transport_type 266 { 267 /** Media transport using standard UDP */ 268 PJMEDIA_TRANSPORT_TYPE_UDP, 269 270 /** Media transport using ICE */ 271 PJMEDIA_TRANSPORT_TYPE_ICE 272 273 } pjmedia_transport_type; 274 275 257 276 /** 258 277 * This structure declares stream transport. A stream transport is called … … 263 282 { 264 283 /** Transport name (for logging purpose). */ 265 char name[PJ_MAX_OBJ_NAME]; 284 char name[PJ_MAX_OBJ_NAME]; 285 286 /** Transport type. */ 287 pjmedia_transport_type type; 266 288 267 289 /** Transport's "virtual" function table. */ 268 pjmedia_transport_op *op;290 pjmedia_transport_op *op; 269 291 }; 270 292 271 293 294 /** 295 * Get media socket info from the specified transport. The socket info 296 * contains information about the local address of this transport, and 297 * would be needed for example to fill in the "c=" and "m=" line of local 298 * SDP. 299 * 300 * @param tp The transport. 301 * @param info Media socket info to be initialized. 302 * 303 * @return PJ_SUCCESS on success. 304 */ 272 305 PJ_INLINE(pj_status_t) pjmedia_transport_get_info(pjmedia_transport *tp, 273 306 pjmedia_sock_info *info) -
pjproject/trunk/pjmedia/include/pjmedia/transport_ice.h
r1097 r1098 42 42 PJ_DECL(pj_status_t) pjmedia_ice_create(pjmedia_endpt *endpt, 43 43 const char *name, 44 unsigned comp_cnt, 44 45 pj_stun_config *stun_cfg, 45 pj_dns_resolver *resolver,46 pj_bool_t enable_relay,47 const pj_str_t *stun_name,48 46 pjmedia_transport **p_tp); 49 47 PJ_DECL(pj_status_t) pjmedia_ice_destroy(pjmedia_transport *tp); 48 49 PJ_DECL(pj_ice_st*) pjmedia_ice_get_ice_st(pjmedia_transport *tp); 50 50 51 51 … … 54 54 const pj_str_t *local_ufrag, 55 55 const pj_str_t *local_passwd); 56 PJ_DECL(pj_status_t) pjmedia_ice_ build_sdp(pjmedia_transport *tp,57 pj_pool_t *pool,58 pjmedia_sdp_session *sdp);56 PJ_DECL(pj_status_t) pjmedia_ice_modify_sdp(pjmedia_transport *tp, 57 pj_pool_t *pool, 58 pjmedia_sdp_session *sdp); 59 59 PJ_DECL(pj_status_t) pjmedia_ice_start_ice(pjmedia_transport *tp, 60 60 pj_pool_t *pool, -
pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c
r1097 r1098 26 26 pj_ice_st *ice_st; 27 27 28 void * user_data;28 void *stream; 29 29 void (*rtp_cb)(void*, 30 30 const void*, … … 42 42 pjmedia_sock_info *info); 43 43 static pj_status_t tp_attach( pjmedia_transport *tp, 44 void * user_data,44 void *stream, 45 45 const pj_sockaddr_t *rem_addr, 46 46 const pj_sockaddr_t *rem_rtcp, … … 93 93 PJ_DEF(pj_status_t) pjmedia_ice_create(pjmedia_endpt *endpt, 94 94 const char *name, 95 unsigned comp_cnt, 95 96 pj_stun_config *stun_cfg, 96 pj_dns_resolver *resolver, 97 pj_bool_t enable_relay, 98 const pj_str_t *stun_name, 99 pjmedia_transport **p_tp) 97 pjmedia_transport **p_tp) 100 98 { 101 99 pj_ice_st *ice_st; 102 100 pj_ice_st_cb ice_st_cb; 103 101 struct transport_ice *tp_ice; 102 unsigned i; 104 103 pj_status_t status; 105 104 … … 118 117 return status; 119 118 120 /* Add component 1 (RTP) */ 121 status = pj_ice_st_add_comp(ice_st, 1); 122 if (status != PJ_SUCCESS) 123 goto on_error; 124 125 /* Add host candidates. */ 126 status = pj_ice_st_add_all_host_interfaces(ice_st, 1, 0, PJ_FALSE, NULL); 127 if (status != PJ_SUCCESS) 128 goto on_error; 129 130 /* Configure STUN server for ICE */ 131 if (stun_name) { 132 status = pj_ice_st_set_stun(ice_st, resolver, enable_relay, stun_name); 119 /* Add components */ 120 for (i=0; i<comp_cnt; ++i) { 121 status = pj_ice_st_add_comp(ice_st, i+1); 133 122 if (status != PJ_SUCCESS) 134 123 goto on_error; 135 136 /* Add STUN candidates */137 status = pj_ice_st_add_stun_interface(ice_st, 1, 0, PJ_FALSE, NULL);138 124 } 139 125 … … 143 129 pj_ansi_strcpy(tp_ice->base.name, ice_st->obj_name); 144 130 tp_ice->base.op = &tp_ice_op; 131 tp_ice->base.type = PJMEDIA_TRANSPORT_TYPE_ICE; 145 132 146 133 ice_st->user_data = (void*)tp_ice; … … 158 145 159 146 160 PJ_DEF(pj_status_t) pjmedia_ice_ close(pjmedia_transport *tp)147 PJ_DEF(pj_status_t) pjmedia_ice_destroy(pjmedia_transport *tp) 161 148 { 162 149 struct transport_ice *tp_ice = (struct transport_ice*)tp; … … 164 151 if (tp_ice->ice_st) { 165 152 pj_ice_st_destroy(tp_ice->ice_st); 166 tp_ice->ice_st = NULL; 153 //Must not touch tp_ice after ice_st is destroyed! 154 //(it has the pool) 155 //tp_ice->ice_st = NULL; 167 156 } 168 157 169 158 return PJ_SUCCESS; 159 } 160 161 162 PJ_DECL(pj_ice_st*) pjmedia_ice_get_ice_st(pjmedia_transport *tp) 163 { 164 struct transport_ice *tp_ice = (struct transport_ice*)tp; 165 return tp_ice->ice_st; 170 166 } 171 167 … … 181 177 182 178 183 PJ_DEF(pj_status_t) pjmedia_ice_ build_sdp(pjmedia_transport *tp,184 pj_pool_t *pool,185 pjmedia_sdp_session *sdp)179 PJ_DEF(pj_status_t) pjmedia_ice_modify_sdp(pjmedia_transport *tp, 180 pj_pool_t *pool, 181 pjmedia_sdp_session *sdp) 186 182 { 187 183 struct transport_ice *tp_ice = (struct transport_ice*)tp; … … 203 199 sdp->attr[sdp->attr_count++] = attr; 204 200 205 /* Add all candidates */201 /* Add all candidates (to media level) */ 206 202 cand_cnt = pj_ice_get_cand_cnt(tp_ice->ice_st->ice); 207 203 for (i=0; i<cand_cnt; ++i) { … … 256 252 value = pj_str(buffer); 257 253 attr = pjmedia_sdp_attr_create(pool, "candidate", &value); 258 sdp-> attr[sdp->attr_count++] = attr;254 sdp->media[0]->attr[sdp->media[0]->attr_count++] = attr; 259 255 } 260 256 … … 378 374 /* Get all candidates */ 379 375 cand_cnt = 0; 380 for (i=0; i<rem_sdp-> attr_count; ++i) {376 for (i=0; i<rem_sdp->media[0]->attr_count; ++i) { 381 377 pjmedia_sdp_attr *attr; 382 378 383 attr = rem_sdp-> attr[i];379 attr = rem_sdp->media[0]->attr[i]; 384 380 if (pj_strcmp2(&attr->name, "candidate")!=0) 385 381 continue; … … 442 438 443 439 static pj_status_t tp_attach( pjmedia_transport *tp, 444 void * user_data,440 void *stream, 445 441 const pj_sockaddr_t *rem_addr, 446 442 const pj_sockaddr_t *rem_rtcp, … … 455 451 struct transport_ice *tp_ice = (struct transport_ice*)tp; 456 452 457 tp_ice-> user_data = user_data;453 tp_ice->stream = stream; 458 454 tp_ice->rtp_cb = rtp_cb; 459 455 tp_ice->rtcp_cb = rtcp_cb; … … 474 470 tp_ice->rtp_cb = NULL; 475 471 tp_ice->rtcp_cb = NULL; 476 tp_ice-> user_data= NULL;472 tp_ice->stream = NULL; 477 473 478 474 PJ_UNUSED_ARG(strm); … … 515 511 516 512 if (comp_id==1 && tp_ice->rtp_cb) 517 (*tp_ice->rtp_cb)(tp_ice-> user_data, pkt, size);513 (*tp_ice->rtp_cb)(tp_ice->stream, pkt, size); 518 514 else if (comp_id==2 && tp_ice->rtcp_cb) 519 (*tp_ice->rtcp_cb)(tp_ice-> user_data, pkt, size);515 (*tp_ice->rtcp_cb)(tp_ice->stream, pkt, size); 520 516 521 517 PJ_UNUSED_ARG(cand_id); -
pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c
r1097 r1098 240 240 pj_ansi_strcpy(tp->base.name, name); 241 241 tp->base.op = &transport_udp_op; 242 tp->base.type = PJMEDIA_TRANSPORT_TYPE_UDP; 242 243 243 244 /* Copy socket infos */ -
pjproject/trunk/pjnath/include/pjnath/ice_stream_transport.h
r1096 r1098 72 72 pj_ice_st *ice_st; 73 73 pj_ice_cand_type type; 74 pj_status_t status; 74 75 unsigned comp_id; 75 76 int cand_id; … … 151 152 pj_bool_t notify, 152 153 void *notify_data); 153 154 PJ_DECL(pj_status_t) pj_ice_st_get_interfaces_status(pj_ice_st *ice_st); 154 155 155 156 PJ_DECL(pj_status_t) pj_ice_st_init_ice(pj_ice_st *ice_st, -
pjproject/trunk/pjnath/src/pjnath/ice.c
r1097 r1098 889 889 { 890 890 if (!ice->is_complete) { 891 char errmsg[PJ_ERR_MSG_SIZE]; 891 892 892 893 ice->is_complete = PJ_TRUE; … … 894 895 895 896 /* Log message */ 896 LOG((ice->obj_name, "ICE process complete")); 897 LOG((ice->obj_name, "ICE process complete, status=%s", 898 pj_strerror(status, errmsg, sizeof(errmsg)).ptr)); 899 897 900 dump_checklist("Dumping checklist", ice, &ice->clist); 898 901 dump_valid_list("Dumping valid list", ice); … … 1137 1140 dump_checklist("Checklist created:", ice, clist); 1138 1141 1139 pj_mutex_ lock(ice->mutex);1142 pj_mutex_unlock(ice->mutex); 1140 1143 1141 1144 return PJ_SUCCESS; -
pjproject/trunk/pjnath/src/pjnath/ice_stream_transport.c
r1096 r1098 152 152 } 153 153 154 155 154 /* 156 155 * This is callback called by ioqueue on incoming packet … … 192 191 } 193 192 194 195 193 /* 196 194 * Destroy an interface … … 207 205 } 208 206 } 209 210 207 211 208 /* … … 242 239 } 243 240 244 245 241 static void destroy_ice_st(pj_ice_st *ice_st, pj_status_t reason) 246 242 { … … 274 270 } 275 271 276 277 272 /* 278 273 * Destroy ICE stream transport. … … 283 278 return PJ_SUCCESS; 284 279 } 285 286 280 287 281 /* … … 301 295 } 302 296 303 304 297 /* 305 298 * Set STUN server address. … … 320 313 } 321 314 322 323 315 /* 324 316 * Add new component. … … 350 342 return PJ_SUCCESS; 351 343 } 352 353 344 354 345 /* Add interface */ … … 406 397 add_interface(ice_st, is, p_itf_id, notify, notify_data); 407 398 408 return PJ_SUCCESS; 409 } 410 399 /* Set interface status to SUCCESS */ 400 is->status = PJ_SUCCESS; 401 402 return PJ_SUCCESS; 403 } 411 404 412 405 /* … … 434 427 NULL, notify, notify_data); 435 428 } 436 437 429 438 430 /* … … 454 446 } 455 447 456 457 448 /* 458 449 * Add TURN mapping interface. … … 473 464 } 474 465 466 PJ_DEF(pj_status_t) pj_ice_st_get_interfaces_status(pj_ice_st *ice_st) 467 { 468 unsigned i; 469 pj_status_t worst = PJ_SUCCESS; 470 471 for (i=0; i<ice_st->itf_cnt; ++i) { 472 pj_ice_st_interface *itf = ice_st->itfs[i]; 473 474 if (itf->status == PJ_SUCCESS) { 475 /* okay */ 476 } else if (itf->status == PJ_EPENDING && worst==PJ_SUCCESS) { 477 worst = itf->status; 478 } else { 479 worst = itf->status; 480 } 481 } 482 483 return worst; 484 } 475 485 476 486 /* … … 538 548 } 539 549 540 541 550 /* 542 551 * Enum candidates … … 568 577 return PJ_SUCCESS; 569 578 } 570 571 579 572 580 /* … … 589 597 } 590 598 591 592 599 /* 593 600 * Stop ICE! … … 602 609 return PJ_SUCCESS; 603 610 } 604 605 611 606 612 /* … … 618 624 } 619 625 620 621 622 626 /* 623 627 * Callback called by ICE session when ICE processing is complete, either … … 631 635 } 632 636 } 633 634 637 635 638 /* … … 668 671 } 669 672 670 671 673 /* 672 674 * Callback called by ICE session when it receives application data. -
pjproject/trunk/pjsip-apps/build/pjsua.dsp
r853 r1098 43 43 # PROP Target_Dir "" 44 44 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 45 # ADD CPP /nologo /MD /W4 /GX /Zi /O2 /I "../../pjsip/include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../../pjmedia/include" / D "NDEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /FD /c45 # ADD CPP /nologo /MD /W4 /GX /Zi /O2 /I "../../pjsip/include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../../pjmedia/include" /I "../../pjnath/include" /D "NDEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /FD /c 46 46 # SUBTRACT CPP /YX 47 47 # ADD BASE RSC /l 0x409 /d "NDEBUG" … … 69 69 # PROP Target_Dir "" 70 70 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 71 # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../../pjsip/include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../../pjmedia/include" / D "_DEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c71 # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../../pjsip/include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../../pjmedia/include" /I "../../pjnath/include" /D "_DEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c 72 72 # SUBTRACT CPP /YX 73 73 # ADD BASE RSC /l 0x409 /d "_DEBUG" -
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
r1044 r1098 145 145 puts (" --outbound=url Set the URL of global outbound proxy server"); 146 146 puts (" May be specified multiple times"); 147 puts (" --use-stun1=FORMAT where FORMAT=host[:port]"); 148 puts (" --use-stun2=FORMAT Resolve local IP with the specified STUN servers"); 147 puts (" --stun-srv=name Set STUN server host or domain"); 149 148 puts (""); 150 149 puts ("TLS Options:"); … … 160 159 puts (""); 161 160 puts ("Media Options:"); 161 puts (" --use-ice Enable ICE (default:no)"); 162 162 puts (" --add-codec=name Manually add codec (default is to enable all)"); 163 163 puts (" --clock-rate=N Override sound device clock rate"); … … 326 326 OPT_REGISTRAR, OPT_REG_TIMEOUT, OPT_PUBLISH, OPT_ID, OPT_CONTACT, 327 327 OPT_REALM, OPT_USERNAME, OPT_PASSWORD, 328 OPT_NAMESERVER, OPT_ USE_STUN1, OPT_USE_STUN2,328 OPT_NAMESERVER, OPT_STUN_SRV, 329 329 OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE, 330 330 OPT_AUTO_ANSWER, OPT_AUTO_HANGUP, OPT_AUTO_PLAY, OPT_AUTO_LOOP, 331 OPT_AUTO_CONF, OPT_CLOCK_RATE, 331 OPT_AUTO_CONF, OPT_CLOCK_RATE, OPT_USE_ICE, 332 332 OPT_PLAY_FILE, OPT_PLAY_TONE, OPT_RTP_PORT, OPT_ADD_CODEC, 333 333 OPT_ILBC_MODE, OPT_REC_FILE, OPT_AUTO_REC, … … 367 367 { "password", 1, 0, OPT_PASSWORD}, 368 368 { "nameserver", 1, 0, OPT_NAMESERVER}, 369 { "use-stun1", 1, 0, OPT_USE_STUN1}, 370 { "use-stun2", 1, 0, OPT_USE_STUN2}, 369 { "stun-srv", 1, 0, OPT_STUN_SRV}, 371 370 { "add-buddy", 1, 0, OPT_ADD_BUDDY}, 372 371 { "offer-x-ms-msg",0,0,OPT_OFFER_X_MS_MSG}, … … 382 381 { "rec-file", 1, 0, OPT_REC_FILE}, 383 382 { "rtp-port", 1, 0, OPT_RTP_PORT}, 383 { "use-ice", 0, 0, OPT_USE_ICE}, 384 384 { "add-codec", 1, 0, OPT_ADD_CODEC}, 385 385 { "complexity", 1, 0, OPT_COMPLEXITY}, … … 442 442 pj_optind = 0; 443 443 while((c=pj_getopt_long(argc,argv, "", long_options,&option_index))!=-1) { 444 char *p;445 444 pj_str_t tmp; 446 445 long lval; … … 633 632 break; 634 633 635 case OPT_USE_STUN1: /* STUN server 1 */ 636 p = pj_ansi_strchr(pj_optarg, ':'); 637 if (p) { 638 *p = '\0'; 639 cfg->udp_cfg.stun_config.stun_srv1 = pj_str(pj_optarg); 640 cfg->udp_cfg.stun_config.stun_port1 = pj_strtoul(pj_cstr(&tmp, p+1)); 641 if (cfg->udp_cfg.stun_config.stun_port1 < 1 || cfg->udp_cfg.stun_config.stun_port1 > 65535) { 642 PJ_LOG(1,(THIS_FILE, 643 "Error: expecting port number with " 644 "option --use-stun1")); 645 return PJ_EINVAL; 646 } 647 } else { 648 cfg->udp_cfg.stun_config.stun_port1 = 3478; 649 cfg->udp_cfg.stun_config.stun_srv1 = pj_str(pj_optarg); 650 } 651 cfg->udp_cfg.use_stun = PJ_TRUE; 652 break; 653 654 case OPT_USE_STUN2: /* STUN server 2 */ 655 p = pj_ansi_strchr(pj_optarg, ':'); 656 if (p) { 657 *p = '\0'; 658 cfg->udp_cfg.stun_config.stun_srv2 = pj_str(pj_optarg); 659 cfg->udp_cfg.stun_config.stun_port2 = pj_strtoul(pj_cstr(&tmp,p+1)); 660 if (cfg->udp_cfg.stun_config.stun_port2 < 1 || cfg->udp_cfg.stun_config.stun_port2 > 65535) { 661 PJ_LOG(1,(THIS_FILE, 662 "Error: expecting port number with " 663 "option --use-stun2")); 664 return PJ_EINVAL; 665 } 666 } else { 667 cfg->udp_cfg.stun_config.stun_port2 = 3478; 668 cfg->udp_cfg.stun_config.stun_srv2 = pj_str(pj_optarg); 669 } 634 case OPT_STUN_SRV: /* STUN server */ 635 cfg->cfg.stun_srv = pj_str(pj_optarg); 670 636 break; 671 637 … … 727 693 case OPT_REC_FILE: 728 694 cfg->rec_file = pj_str(pj_optarg); 695 break; 696 697 case OPT_USE_ICE: 698 cfg->media_cfg.enable_ice = PJ_TRUE; 729 699 break; 730 700 … … 1114 1084 1115 1085 /* STUN */ 1116 if (config->udp_cfg.stun_config.stun_port1) { 1117 pj_ansi_sprintf(line, "--use-stun1 %.*s:%d\n", 1118 (int)config->udp_cfg.stun_config.stun_srv1.slen, 1119 config->udp_cfg.stun_config.stun_srv1.ptr, 1120 config->udp_cfg.stun_config.stun_port1); 1086 if (config->cfg.stun_srv.slen) { 1087 pj_ansi_sprintf(line, "--stun-srv %.*s\n", 1088 (int)config->cfg.stun_srv.slen, 1089 config->cfg.stun_srv.ptr); 1121 1090 pj_strcat2(&cfg, line); 1122 1091 } 1123 1092 1124 if (config->udp_cfg.stun_config.stun_port2) {1125 pj_ansi_sprintf(line, "--use-stun2 %.*s:%d\n",1126 (int)config->udp_cfg.stun_config.stun_srv2.slen,1127 config->udp_cfg.stun_config.stun_srv2.ptr,1128 config->udp_cfg.stun_config.stun_port2);1129 pj_strcat2(&cfg, line);1130 }1131 1093 1132 1094 /* TLS */ … … 1175 1137 1176 1138 /* Media */ 1139 if (config->media_cfg.enable_ice) 1140 pj_strcat2(&cfg, "--use-ice\n"); 1177 1141 if (config->null_audio) 1178 1142 pj_strcat2(&cfg, "--null-audio\n"); … … 2963 2927 return status; 2964 2928 2965 /* Copy udp_cfg STUN config to rtp_cfg */2966 app_config.rtp_cfg.use_stun = app_config.udp_cfg.use_stun;2967 app_config.rtp_cfg.stun_config = app_config.udp_cfg.stun_config;2968 2969 2970 2929 /* Initialize application callbacks */ 2971 2930 app_config.cfg.cb.on_call_state = &on_call_state; -
pjproject/trunk/pjsip/build/pjsua_lib.dsp
r853 r1098 42 42 # PROP Target_Dir "" 43 43 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c 44 # ADD CPP /nologo /MD /W4 /GX /Zi /O2 /I "../include" /I "../../pjmedia/include" /I "../../pjlib-util/include" /I "../../pjlib/include" / D "NDEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_MBCS" /D "_LIB" /FR /FD /c44 # ADD CPP /nologo /MD /W4 /GX /Zi /O2 /I "../include" /I "../../pjmedia/include" /I "../../pjlib-util/include" /I "../../pjlib/include" /I "../../pjnath/include" /D "NDEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_MBCS" /D "_LIB" /FR /FD /c 45 45 # SUBTRACT CPP /YX 46 46 # ADD BASE RSC /l 0x409 /d "NDEBUG" … … 66 66 # PROP Target_Dir "" 67 67 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c 68 # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjmedia/include" /I "../../pjlib-util/include" /I "../../pjlib/include" / D "_DEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_MBCS" /D "_LIB" /FR /FD /GZ /c68 # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjmedia/include" /I "../../pjlib-util/include" /I "../../pjlib/include" /I "../../pjnath/include" /D "_DEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_MBCS" /D "_LIB" /FR /FD /GZ /c 69 69 # SUBTRACT CPP /YX 70 70 # ADD BASE RSC /l 0x409 /d "_DEBUG" -
pjproject/trunk/pjsip/include/pjsip/sip_endpoint.h
r974 r1098 157 157 pj_timer_entry *entry ); 158 158 159 /** 160 * Get the timer heap instance of the SIP endpoint. 161 * 162 * @param endpt The endpoint. 163 * 164 * @return The timer heap instance. 165 */ 166 PJ_DECL(pj_timer_heap_t*) pjsip_endpt_get_timer_heap(pjsip_endpoint *endpt); 167 159 168 160 169 /** -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r974 r1098 903 903 pj_str_t outbound_proxy[4]; 904 904 905 /** 906 * Specify STUN server. This server will be first resolved with DNS SRV 907 * to get the actual server address. If DNS SRV resolution failed, or 908 * when nameserver is not configured, the server will be resolved using 909 * DNS A resolution (i.e. gethostbyname()). 910 */ 911 pj_str_t stun_srv; 912 905 913 /** 906 914 * Number of credentials in the credential array. … … 1002 1010 1003 1011 pj_strdup_with_null(pool, &dst->user_agent, &src->user_agent); 1012 pj_strdup_with_null(pool, &dst->stun_srv, &src->stun_srv); 1004 1013 } 1005 1014 … … 1335 1344 1336 1345 /** 1337 * This structure describes STUN configuration for SIP and media transport,1338 * and is embedded inside pjsua_transport_config structure.1339 */1340 typedef struct pjsua_stun_config1341 {1342 /**1343 * The first STUN server IP address or hostname.1344 */1345 pj_str_t stun_srv1;1346 1347 /**1348 * Port number of the first STUN server.1349 * If zero, default STUN port will be used.1350 */1351 unsigned stun_port1;1352 1353 /**1354 * Optional second STUN server IP address or hostname, for which the1355 * result of the mapping request will be compared to. If the value1356 * is empty, only one STUN server will be used.1357 */1358 pj_str_t stun_srv2;1359 1360 /**1361 * Port number of the second STUN server.1362 * If zero, default STUN port will be used.1363 */1364 unsigned stun_port2;1365 1366 } pjsua_stun_config;1367 1368 1369 1370 /**1371 * Call this function to initialize STUN config with default values.1372 * STUN config is normally embedded inside pjsua_transport_config, so1373 * normally there is no need to call this function and rather just1374 * call pjsua_transport_config_default() instead.1375 *1376 * @param cfg The STUN config to be initialized.1377 *1378 * \par Python:1379 * The corresponding Python function creates and initialize the config:1380 * \code1381 stun_cfg = py_pjsua.stun_config_default()1382 * \endcode1383 */1384 PJ_INLINE(void) pjsua_stun_config_default(pjsua_stun_config *cfg)1385 {1386 pj_bzero(cfg, sizeof(*cfg));1387 }1388 1389 1390 /**1391 1346 * Transport configuration for creating transports for both SIP 1392 1347 * and media. Before setting some values to this structure, application … … 1436 1391 1437 1392 /** 1438 * Flag to indicate whether STUN should be used.1439 */1440 pj_bool_t use_stun;1441 1442 /**1443 * STUN configuration, must be specified when STUN is used.1444 */1445 pjsua_stun_config stun_config;1446 1447 /**1448 1393 * This specifies TLS settings for TLS transport. It is only be used 1449 1394 * when this transport config is being used to create a SIP TLS … … 1469 1414 { 1470 1415 pj_bzero(cfg, sizeof(*cfg)); 1471 pjsua_stun_config_default(&cfg->stun_config);1472 1416 pjsip_tls_setting_default(&cfg->tls_setting); 1473 }1474 1475 1476 /**1477 * This is a utility function to normalize STUN config. It's only1478 * used internally by the library.1479 *1480 * @param cfg The STUN config to be initialized.1481 *1482 * \par Python:1483 * \code1484 py_pjsua.normalize_stun_config(cfg)1485 * \code1486 */1487 PJ_INLINE(void) pjsua_normalize_stun_config( pjsua_stun_config *cfg )1488 {1489 if (cfg->stun_srv1.slen) {1490 1491 if (cfg->stun_port1 == 0)1492 cfg->stun_port1 = 3478;1493 1494 if (cfg->stun_srv2.slen == 0) {1495 cfg->stun_srv2 = cfg->stun_srv1;1496 cfg->stun_port2 = cfg->stun_port1;1497 } else {1498 if (cfg->stun_port2 == 0)1499 cfg->stun_port2 = 3478;1500 }1501 1502 } else {1503 cfg->stun_port1 = 0;1504 cfg->stun_srv2.slen = 0;1505 cfg->stun_port2 = 0;1506 }1507 1417 } 1508 1418 … … 1523 1433 const pjsua_transport_config *src) 1524 1434 { 1435 PJ_UNUSED_ARG(pool); 1525 1436 pj_memcpy(dst, src, sizeof(*src)); 1526 1527 if (src->stun_config.stun_srv1.slen) {1528 pj_strdup_with_null(pool, &dst->stun_config.stun_srv1,1529 &src->stun_config.stun_srv1);1530 }1531 1532 if (src->stun_config.stun_srv2.slen) {1533 pj_strdup_with_null(pool, &dst->stun_config.stun_srv2,1534 &src->stun_config.stun_srv2);1535 }1536 1537 pjsua_normalize_stun_config(&dst->stun_config);1538 1437 } 1539 1438 … … 3531 3430 int jb_max; 3532 3431 3432 /** 3433 * Enable ICE 3434 */ 3435 pj_bool_t enable_ice; 3436 3437 /** 3438 * Enable ICE media relay. 3439 */ 3440 pj_bool_t enable_relay; 3533 3441 }; 3534 3442 -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
r998 r1098 187 187 pj_thread_t *thread[4]; /**< Array of threads. */ 188 188 189 /* STUN and resolver */ 190 pj_stun_config stun_cfg; /**< Global STUN settings. */ 191 pj_sockaddr stun_srv; /**< Resolved STUN server address */ 192 pj_status_t stun_status; /**< STUN server status. */ 193 pj_dns_resolver *resolver; /**< DNS resolver. */ 194 189 195 /* Account: */ 190 196 unsigned acc_cnt; /**< Number of accounts. */ … … 271 277 272 278 279 /** 280 * Resolve STUN server. 281 */ 282 pj_status_t pjsua_resolve_stun_server(pj_bool_t wait); 273 283 274 284 /** … … 276 286 */ 277 287 pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata); 288 289 /* 290 * Media channel. 291 */ 292 pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, 293 pjsip_role_e role); 294 pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, 295 pj_pool_t *pool, 296 pjmedia_sdp_session **p_sdp); 297 pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, 298 pjmedia_sdp_session *local_sdp, 299 pjmedia_sdp_session *remote_sdp); 300 pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id); 301 278 302 279 303 /** -
pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c
r1017 r1098 759 759 760 760 /* 761 * Get the timer heap instance of the SIP endpoint. 762 */ 763 PJ_DEF(pj_timer_heap_t*) pjsip_endpt_get_timer_heap(pjsip_endpoint *endpt) 764 { 765 return endpt->timer_heap; 766 } 767 768 /* 761 769 * This is the callback that is called by the transport manager when it 762 770 * receives a message from the network. -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r974 r1098 61 61 62 62 63 /* Destroy the call's media */64 static pj_status_t call_destroy_media(int call_id);65 63 66 64 /* Create inactive SDP for call hold. */ … … 303 301 } 304 302 305 /* Get media capability from media endpoint: */ 306 307 status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt, dlg->pool, 1, 308 &call->skinfo, &offer); 303 /* Init media channel */ 304 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC); 305 if (status != PJ_SUCCESS) { 306 pjsua_perror(THIS_FILE, "Error initializing media channel", status); 307 goto on_error; 308 } 309 310 /* Create SDP offer */ 311 status = pjsua_media_channel_create_sdp(call->index, dlg->pool, &offer); 309 312 if (status != PJ_SUCCESS) { 310 313 pjsua_perror(THIS_FILE, "pjmedia unable to create SDP", status); … … 404 407 if (call_id != -1) { 405 408 reset_call(call_id); 409 pjsua_media_channel_deinit(call_id); 406 410 } 407 411 … … 527 531 528 532 529 /* Get media capability from media endpoint: */ 530 status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt, 531 rdata->tp_info.pool, 1, 532 &call->skinfo, &answer ); 533 /* Init media channel */ 534 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS); 533 535 if (status != PJ_SUCCESS) { 534 536 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, … … 539 541 540 542 543 /* Get media capability from media endpoint: */ 544 status = pjsua_media_channel_create_sdp(call->index, rdata->tp_info.pool, &answer); 545 if (status != PJ_SUCCESS) { 546 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, 547 NULL, NULL); 548 pjsua_media_channel_deinit(call->index); 549 PJSUA_UNLOCK(); 550 return PJ_TRUE; 551 } 552 553 541 554 /* Verify that we can handle the request. */ 542 555 status = pjsip_inv_verify_request(rdata, &options, answer, NULL, … … 562 575 } 563 576 577 pjsua_media_channel_deinit(call->index); 564 578 PJSUA_UNLOCK(); 565 579 return PJ_TRUE; … … 581 595 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, 582 596 NULL, NULL); 597 pjsua_media_channel_deinit(call->index); 583 598 PJSUA_UNLOCK(); 584 599 return PJ_TRUE; … … 591 606 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, 592 607 NULL, NULL); 608 pjsua_media_channel_deinit(call->index); 593 609 PJSUA_UNLOCK(); 594 610 return PJ_TRUE; … … 619 635 pjsip_dlg_terminate(dlg); 620 636 */ 637 pjsua_media_channel_deinit(call->index); 621 638 PJSUA_UNLOCK(); 622 639 return PJ_TRUE; … … 650 667 pjsip_dlg_respond(dlg, rdata, 500, NULL, NULL, NULL); 651 668 pjsip_inv_terminate(inv, 500, PJ_FALSE); 669 pjsua_media_channel_deinit(call->index); 652 670 PJSUA_UNLOCK(); 653 671 return PJ_TRUE; … … 655 673 } else { 656 674 status = pjsip_inv_send_msg(inv, response); 657 if (status != PJ_SUCCESS) 675 if (status != PJ_SUCCESS) { 658 676 pjsua_perror(THIS_FILE, "Unable to send 100 response", status); 677 } 659 678 } 660 679 … … 1192 1211 PJ_UNUSED_ARG(unhold); 1193 1212 PJ_TODO(create_active_inactive_sdp_based_on_unhold_arg); 1194 status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt, call->inv->pool, 1195 1, &call->skinfo, &sdp); 1213 status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, &sdp); 1196 1214 if (status != PJ_SUCCESS) { 1197 1215 pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint", … … 1886 1904 1887 1905 /* 1888 * Destroy the call's media1889 */1890 static pj_status_t call_destroy_media(int call_id)1891 {1892 pjsua_call *call = &pjsua_var.calls[call_id];1893 1894 if (call->conf_slot != PJSUA_INVALID_ID) {1895 pjmedia_conf_remove_port(pjsua_var.mconf, call->conf_slot);1896 call->conf_slot = PJSUA_INVALID_ID;1897 }1898 1899 if (call->session) {1900 /* Destroy session (this will also close RTP/RTCP sockets). */1901 pjmedia_session_destroy(call->session);1902 call->session = NULL;1903 1904 PJ_LOG(4,(THIS_FILE, "Media session for call %d is destroyed",1905 call_id));1906 1907 }1908 1909 call->media_st = PJSUA_CALL_MEDIA_NONE;1910 1911 return PJ_SUCCESS;1912 }1913 1914 1915 /*1916 1906 * This callback receives notification from invite session when the 1917 1907 * session state has changed. … … 2035 2025 2036 2026 if (call) 2037 call_destroy_media(call->index);2027 pjsua_media_channel_deinit(call->index); 2038 2028 2039 2029 /* Free call */ … … 2078 2068 2079 2069 /* 2080 * DTMF callback from the stream.2081 */2082 static void dtmf_callback(pjmedia_stream *strm, void *user_data,2083 int digit)2084 {2085 PJ_UNUSED_ARG(strm);2086 2087 if (pjsua_var.ua_cfg.cb.on_dtmf_digit) {2088 pjsua_call_id call_id;2089 2090 call_id = (pjsua_call_id)user_data;2091 pjsua_var.ua_cfg.cb.on_dtmf_digit(call_id, digit);2092 }2093 }2094 2095 /*2096 2070 * Callback to be called when SDP offer/answer negotiation has just completed 2097 2071 * in the session. This function will start/update media if negotiation … … 2101 2075 pj_status_t status) 2102 2076 { 2103 int prev_media_st = 0;2104 2077 pjsua_call *call; 2105 pjmedia_session_info sess_info; 2106 const pjmedia_sdp_session *local_sdp; 2107 const pjmedia_sdp_session *remote_sdp; 2108 pjmedia_port *media_port; 2109 pj_str_t port_name; 2110 char tmp[PJSIP_MAX_URL_SIZE]; 2078 pjmedia_sdp_session *local_sdp; 2079 pjmedia_sdp_session *remote_sdp; 2111 2080 2112 2081 PJSUA_LOCK(); … … 2119 2088 2120 2089 /* Stop/destroy media, if any */ 2121 call_destroy_media(call->index);2090 pjsua_media_channel_deinit(call->index); 2122 2091 2123 2092 /* Disconnect call if we're not in the middle of initializing an … … 2134 2103 } 2135 2104 2136 /* Destroy existing media session, if any. */2137 2138 if (call) {2139 prev_media_st = call->media_st;2140 call_destroy_media(call->index);2141 }2142 2105 2143 2106 /* Get local and remote SDP */ 2144 2145 2107 status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &local_sdp); 2146 2108 if (status != PJ_SUCCESS) { … … 2164 2126 } 2165 2127 2166 /* Create media session info based on SDP parameters. 2167 * We only support one stream per session at the moment 2168 */ 2169 status = pjmedia_session_info_from_sdp( call->inv->dlg->pool, 2170 pjsua_var.med_endpt, 2171 1,&sess_info, 2172 local_sdp, remote_sdp); 2128 status = pjsua_media_channel_update(call->index, local_sdp, remote_sdp); 2173 2129 if (status != PJ_SUCCESS) { 2174 2130 pjsua_perror(THIS_FILE, "Unable to create media session", 2175 2131 status); 2176 2132 call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 2133 pjsua_media_channel_deinit(call->index); 2177 2134 PJSUA_UNLOCK(); 2178 2135 return; 2179 2136 } 2180 2137 2181 /* Check if media is put on-hold */2182 if (sess_info.stream_cnt == 0 ||2183 sess_info.stream_info[0].dir == PJMEDIA_DIR_NONE)2184 {2185 2186 /* Determine who puts the call on-hold */2187 if (prev_media_st == PJSUA_CALL_MEDIA_ACTIVE) {2188 if (pjmedia_sdp_neg_was_answer_remote(call->inv->neg)) {2189 /* It was local who offer hold */2190 call->media_st = PJSUA_CALL_MEDIA_LOCAL_HOLD;2191 } else {2192 call->media_st = PJSUA_CALL_MEDIA_REMOTE_HOLD;2193 }2194 }2195 2196 call->media_dir = PJMEDIA_DIR_NONE;2197 2198 } else {2199 2200 /* Override ptime, if this option is specified. */2201 if (pjsua_var.media_cfg.ptime != 0) {2202 sess_info.stream_info[0].param->setting.frm_per_pkt = (pj_uint8_t)2203 (pjsua_var.media_cfg.ptime / sess_info.stream_info[0].param->info.frm_ptime);2204 if (sess_info.stream_info[0].param->setting.frm_per_pkt == 0)2205 sess_info.stream_info[0].param->setting.frm_per_pkt = 1;2206 }2207 2208 /* Disable VAD, if this option is specified. */2209 if (pjsua_var.media_cfg.no_vad) {2210 sess_info.stream_info[0].param->setting.vad = 0;2211 }2212 2213 2214 /* Optionally, application may modify other stream settings here2215 * (such as jitter buffer parameters, codec ptime, etc.)2216 */2217 sess_info.stream_info[0].jb_init = pjsua_var.media_cfg.jb_init;2218 sess_info.stream_info[0].jb_min_pre = pjsua_var.media_cfg.jb_min_pre;2219 sess_info.stream_info[0].jb_max_pre = pjsua_var.media_cfg.jb_max_pre;2220 sess_info.stream_info[0].jb_max = pjsua_var.media_cfg.jb_max;2221 2222 /* Create session based on session info. */2223 status = pjmedia_session_create( pjsua_var.med_endpt, &sess_info,2224 &call->med_tp,2225 call, &call->session );2226 if (status != PJ_SUCCESS) {2227 pjsua_perror(THIS_FILE, "Unable to create media session",2228 status);2229 //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE);2230 PJSUA_UNLOCK();2231 return;2232 }2233 2234 /* If DTMF callback is installed by application, install our2235 * callback to the session.2236 */2237 if (pjsua_var.ua_cfg.cb.on_dtmf_digit) {2238 pjmedia_session_set_dtmf_callback(call->session, 0,2239 &dtmf_callback,2240 (void*)(call->index));2241 }2242 2243 /* Get the port interface of the first stream in the session.2244 * We need the port interface to add to the conference bridge.2245 */2246 pjmedia_session_get_port(call->session, 0, &media_port);2247 2248 2249 /*2250 * Add the call to conference bridge.2251 */2252 port_name.ptr = tmp;2253 port_name.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI,2254 call->inv->dlg->remote.info->uri,2255 tmp, sizeof(tmp));2256 if (port_name.slen < 1) {2257 port_name = pj_str("call");2258 }2259 status = pjmedia_conf_add_port( pjsua_var.mconf, call->inv->pool,2260 media_port,2261 &port_name,2262 (unsigned*)&call->conf_slot);2263 if (status != PJ_SUCCESS) {2264 pjsua_perror(THIS_FILE, "Unable to create conference slot",2265 status);2266 call_destroy_media(call->index);2267 //call_disconnect(inv, PJSIP_SC_INTERNAL_SERVER_ERROR);2268 PJSUA_UNLOCK();2269 return;2270 }2271 2272 /* Call's media state is active */2273 call->media_st = PJSUA_CALL_MEDIA_ACTIVE;2274 call->media_dir = sess_info.stream_info[0].dir;2275 }2276 2277 /* Print info. */2278 {2279 char info[80];2280 int info_len = 0;2281 unsigned i;2282 2283 for (i=0; i<sess_info.stream_cnt; ++i) {2284 int len;2285 const char *dir;2286 pjmedia_stream_info *strm_info = &sess_info.stream_info[i];2287 2288 switch (strm_info->dir) {2289 case PJMEDIA_DIR_NONE:2290 dir = "inactive";2291 break;2292 case PJMEDIA_DIR_ENCODING:2293 dir = "sendonly";2294 break;2295 case PJMEDIA_DIR_DECODING:2296 dir = "recvonly";2297 break;2298 case PJMEDIA_DIR_ENCODING_DECODING:2299 dir = "sendrecv";2300 break;2301 default:2302 dir = "unknown";2303 break;2304 }2305 len = pj_ansi_sprintf( info+info_len,2306 ", stream #%d: %.*s (%s)", i,2307 (int)strm_info->fmt.encoding_name.slen,2308 strm_info->fmt.encoding_name.ptr,2309 dir);2310 if (len > 0)2311 info_len += len;2312 }2313 PJ_LOG(4,(THIS_FILE,"Media updates%s", info));2314 }2315 2138 2316 2139 /* Call application callback, if any */ … … 2414 2237 PJ_LOG(4,(THIS_FILE, "Call %d: received updated media offer", 2415 2238 call->index)); 2416 status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt, 2417 call->inv->pool, 1, 2418 &call->skinfo, &answer); 2239 status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, &answer); 2419 2240 } 2420 2241 -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
r1074 r1098 43 43 unsigned i; 44 44 45 pj_bzero(&pjsua_var, sizeof(pjsua_var)); 46 45 47 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) 46 48 pjsua_var.acc[i].index = i; … … 48 50 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) 49 51 pjsua_var.tpdata[i].index = i; 52 53 pjsua_var.stun_status = PJ_EUNKNOWN; 50 54 } 51 55 … … 467 471 if (ua_cfg->nameserver_count) { 468 472 #if PJSIP_HAS_RESOLVER 469 pj_dns_resolver *resv;470 473 unsigned i; 471 474 472 475 /* Create DNS resolver */ 473 status = pjsip_endpt_create_resolver(pjsua_var.endpt, &resv); 476 status = pjsip_endpt_create_resolver(pjsua_var.endpt, 477 &pjsua_var.resolver); 474 478 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 475 479 476 480 /* Configure nameserver for the DNS resolver */ 477 status = pj_dns_resolver_set_ns(resv, ua_cfg->nameserver_count, 481 status = pj_dns_resolver_set_ns(pjsua_var.resolver, 482 ua_cfg->nameserver_count, 478 483 ua_cfg->nameserver, NULL); 479 484 if (status != PJ_SUCCESS) { … … 483 488 484 489 /* Set this DNS resolver to be used by the SIP resolver */ 485 status = pjsip_endpt_set_resolver(pjsua_var.endpt, resv);490 status = pjsip_endpt_set_resolver(pjsua_var.endpt, pjsua_var.resolver); 486 491 if (status != PJ_SUCCESS) { 487 492 pjsua_perror(THIS_FILE, "Error setting DNS resolver", status); … … 551 556 552 557 558 /* Start resolving STUN server */ 559 status = pjsua_resolve_stun_server(PJ_FALSE); 560 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 561 pjsua_perror(THIS_FILE, "Error resolving STUN server", status); 562 return status; 563 } 564 553 565 /* Initialize PJSUA media subsystem */ 554 566 status = pjsua_media_subsys_init(media_cfg); … … 636 648 pj_gettimeofday(&now); 637 649 } while (PJ_TIME_VAL_LT(now, timeout)); 650 } 651 652 /* 653 * Resolve STUN server. 654 */ 655 pj_status_t pjsua_resolve_stun_server(pj_bool_t wait) 656 { 657 if (pjsua_var.stun_status == PJ_EUNKNOWN) { 658 /* Initialize STUN configuration */ 659 pj_stun_config_init(&pjsua_var.stun_cfg, &pjsua_var.cp.factory, 0, 660 pjsip_endpt_get_ioqueue(pjsua_var.endpt), 661 pjsip_endpt_get_timer_heap(pjsua_var.endpt)); 662 663 /* Start STUN server resolution */ 664 /* For now just do DNS A resolution */ 665 666 if (pjsua_var.ua_cfg.stun_srv.slen == 0) { 667 pjsua_var.stun_status = PJ_SUCCESS; 668 } else { 669 pj_hostent he; 670 671 pjsua_var.stun_status = 672 pj_gethostbyname(&pjsua_var.ua_cfg.stun_srv, &he); 673 674 if (pjsua_var.stun_status == PJ_SUCCESS) { 675 pj_sockaddr_in_init(&pjsua_var.stun_srv.ipv4, NULL, 0); 676 pjsua_var.stun_srv.ipv4.sin_addr = *(pj_in_addr*)he.h_addr; 677 pjsua_var.stun_srv.ipv4.sin_port = pj_htons((pj_uint16_t)3478); 678 } 679 } 680 return pjsua_var.stun_status; 681 682 } else if (pjsua_var.stun_status == PJ_EPENDING) { 683 /* STUN server resolution has been started, wait for the 684 * result. 685 */ 686 pj_assert(!"Should not happen"); 687 return PJ_EBUG; 688 689 } else { 690 /* STUN server has been resolved, return the status */ 691 return pjsua_var.stun_status; 692 } 638 693 } 639 694 … … 820 875 static pj_status_t create_sip_udp_sock(pj_in_addr bound_addr, 821 876 int port, 822 pj_bool_t use_stun,823 const pjsua_stun_config *stun_param,824 877 pj_sock_t *p_sock, 825 878 pj_sockaddr_in *p_pub_addr) 826 879 { 827 pjsua_stun_config stun; 880 char ip_addr[32]; 881 pj_str_t stun_srv; 828 882 pj_sock_t sock; 829 883 pj_status_t status; 884 885 /* Make sure STUN server resolution has completed */ 886 status = pjsua_resolve_stun_server(PJ_TRUE); 887 if (status != PJ_SUCCESS) { 888 pjsua_perror(THIS_FILE, "Error resolving STUN server", status); 889 return status; 890 } 830 891 831 892 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock); … … 857 918 } 858 919 859 /* Copy and normalize STUN param */ 860 if (use_stun) { 861 pj_memcpy(&stun, stun_param, sizeof(*stun_param)); 862 pjsua_normalize_stun_config(&stun); 920 if (pjsua_var.stun_srv.addr.sa_family != 0) { 921 pj_ansi_strcpy(ip_addr,pj_inet_ntoa(pjsua_var.stun_srv.ipv4.sin_addr)); 922 stun_srv = pj_str(ip_addr); 863 923 } else { 864 pj_bzero(&stun, sizeof(pjsua_stun_config));924 stun_srv.slen = 0; 865 925 } 866 926 … … 868 928 * the name of local host. 869 929 */ 870 if (stun .stun_srv1.slen) {930 if (stun_srv.slen) { 871 931 /* 872 932 * STUN is specified, resolve the address with STUN. 873 933 */ 874 934 status = pjstun_get_mapped_addr(&pjsua_var.cp.factory, 1, &sock, 875 &stun.stun_srv1, 876 stun.stun_port1, 877 &stun.stun_srv2, 878 stun.stun_port2, 879 p_pub_addr); 935 &stun_srv, 3478, 936 &stun_srv, 3478, 937 p_pub_addr); 880 938 if (status != PJ_SUCCESS) { 881 939 pjsua_perror(THIS_FILE, "Error resolving with STUN", status); … … 987 1045 */ 988 1046 status = create_sip_udp_sock(bound_addr.sin_addr, cfg->port, 989 cfg->use_stun, &cfg->stun_config,990 1047 &sock, &pub_addr); 991 1048 if (status != PJ_SUCCESS) -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
r1066 r1098 216 216 pj_sock_t sock[2]; 217 217 218 /* Make sure STUN server resolution has completed */ 219 status = pjsua_resolve_stun_server(PJ_TRUE); 220 if (status != PJ_SUCCESS) { 221 pjsua_perror(THIS_FILE, "Error resolving STUN server", status); 222 return status; 223 } 224 225 218 226 if (next_rtp_port == 0) 219 227 next_rtp_port = (pj_uint16_t)cfg->port; … … 273 281 * and make sure that the mapped RTCP port is adjacent with the RTP. 274 282 */ 275 if (cfg->stun_config.stun_srv1.slen) { 283 if (pjsua_var.stun_srv.addr.sa_family != 0) { 284 char ip_addr[32]; 285 pj_str_t stun_srv; 286 287 pj_ansi_strcpy(ip_addr, 288 pj_inet_ntoa(pjsua_var.stun_srv.ipv4.sin_addr)); 289 stun_srv = pj_str(ip_addr); 290 276 291 status=pjstun_get_mapped_addr(&pjsua_var.cp.factory, 2, sock, 277 &cfg->stun_config.stun_srv1, 278 cfg->stun_config.stun_port1, 279 &cfg->stun_config.stun_srv2, 280 cfg->stun_config.stun_port2, 292 &stun_srv, 3478, 293 &stun_srv, 3478, 281 294 mapped_addr); 282 295 if (status != PJ_SUCCESS) { … … 489 502 490 503 491 /* 492 * Create UDP media transports for all the calls. This function creates 493 * one UDP media transport for each call. 494 */ 495 PJ_DEF(pj_status_t) 496 pjsua_media_transports_create(const pjsua_transport_config *app_cfg) 497 { 498 pjsua_transport_config cfg; 504 /* Create normal UDP media transports */ 505 static pj_status_t create_udp_media_transports(pjsua_transport_config *cfg) 506 { 499 507 unsigned i; 500 508 pj_status_t status; 501 509 502 503 /* Make sure pjsua_init() has been called */504 PJ_ASSERT_RETURN(pjsua_var.ua_cfg.max_calls>0, PJ_EINVALIDOP);505 506 PJSUA_LOCK();507 508 /* Delete existing media transports */509 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {510 if (pjsua_var.calls[i].med_tp != NULL) {511 pjsua_var.calls[i].med_tp->op->destroy(pjsua_var.calls[i].med_tp);512 pjsua_var.calls[i].med_tp = NULL;513 }514 }515 516 /* Copy config */517 pj_memcpy(&cfg, app_cfg, sizeof(*app_cfg));518 pjsua_normalize_stun_config(&cfg.stun_config);519 520 510 /* Create each media transport */ 521 511 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 522 512 523 status = create_rtp_rtcp_sock( &cfg, &pjsua_var.calls[i].skinfo);513 status = create_rtp_rtcp_sock(cfg, &pjsua_var.calls[i].skinfo); 524 514 if (status != PJ_SUCCESS) { 525 515 pjsua_perror(THIS_FILE, "Unable to create RTP/RTCP socket", … … 546 536 } 547 537 548 PJSUA_UNLOCK();549 550 538 return PJ_SUCCESS; 551 539 … … 553 541 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 554 542 if (pjsua_var.calls[i].med_tp != NULL) { 555 pj sua_var.calls[i].med_tp->op->destroy(pjsua_var.calls[i].med_tp);543 pjmedia_transport_close(pjsua_var.calls[i].med_tp); 556 544 pjsua_var.calls[i].med_tp = NULL; 557 545 } 558 546 } 559 547 548 return status; 549 } 550 551 552 /* Create ICE media transports (when ice is enabled) */ 553 static pj_status_t create_ice_media_transports(pjsua_transport_config *cfg) 554 { 555 unsigned i; 556 pj_status_t status; 557 558 /* Create each media transport */ 559 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 560 pj_ice_st *ice_st; 561 562 status = pjmedia_ice_create(pjsua_var.med_endpt, NULL, 1, 563 &pjsua_var.stun_cfg, 564 &pjsua_var.calls[i].med_tp); 565 if (status != PJ_SUCCESS) { 566 pjsua_perror(THIS_FILE, "Unable to create ICE media transport", 567 status); 568 goto on_error; 569 } 570 571 ice_st = pjmedia_ice_get_ice_st(pjsua_var.calls[i].med_tp); 572 573 /* Add host candidates for RTP */ 574 status = pj_ice_st_add_all_host_interfaces(ice_st, 1, 0, 575 PJ_FALSE, NULL); 576 if (status != PJ_SUCCESS) { 577 pjsua_perror(THIS_FILE, "Error adding ICE host candidates", 578 status); 579 goto on_error; 580 } 581 582 /* Configure STUN server */ 583 if (pjsua_var.stun_srv.addr.sa_family != 0) { 584 585 status = pj_ice_st_set_stun_addr(ice_st, 586 pjsua_var.media_cfg.enable_relay, 587 &pjsua_var.stun_srv.ipv4); 588 if (status != PJ_SUCCESS) { 589 pjsua_perror(THIS_FILE, "Error setting ICE's STUN server", 590 status); 591 goto on_error; 592 } 593 594 /* Add STUN server reflexive candidate for RTP */ 595 status = pj_ice_st_add_stun_interface(ice_st, 1, 0, 596 PJ_FALSE, NULL); 597 if (status != PJ_SUCCESS) { 598 pjsua_perror(THIS_FILE, "Error adding ICE address", 599 status); 600 goto on_error; 601 } 602 } 603 } 604 605 /* Wait until all ICE transports are ready */ 606 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 607 pj_ice_st *ice_st; 608 609 ice_st = pjmedia_ice_get_ice_st(pjsua_var.calls[i].med_tp); 610 611 /* Wait until interface status is PJ_SUCCESS */ 612 for (;;) { 613 status = pj_ice_st_get_interfaces_status(ice_st); 614 if (status == PJ_EPENDING) 615 pjsua_handle_events(100); 616 else 617 break; 618 } 619 620 if (status != PJ_SUCCESS) { 621 pjsua_perror(THIS_FILE, 622 "Error adding STUN address to ICE media transport", 623 status); 624 goto on_error; 625 } 626 627 /* Get transport info */ 628 pjmedia_transport_get_info(pjsua_var.calls[i].med_tp, 629 &pjsua_var.calls[i].skinfo); 630 631 } 632 633 return PJ_SUCCESS; 634 635 on_error: 636 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 637 if (pjsua_var.calls[i].med_tp != NULL) { 638 pjmedia_transport_close(pjsua_var.calls[i].med_tp); 639 pjsua_var.calls[i].med_tp = NULL; 640 } 641 } 642 643 return status; 644 } 645 646 647 /* 648 * Create UDP media transports for all the calls. This function creates 649 * one UDP media transport for each call. 650 */ 651 PJ_DEF(pj_status_t) 652 pjsua_media_transports_create(const pjsua_transport_config *app_cfg) 653 { 654 pjsua_transport_config cfg; 655 unsigned i; 656 pj_status_t status; 657 658 659 /* Make sure pjsua_init() has been called */ 660 PJ_ASSERT_RETURN(pjsua_var.ua_cfg.max_calls>0, PJ_EINVALIDOP); 661 662 PJSUA_LOCK(); 663 664 /* Delete existing media transports */ 665 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 666 if (pjsua_var.calls[i].med_tp != NULL) { 667 pjmedia_transport_close(pjsua_var.calls[i].med_tp); 668 pjsua_var.calls[i].med_tp = NULL; 669 } 670 } 671 672 /* Copy config */ 673 pjsua_transport_config_dup(pjsua_var.pool, &cfg, app_cfg); 674 675 if (pjsua_var.media_cfg.enable_ice) { 676 status = create_ice_media_transports(&cfg); 677 } else { 678 status = create_udp_media_transports(&cfg); 679 } 680 681 560 682 PJSUA_UNLOCK(); 561 683 562 684 return status; 685 } 686 687 688 pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, 689 pjsip_role_e role) 690 { 691 pjsua_call *call = &pjsua_var.calls[call_id]; 692 693 if (pjsua_var.media_cfg.enable_ice) { 694 pj_ice_role ice_role; 695 pj_status_t status; 696 697 ice_role = (role==PJSIP_ROLE_UAC ? PJ_ICE_ROLE_CONTROLLING : 698 PJ_ICE_ROLE_CONTROLLED); 699 700 /* Restart ICE */ 701 pjmedia_ice_stop_ice(call->med_tp); 702 703 status = pjmedia_ice_init_ice(call->med_tp, ice_role, NULL, NULL); 704 if (status != PJ_SUCCESS) 705 return status; 706 } 707 708 return PJ_SUCCESS; 709 } 710 711 pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, 712 pj_pool_t *pool, 713 pjmedia_sdp_session **p_sdp) 714 { 715 pjmedia_sdp_session *sdp; 716 pjsua_call *call = &pjsua_var.calls[call_id]; 717 pj_status_t status; 718 719 status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, pool, 1, 720 &call->skinfo, &sdp); 721 if (status != PJ_SUCCESS) 722 goto on_error; 723 724 if (pjsua_var.media_cfg.enable_ice) { 725 status = pjmedia_ice_modify_sdp(call->med_tp, pool, sdp); 726 if (status != PJ_SUCCESS) 727 goto on_error; 728 } 729 730 *p_sdp = sdp; 731 return PJ_SUCCESS; 732 733 on_error: 734 pjsua_media_channel_deinit(call_id); 735 return status; 736 737 } 738 739 740 static void stop_media_session(pjsua_call_id call_id) 741 { 742 pjsua_call *call = &pjsua_var.calls[call_id]; 743 744 if (call->conf_slot != PJSUA_INVALID_ID) { 745 pjmedia_conf_remove_port(pjsua_var.mconf, call->conf_slot); 746 call->conf_slot = PJSUA_INVALID_ID; 747 } 748 749 if (call->session) { 750 pjmedia_session_destroy(call->session); 751 call->session = NULL; 752 753 PJ_LOG(4,(THIS_FILE, "Media session for call %d is destroyed", 754 call_id)); 755 756 } 757 758 call->media_st = PJSUA_CALL_MEDIA_NONE; 759 } 760 761 pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id) 762 { 763 pjsua_call *call = &pjsua_var.calls[call_id]; 764 765 stop_media_session(call_id); 766 767 if (pjsua_var.media_cfg.enable_ice) { 768 pjmedia_ice_stop_ice(call->med_tp); 769 } 770 771 return PJ_SUCCESS; 772 } 773 774 775 /* 776 * DTMF callback from the stream. 777 */ 778 static void dtmf_callback(pjmedia_stream *strm, void *user_data, 779 int digit) 780 { 781 PJ_UNUSED_ARG(strm); 782 783 if (pjsua_var.ua_cfg.cb.on_dtmf_digit) { 784 pjsua_call_id call_id; 785 786 call_id = (pjsua_call_id)user_data; 787 pjsua_var.ua_cfg.cb.on_dtmf_digit(call_id, digit); 788 } 789 } 790 791 792 pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, 793 pjmedia_sdp_session *local_sdp, 794 pjmedia_sdp_session *remote_sdp) 795 { 796 int prev_media_st = 0; 797 pjsua_call *call = &pjsua_var.calls[call_id]; 798 pjmedia_session_info sess_info; 799 pjmedia_port *media_port; 800 pj_str_t port_name; 801 char tmp[PJSIP_MAX_URL_SIZE]; 802 pj_status_t status; 803 804 /* Destroy existing media session, if any. */ 805 prev_media_st = call->media_st; 806 stop_media_session(call->index); 807 808 /* Create media session info based on SDP parameters. 809 * We only support one stream per session at the moment 810 */ 811 status = pjmedia_session_info_from_sdp( call->inv->dlg->pool, 812 pjsua_var.med_endpt, 813 1,&sess_info, 814 local_sdp, remote_sdp); 815 if (status != PJ_SUCCESS) 816 return status; 817 818 819 /* Check if media is put on-hold */ 820 if (sess_info.stream_cnt == 0 || 821 sess_info.stream_info[0].dir == PJMEDIA_DIR_NONE) 822 { 823 824 /* Determine who puts the call on-hold */ 825 if (prev_media_st == PJSUA_CALL_MEDIA_ACTIVE) { 826 if (pjmedia_sdp_neg_was_answer_remote(call->inv->neg)) { 827 /* It was local who offer hold */ 828 call->media_st = PJSUA_CALL_MEDIA_LOCAL_HOLD; 829 } else { 830 call->media_st = PJSUA_CALL_MEDIA_REMOTE_HOLD; 831 } 832 } 833 834 call->media_dir = PJMEDIA_DIR_NONE; 835 836 /* Shutdown transport */ 837 /* No need because we need keepalive? */ 838 839 } else { 840 841 /* Start ICE */ 842 if (pjsua_var.media_cfg.enable_ice) { 843 status = pjmedia_ice_start_ice(call->med_tp, call->inv->pool, 844 remote_sdp); 845 if (status != PJ_SUCCESS) 846 return status; 847 } 848 849 /* Override ptime, if this option is specified. */ 850 if (pjsua_var.media_cfg.ptime != 0) { 851 sess_info.stream_info[0].param->setting.frm_per_pkt = (pj_uint8_t) 852 (pjsua_var.media_cfg.ptime / sess_info.stream_info[0].param->info.frm_ptime); 853 if (sess_info.stream_info[0].param->setting.frm_per_pkt == 0) 854 sess_info.stream_info[0].param->setting.frm_per_pkt = 1; 855 } 856 857 /* Disable VAD, if this option is specified. */ 858 if (pjsua_var.media_cfg.no_vad) { 859 sess_info.stream_info[0].param->setting.vad = 0; 860 } 861 862 863 /* Optionally, application may modify other stream settings here 864 * (such as jitter buffer parameters, codec ptime, etc.) 865 */ 866 sess_info.stream_info[0].jb_init = pjsua_var.media_cfg.jb_init; 867 sess_info.stream_info[0].jb_min_pre = pjsua_var.media_cfg.jb_min_pre; 868 sess_info.stream_info[0].jb_max_pre = pjsua_var.media_cfg.jb_max_pre; 869 sess_info.stream_info[0].jb_max = pjsua_var.media_cfg.jb_max; 870 871 /* Create session based on session info. */ 872 status = pjmedia_session_create( pjsua_var.med_endpt, &sess_info, 873 &call->med_tp, 874 call, &call->session ); 875 if (status != PJ_SUCCESS) { 876 return status; 877 } 878 879 /* If DTMF callback is installed by application, install our 880 * callback to the session. 881 */ 882 if (pjsua_var.ua_cfg.cb.on_dtmf_digit) { 883 pjmedia_session_set_dtmf_callback(call->session, 0, 884 &dtmf_callback, 885 (void*)(call->index)); 886 } 887 888 /* Get the port interface of the first stream in the session. 889 * We need the port interface to add to the conference bridge. 890 */ 891 pjmedia_session_get_port(call->session, 0, &media_port); 892 893 894 /* 895 * Add the call to conference bridge. 896 */ 897 port_name.ptr = tmp; 898 port_name.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, 899 call->inv->dlg->remote.info->uri, 900 tmp, sizeof(tmp)); 901 if (port_name.slen < 1) { 902 port_name = pj_str("call"); 903 } 904 status = pjmedia_conf_add_port( pjsua_var.mconf, call->inv->pool, 905 media_port, 906 &port_name, 907 (unsigned*)&call->conf_slot); 908 if (status != PJ_SUCCESS) { 909 return status; 910 } 911 912 /* Call's media state is active */ 913 call->media_st = PJSUA_CALL_MEDIA_ACTIVE; 914 call->media_dir = sess_info.stream_info[0].dir; 915 } 916 917 /* Print info. */ 918 { 919 char info[80]; 920 int info_len = 0; 921 unsigned i; 922 923 for (i=0; i<sess_info.stream_cnt; ++i) { 924 int len; 925 const char *dir; 926 pjmedia_stream_info *strm_info = &sess_info.stream_info[i]; 927 928 switch (strm_info->dir) { 929 case PJMEDIA_DIR_NONE: 930 dir = "inactive"; 931 break; 932 case PJMEDIA_DIR_ENCODING: 933 dir = "sendonly"; 934 break; 935 case PJMEDIA_DIR_DECODING: 936 dir = "recvonly"; 937 break; 938 case PJMEDIA_DIR_ENCODING_DECODING: 939 dir = "sendrecv"; 940 break; 941 default: 942 dir = "unknown"; 943 break; 944 } 945 len = pj_ansi_sprintf( info+info_len, 946 ", stream #%d: %.*s (%s)", i, 947 (int)strm_info->fmt.encoding_name.slen, 948 strm_info->fmt.encoding_name.ptr, 949 dir); 950 if (len > 0) 951 info_len += len; 952 } 953 PJ_LOG(4,(THIS_FILE,"Media updates%s", info)); 954 } 955 956 return PJ_SUCCESS; 563 957 } 564 958
Note: See TracChangeset
for help on using the changeset viewer.