Changeset 236 for pjproject/trunk
- Timestamp:
- Feb 26, 2006 9:23:45 PM (19 years ago)
- Location:
- pjproject/trunk/pjsip
- Files:
-
- 7 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/build/pjsua.dsp
r197 r236 99 99 # Begin Source File 100 100 101 SOURCE=..\src\pjsua\pjsua_c ore.c101 SOURCE=..\src\pjsua\pjsua_call.c 102 102 # End Source File 103 103 # Begin Source File 104 104 105 SOURCE=..\src\pjsua\pjsua_ inv.c105 SOURCE=..\src\pjsua\pjsua_core.c 106 106 # End Source File 107 107 # Begin Source File -
pjproject/trunk/pjsip/src/pjsua/main.c
r230 r236 24 24 25 25 /* Current dialog */ 26 static struct pjsua_inv_data *inv_session; 26 static int current_acc; 27 static int current_call = -1; 28 29 30 /* 31 * Find next call. 32 */ 33 static pj_bool_t find_next_call(void) 34 { 35 int i; 36 37 for (i=current_call+1; i<(int)pjsua.max_calls; ++i) { 38 if (pjsua.calls[i].inv != NULL) { 39 current_call = i; 40 return PJ_TRUE; 41 } 42 } 43 44 for (i=0; i<current_call; ++i) { 45 if (pjsua.calls[i].inv != NULL) { 46 current_call = i; 47 return PJ_TRUE; 48 } 49 } 50 51 current_call = -1; 52 return PJ_FALSE; 53 } 54 55 56 /* 57 * Find previous call. 58 */ 59 static pj_bool_t find_prev_call(void) 60 { 61 int i; 62 63 for (i=current_call-1; i>=0; --i) { 64 if (pjsua.calls[i].inv != NULL) { 65 current_call = i; 66 return PJ_TRUE; 67 } 68 } 69 70 for (i=pjsua.max_calls-1; i>current_call; --i) { 71 if (pjsua.calls[i].inv != NULL) { 72 current_call = i; 73 return PJ_TRUE; 74 } 75 } 76 77 current_call = -1; 78 return PJ_FALSE; 79 } 80 81 27 82 28 83 /* 29 84 * Notify UI when invite state has changed. 30 85 */ 31 void pjsua_ui_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e) 32 { 86 void pjsua_ui_inv_on_state_changed(int call_index, pjsip_event *e) 87 { 88 pjsua_call *call = &pjsua.calls[call_index]; 89 33 90 PJ_UNUSED_ARG(e); 34 91 35 PJ_LOG(3,(THIS_FILE, " INVITE sessionstate changed to %s",36 pjsua_inv_state_names[inv->state]));37 38 if (inv->state == PJSIP_INV_STATE_DISCONNECTED) { 39 if (inv == inv_session->inv) {40 inv_session = inv_session->next;41 if (inv_session == &pjsua.inv_list)42 inv_session = pjsua.inv_list.next;92 PJ_LOG(3,(THIS_FILE, "Call %d state changed to %s", 93 call_index, 94 pjsua_inv_state_names[call->inv->state])); 95 96 if (call->inv->state == PJSIP_INV_STATE_DISCONNECTED) { 97 call->inv = NULL; 98 if ((int)call->index == current_call) { 99 find_next_call(); 43 100 } 44 101 45 102 } else { 46 103 47 if ( inv_session == &pjsua.inv_list || inv_session == NULL)48 inv_session = inv->mod_data[pjsua.mod.id];104 if (call && current_call==-1) 105 current_call = call->index; 49 106 50 107 } … … 67 124 static void print_buddy_list(void) 68 125 { 69 unsignedi;126 int i; 70 127 71 128 puts("Buddy list:"); 72 //puts("-------------------------------------------------------------------------------"); 129 73 130 if (pjsua.buddy_cnt == 0) 74 131 puts(" -none-"); … … 94 151 } 95 152 153 96 154 /* 97 * Show a bit of help.98 */ 99 static void keystroke_help(void)155 * Print account status. 156 */ 157 static void print_acc_status(int acc_index) 100 158 { 101 159 char reg_status[128]; 102 160 103 if (pjsua. regc == NULL) {161 if (pjsua.acc[acc_index].regc == NULL) { 104 162 pj_ansi_strcpy(reg_status, " -not registered to server-"); 105 } else if (pjsua.regc_last_err != PJ_SUCCESS) { 106 pj_strerror(pjsua.regc_last_err, reg_status, sizeof(reg_status)); 107 } else if (pjsua.regc_last_code>=200 && pjsua.regc_last_code<=699) { 163 164 } else if (pjsua.acc[acc_index].reg_last_err != PJ_SUCCESS) { 165 pj_strerror(pjsua.acc[acc_index].reg_last_err, reg_status, sizeof(reg_status)); 166 167 } else if (pjsua.acc[acc_index].reg_last_code>=200 && 168 pjsua.acc[acc_index].reg_last_code<=699) { 108 169 109 170 pjsip_regc_info info; 110 171 111 pjsip_regc_get_info(pjsua. regc, &info);172 pjsip_regc_get_info(pjsua.acc[acc_index].regc, &info); 112 173 113 174 pj_snprintf(reg_status, sizeof(reg_status), 114 175 "%s (%.*s;expires=%d)", 115 pjsip_get_status_text(pjsua. regc_last_code)->ptr,176 pjsip_get_status_text(pjsua.acc[acc_index].reg_last_code)->ptr, 116 177 (int)info.client_uri.slen, 117 178 info.client_uri.ptr, … … 119 180 120 181 } else { 121 pj_sprintf(reg_status, "in progress (%d)", pjsua.regc_last_code); 122 } 123 124 printf(">>>>\nRegistration status: %s\n", reg_status); 125 printf("Online status: %s\n", 126 (pjsua.online_status ? "Online" : "Invisible")); 182 pj_sprintf(reg_status, "in progress (%d)", 183 pjsua.acc[acc_index].reg_last_code); 184 } 185 186 printf("[%2d] Registration status: %s\n", acc_index, reg_status); 187 printf(" Online status: %s\n", 188 (pjsua.acc[acc_index].online_status ? "Online" : "Invisible")); 189 } 190 191 /* 192 * Show a bit of help. 193 */ 194 static void keystroke_help(void) 195 { 196 int i; 197 198 printf(">>>>\n"); 199 200 for (i=0; i<pjsua.acc_cnt; ++i) 201 print_acc_status(i); 202 127 203 print_buddy_list(); 128 204 … … 135 211 puts("| h Hangup call | u Unsubscribe presence | ru Unregister |"); 136 212 puts("| ] Select next dialog | t ToGgle Online status | d Dump status |"); 137 puts("| [ Select previous dialog | | 213 puts("| [ Select previous dialog | | dc Dump config |"); 138 214 puts("| +--------------------------+-------------------+"); 139 215 puts("| H Hold call | Conference Command | |"); … … 263 339 { 264 340 unsigned i, count; 265 pjmedia_conf_port_info info[ 16];341 pjmedia_conf_port_info info[PJSUA_MAX_CALLS]; 266 342 267 343 printf("Conference ports:\n"); … … 270 346 pjmedia_conf_get_ports_info(pjsua.mconf, &count, info); 271 347 for (i=0; i<count; ++i) { 272 char txlist[ 80];273 unsignedj;348 char txlist[PJSUA_MAX_CALLS*4+10]; 349 int j; 274 350 pjmedia_conf_port_info *port_info = &info[i]; 275 351 276 352 txlist[0] = '\0'; 277 for (j=0; j<pjsua.max_ ports; ++j) {353 for (j=0; j<pjsua.max_calls+PJSUA_CONF_MORE_PORTS; ++j) { 278 354 char s[10]; 279 355 if (port_info->listener[j]) { … … 310 386 case 'm': 311 387 /* Make call! : */ 312 if (pj_list_size(&pjsua.inv_list)) 313 printf("(You have %d calls)\n", pj_list_size(&pjsua.inv_list)); 388 printf("(You currently have %d calls)\n", pjsua.call_cnt); 314 389 315 390 ui_input_url("Make call", buf, sizeof(buf), &result); … … 318 393 puts("You can't do that with make call!"); 319 394 else 320 pjsua_invite(pjsua.buddies[result.nb_result].uri.ptr, NULL); 395 pjsua_make_call( current_acc, 396 pjsua.buddies[result.nb_result].uri.ptr, 397 NULL); 321 398 } else if (result.uri_result) 322 pjsua_ invite(result.uri_result, NULL);399 pjsua_make_call( current_acc, result.uri_result, NULL); 323 400 324 401 break; … … 327 404 case 'a': 328 405 329 if ( inv_session == &pjsua.inv_list||330 inv_session->inv->role != PJSIP_ROLE_UAS ||331 inv_session->inv->state >= PJSIP_INV_STATE_CONNECTING)406 if (current_call == -1 || 407 pjsua.calls[current_call].inv->role != PJSIP_ROLE_UAS || 408 pjsua.calls[current_call].inv->state >= PJSIP_INV_STATE_CONNECTING) 332 409 { 333 410 puts("No pending incoming call"); … … 350 427 * keyboard input. 351 428 */ 352 if ( inv_session == &pjsua.inv_list) {429 if (current_call == -1) { 353 430 puts("Call has been disconnected"); 354 431 fflush(stdout); … … 356 433 } 357 434 358 status = pjsip_inv_answer(inv_session->inv, atoi(buf), 435 status = pjsip_inv_answer(pjsua.calls[current_call].inv, 436 atoi(buf), 359 437 NULL, NULL, &tdata); 360 438 if (status == PJ_SUCCESS) 361 status = pjsip_inv_send_msg(inv_session->inv, tdata, NULL); 439 status = pjsip_inv_send_msg(pjsua.calls[current_call].inv, 440 tdata, NULL); 362 441 363 442 if (status != PJ_SUCCESS) … … 371 450 case 'h': 372 451 373 if ( inv_session == &pjsua.inv_list) {452 if (current_call == -1) { 374 453 puts("No current call"); 375 454 fflush(stdout); … … 377 456 378 457 } else { 379 pjsua_ inv_hangup(inv_session, PJSIP_SC_DECLINE);458 pjsua_call_hangup(current_call, PJSIP_SC_DECLINE); 380 459 } 381 460 break; … … 387 466 */ 388 467 if (menuin[0] == ']') { 389 inv_session = inv_session->next; 390 if (inv_session == &pjsua.inv_list) 391 inv_session = pjsua.inv_list.next; 468 find_next_call(); 392 469 393 470 } else { 394 inv_session = inv_session->prev; 395 if (inv_session == &pjsua.inv_list) 396 inv_session = pjsua.inv_list.prev; 397 } 398 399 if (inv_session != &pjsua.inv_list) { 471 find_prev_call(); 472 } 473 474 if (current_call != -1) { 400 475 char url[PJSIP_MAX_URL_SIZE]; 401 476 int len; 402 403 len = pjsip_uri_print(0, inv_session->inv->dlg->remote.info->uri, 404 url, sizeof(url)-1); 477 const pjsip_uri *u; 478 479 u = pjsua.calls[current_call].inv->dlg->remote.info->uri; 480 len = pjsip_uri_print(0, u, url, sizeof(url)-1); 405 481 if (len < 1) { 406 482 pj_ansi_strcpy(url, "<uri is too long>"); … … 420 496 * Hold call. 421 497 */ 422 if ( inv_session != &pjsua.inv_list) {498 if (current_call != -1) { 423 499 424 pjsua_ inv_set_hold(inv_session);500 pjsua_call_set_hold(current_call); 425 501 426 502 } else { … … 433 509 * Send re-INVITE (to release hold, etc). 434 510 */ 435 if ( inv_session != &pjsua.inv_list) {511 if (current_call != -1) { 436 512 437 pjsua_ inv_reinvite(inv_session);513 pjsua_call_reinvite(current_call); 438 514 439 515 } else { … … 446 522 * Transfer call. 447 523 */ 448 if ( inv_session == &pjsua.inv_list) {524 if (current_call == -1) { 449 525 450 526 PJ_LOG(3,(THIS_FILE, "No current call")); 451 527 452 528 } else { 453 struct pjsua_inv_data *cur = inv_session;529 int call = current_call; 454 530 455 531 ui_input_url("Transfer to URL", buf, sizeof(buf), &result); … … 457 533 /* Check if call is still there. */ 458 534 459 if (c ur != inv_session) {535 if (call != current_call) { 460 536 puts("Call has been disconnected"); 461 537 continue; … … 466 542 puts("You can't do that with transfer call!"); 467 543 else 468 pjsua_ inv_xfer_call( inv_session,469 544 pjsua_call_xfer( current_call, 545 pjsua.buddies[result.nb_result].uri.ptr); 470 546 471 547 } else if (result.uri_result) { 472 pjsua_ inv_xfer_call( inv_session, result.uri_result);548 pjsua_call_xfer( current_call, result.uri_result); 473 549 } 474 550 } … … 479 555 * Send DTMF strings. 480 556 */ 481 if ( inv_session == &pjsua.inv_list) {557 if (current_call == -1) { 482 558 483 559 PJ_LOG(3,(THIS_FILE, "No current call")); 484 560 485 } else if ( inv_session->session == NULL) {561 } else if (pjsua.calls[current_call].session == NULL) { 486 562 487 563 PJ_LOG(3,(THIS_FILE, "Media is not established yet!")); … … 489 565 } else { 490 566 pj_str_t digits; 491 struct pjsua_inv_data *cur = inv_session;567 int call = current_call; 492 568 pj_status_t status; 493 569 … … 498 574 } 499 575 500 if (c ur != inv_session) {576 if (call != current_call) { 501 577 puts("Call has been disconnected"); 502 578 continue; … … 504 580 505 581 digits = pj_str(buf); 506 status = pjmedia_session_dial_dtmf( inv_session->session, 0,582 status = pjmedia_session_dial_dtmf(pjsua.calls[current_call].session, 0, 507 583 &digits); 508 584 if (status != PJ_SUCCESS) { … … 522 598 if (result.nb_result != NO_NB) { 523 599 if (result.nb_result == -1) { 524 unsignedi;600 int i; 525 601 for (i=0; i<pjsua.buddy_cnt; ++i) 526 602 pjsua.buddies[i].monitor = (menuin[0]=='s'); … … 529 605 } 530 606 531 pjsua_pres_refresh( );607 pjsua_pres_refresh(current_acc); 532 608 533 609 } else if (result.uri_result) { … … 544 620 * Re-Register. 545 621 */ 546 pjsua_regc_update( PJ_TRUE);622 pjsua_regc_update(current_acc, PJ_TRUE); 547 623 break; 548 624 case 'u': … … 550 626 * Unregister 551 627 */ 552 pjsua_regc_update( PJ_FALSE);628 pjsua_regc_update(current_acc, PJ_FALSE); 553 629 break; 554 630 } … … 556 632 557 633 case 't': 558 pjsua.online_status = !pjsua.online_status; 559 pjsua_pres_refresh(); 634 pjsua.acc[current_acc].online_status = 635 !pjsua.acc[current_acc].online_status; 636 pjsua_pres_refresh(current_acc); 560 637 break; 561 638 … … 607 684 608 685 case 'd': 609 pjsua_dump(); 686 if (menuin[1] == 'c') { 687 char settings[2000]; 688 int len; 689 690 len = pjsua_dump_settings(settings, sizeof(settings)); 691 if (len < 1) 692 PJ_LOG(3,(THIS_FILE, "Error: not enough buffer")); 693 else 694 PJ_LOG(3,(THIS_FILE, 695 "Dumping configuration (%d bytes):\n%s\n", 696 len, settings)); 697 } else { 698 pjsua_dump(); 699 } 610 700 break; 611 701 … … 766 856 767 857 /* Init default settings. */ 768 769 858 pjsua_default(); 770 859 … … 772 861 /* Initialize pjsua (to create pool etc). 773 862 */ 774 775 863 if (pjsua_init() != PJ_SUCCESS) 776 864 return 1; … … 778 866 779 867 /* Parse command line arguments: */ 780 781 868 if (pjsua_parse_args(argc, argv) != PJ_SUCCESS) 782 869 return 1; … … 784 871 785 872 /* Init logging: */ 786 787 873 app_logging_init(); 788 874 … … 791 877 * messages. 792 878 */ 793 794 879 pjsip_endpt_register_module(pjsua.endpt, &console_msg_logger); 795 880 796 881 797 882 /* Start pjsua! */ 798 799 883 if (pjsua_start() != PJ_SUCCESS) { 800 884 … … 805 889 806 890 /* Sleep for a while, let any messages get printed to console: */ 807 808 891 pj_thread_sleep(500); 809 892 810 893 811 /* No current call initially: */812 813 inv_session = &pjsua.inv_list;814 815 816 894 /* Start UI console main loop: */ 817 818 895 ui_console_main(); 819 896 820 897 821 898 /* Destroy pjsua: */ 822 823 899 pjsua_destroy(); 824 900 825 901 826 902 /* Close logging: */ 827 828 903 app_logging_shutdown(); 829 904 -
pjproject/trunk/pjsip/src/pjsua/pjsua.h
r223 r236 48 48 * Max buddies in buddy list. 49 49 */ 50 #define PJSUA_MAX_BUDDIES 32 50 #ifndef PJSUA_MAX_BUDDIES 51 # define PJSUA_MAX_BUDDIES 32 52 #endif 53 51 54 52 55 /** 53 56 * Max simultaneous calls. 54 57 */ 55 #define PJSUA_MAX_CALLS 8 58 #ifndef PJSUA_MAX_CALLS 59 # define PJSUA_MAX_CALLS 256 60 #endif 61 62 63 /** 64 * Aditional ports to be allocated in the conference ports for non-call 65 * streams. 66 */ 67 #define PJSUA_CONF_MORE_PORTS 2 68 69 70 /** 71 * Maximum accounts. 72 */ 73 #ifndef PJSUA_MAX_ACC 74 # define PJSUA_MAX_ACC 8 75 #endif 76 77 78 /** 79 * Maximum credentials. 80 */ 81 #ifndef PJSUA_MAX_CRED 82 # define PJSUA_MAX_CRED PJSUA_MAX_ACC 83 #endif 56 84 57 85 58 86 /** 59 * Structure to be attached to alldialog.87 * Structure to be attached to invite dialog. 60 88 * Given a dialog "dlg", application can retrieve this structure 61 89 * by accessing dlg->mod_data[pjsua.mod.id]. 62 90 */ 63 struct pjsua_ inv_data91 struct pjsua_call 64 92 { 65 PJ_DECL_LIST_MEMBER(struct pjsua_inv_data); 66 93 unsigned index; /**< Index in pjsua array. */ 67 94 pjsip_inv_session *inv; /**< The invite session. */ 95 int acc_index; /**< Account index being used. */ 68 96 pjmedia_session *session; /**< The media session. */ 69 97 unsigned conf_slot; /**< Slot # in conference bridge. */ 70 unsigned call_slot; /**< RTP media index in med_sock_use[] */71 98 pjsip_evsub *xfer_sub; /**< Xfer server subscription, if this 72 99 call was triggered by xfer. */ 100 pjmedia_sock_info skinfo; /**< Preallocated media sockets. */ 101 102 void *app_data; /**< Application data. */ 73 103 }; 104 105 typedef struct pjsua_call pjsua_call; 74 106 75 107 … … 80 112 { 81 113 pj_str_t uri; /**< Buddy URI */ 114 int acc_index; /**< Which account to use. */ 82 115 pj_bool_t monitor; /**< Should we monitor? */ 83 116 pjsip_evsub *sub; /**< Buddy presence subscription */ … … 101 134 102 135 136 /** 137 * Account 138 */ 139 struct pjsua_acc 140 { 141 int index; /**< Index in accounts array. */ 142 pj_str_t local_uri; /**< Uri in From: header. */ 143 pj_str_t user_part; /**< User part of local URI. */ 144 pj_str_t host_part; /**< Host part of local URI. */ 145 pj_str_t contact_uri; /**< Uri in Contact: header. */ 146 147 pj_str_t reg_uri; /**< Registrar URI. */ 148 pjsip_regc *regc; /**< Client registration session. */ 149 pj_int32_t reg_timeout; /**< Default timeout. */ 150 pj_timer_entry reg_timer; /**< Registration timer. */ 151 pj_status_t reg_last_err; /**< Last registration error. */ 152 int reg_last_code; /**< Last status last register. */ 153 154 pj_str_t proxy; /**< Proxy URL. */ 155 pjsip_route_hdr route_set; /**< Route set. */ 156 157 pj_bool_t online_status; /**< Our online status. */ 158 pjsua_srv_pres pres_srv_list; /**< Server subscription list. */ 159 160 void *app_data; /**< Application data. */ 161 }; 162 163 164 typedef struct pjsua_acc pjsua_acc; 165 103 166 104 167 /* PJSUA application variables. */ … … 106 169 { 107 170 /* Control: */ 108 109 171 pj_caching_pool cp; /**< Global pool factory. */ 110 172 pjsip_endpoint *endpt; /**< Global endpoint. */ … … 114 176 115 177 /* Media: */ 116 117 178 pjmedia_endpt *med_endpt; /**< Media endpoint. */ 118 unsigned max_ports; /**< Max ports in conf. */119 179 pjmedia_conf *mconf; /**< Media conference. */ 120 180 pj_bool_t null_audio; /**< Null audio flag. */ 121 181 char *wav_file; /**< WAV file name to play. */ 122 182 unsigned wav_slot; /**< WAV player slot in bridge */ 183 pj_bool_t auto_play; /**< Auto play file for calls? */ 184 pj_bool_t auto_loop; /**< Auto loop RTP stream? */ 185 pj_bool_t auto_conf; /**< Auto put to conference? */ 186 123 187 124 188 /* User Agent behaviour: */ 125 126 189 int auto_answer; /**< Automatically answer in calls. */ 127 190 128 129 /* Since we support simultaneous calls, we need to have multiple 130 * RTP sockets. 131 */ 132 pjmedia_sock_info med_sock_info[PJSUA_MAX_CALLS]; 133 pj_bool_t med_sock_use[PJSUA_MAX_CALLS]; 134 135 /* User info: */ 136 137 pj_str_t local_uri; /**< Uri in From: header. */ 138 pj_str_t contact_uri; /**< Uri in Contact: header. */ 139 140 /* Proxy URLs: */ 141 142 pj_str_t proxy; 143 pj_str_t outbound_proxy; 144 pjsip_route_hdr route_set; 145 146 147 /* Registration: */ 148 149 pj_str_t registrar_uri; 150 pjsip_regc *regc; 151 pj_int32_t reg_timeout; 152 pj_timer_entry regc_timer; 153 pj_status_t regc_last_err; /**< Last registration error. */ 154 int regc_last_code;/**< Last status last register. */ 191 /* Account: */ 192 int acc_cnt; /**< Number of client registrations */ 193 pjsua_acc acc[PJSUA_MAX_ACC]; /** Client regs array. */ 155 194 156 195 157 196 /* Authentication credentials: */ 158 197 159 unsigned cred_count;160 pjsip_cred_info cred_info[ 4];198 int cred_count; /**< Number of credentials. */ 199 pjsip_cred_info cred_info[10]; /**< Array of credentials. */ 161 200 162 201 163 202 /* Threading (optional): */ 164 165 203 int thread_cnt; /**< Thread count. */ 166 204 pj_thread_t *threads[8]; /**< Thread instances. */ … … 168 206 169 207 /* Transport (UDP): */ 170 171 208 pj_uint16_t sip_port; /**< SIP signaling port. */ 172 209 pj_sock_t sip_sock; /**< SIP UDP socket. */ 173 210 pj_sockaddr_in sip_sock_name; /**< Public/STUN UDP socket addr. */ 174 211 212 pj_str_t outbound_proxy;/**< Outbound proxy. */ 175 213 176 214 177 215 /* STUN: */ 178 179 216 pj_str_t stun_srv1; 180 217 int stun_port1; … … 183 220 184 221 185 /* Logging: */ 186 222 /* Logging: */ 187 223 int log_level; /**< Logging verbosity. */ 188 224 int app_log_level; /**< stdout log verbosity. */ … … 191 227 192 228 193 /* List of invite sessions: */ 194 195 struct pjsua_inv_data inv_list; 229 /* PJSUA Calls: */ 230 int max_calls; /**< Max nb of calls. */ 231 int call_cnt; /**< Number of calls. */ 232 pjsua_call calls[PJSUA_MAX_CALLS]; /** Calls array. */ 196 233 197 234 198 235 /* SIMPLE and buddy status: */ 199 200 pj_bool_t online_status; /**< Out online status. */ 201 pjsua_srv_pres pres_srv_list; /**< Server subscription list. */ 202 203 unsigned buddy_cnt; 204 pjsua_buddy buddies[PJSUA_MAX_BUDDIES]; 236 int buddy_cnt; 237 pjsua_buddy buddies[PJSUA_MAX_BUDDIES]; 205 238 }; 206 239 … … 256 289 257 290 258 /***************************************************************************** 259 * PJSUA Invite session API (defined in pjsua_inv.c). 260 */ 291 /** 292 * Find account for incoming request. 293 */ 294 int pjsua_find_account_for_incoming(pjsip_rx_data *rdata); 295 296 297 /** 298 * Find account for outgoing request. 299 */ 300 int pjsua_find_account_for_outgoing(const pj_str_t *url); 301 302 303 /***************************************************************************** 304 * PJSUA Call API (defined in pjsua_call.c). 305 */ 306 307 /** 308 * Init pjsua call module. 309 */ 310 pj_status_t pjsua_call_init(void); 261 311 262 312 /** 263 313 * Make outgoing call. 264 314 */ 265 pj_status_t pjsua_invite(const char *cstr_dest_uri, 266 struct pjsua_inv_data **p_inv_data); 315 pj_status_t pjsua_make_call(int acc_index, 316 const char *cstr_dest_uri, 317 int *p_call_index); 267 318 268 319 … … 270 321 * Handle incoming invite request. 271 322 */ 272 pj_bool_t pjsua_inv_on_incoming(pjsip_rx_data *rdata); 273 323 pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata); 324 325 326 /** 327 * Answer call. 328 */ 329 void pjsua_call_answer(int call_index, int code); 274 330 275 331 /** 276 332 * Hangup call. 277 333 */ 278 void pjsua_ inv_hangup(struct pjsua_inv_data *inv_session, int code);334 void pjsua_call_hangup(int call_index, int code); 279 335 280 336 … … 282 338 * Put call on-hold. 283 339 */ 284 void pjsua_ inv_set_hold(struct pjsua_inv_data *inv_session);340 void pjsua_call_set_hold(int call_index); 285 341 286 342 … … 288 344 * Send re-INVITE (to release hold). 289 345 */ 290 void pjsua_ inv_reinvite(struct pjsua_inv_data *inv_session);346 void pjsua_call_reinvite(int call_index); 291 347 292 348 … … 294 350 * Transfer call. 295 351 */ 296 void pjsua_inv_xfer_call(struct pjsua_inv_data *inv_session, 297 const char *dest); 298 299 300 /** 301 * Callback to be called by session when invite session's state has changed. 302 */ 303 void pjsua_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e); 304 305 306 /** 307 * Callback to be called by session when outgoing dialog has forked. 308 * This function will create a forked dialog. 309 */ 310 void pjsua_inv_on_new_session(pjsip_inv_session *inv, pjsip_event *e); 311 312 313 /** 314 * Callback to be called when SDP offer/answer negotiation has just completed 315 * in the session. This function will start/update media if negotiation 316 * has succeeded. 317 */ 318 void pjsua_inv_on_media_update(pjsip_inv_session *inv, pj_status_t status); 319 320 /** 321 * Callback called when invite session received new offer. 322 */ 323 void pjsua_inv_on_rx_offer( pjsip_inv_session *inv, 324 const pjmedia_sdp_session *offer); 325 326 /** 327 * Callback to receive transaction state inside invite session or dialog 328 * (e.g. REFER, MESSAGE). 329 */ 330 void pjsua_inv_on_tsx_state_changed(pjsip_inv_session *inv, 331 pjsip_transaction *tsx, 332 pjsip_event *e); 352 void pjsua_call_xfer(int call_index, const char *dest); 353 333 354 334 355 /** … … 347 368 * @param app_callback Optional callback 348 369 */ 349 pj_status_t pjsua_regc_init( void);370 pj_status_t pjsua_regc_init(int acc_index); 350 371 351 372 /** … … 353 374 * this will start unregistration process. 354 375 */ 355 void pjsua_regc_update( pj_bool_t renew);376 void pjsua_regc_update(int acc_index, pj_bool_t renew); 356 377 357 378 … … 370 391 * Refresh both presence client and server subscriptions. 371 392 */ 372 void pjsua_pres_refresh( void);393 void pjsua_pres_refresh(int acc_index); 373 394 374 395 /** … … 393 414 * Notify UI when invite state has changed. 394 415 */ 395 void pjsua_ui_inv_on_state_changed( pjsip_inv_session *inv, pjsip_event *e);416 void pjsua_ui_inv_on_state_changed(int call_index, pjsip_event *e); 396 417 397 418 /** 398 419 * Notify UI when registration status has changed. 399 420 */ 400 void pjsua_ui_regc_on_state_changed(int code);421 void pjsua_ui_regc_on_state_changed(int acc_index); 401 422 402 423 … … 418 439 */ 419 440 pj_status_t pjsua_load_settings(const char *filename); 441 442 /** 443 * Dump settings. 444 */ 445 int pjsua_dump_settings(char *buf, pj_size_t max); 420 446 421 447 /** -
pjproject/trunk/pjsip/src/pjsua/pjsua_call.c
r226 r236 33 33 * Make outgoing call. 34 34 */ 35 pj_status_t pjsua_invite(const char *cstr_dest_uri, 36 struct pjsua_inv_data **p_inv_data) 35 pj_status_t pjsua_make_call(int acc_index, 36 const char *cstr_dest_uri, 37 int *p_call_index) 37 38 { 38 39 pj_str_t dest_uri; … … 40 41 pjmedia_sdp_session *offer; 41 42 pjsip_inv_session *inv; 42 struct pjsua_inv_data *inv_data;43 int call_index = -1; 43 44 pjsip_tx_data *tdata; 44 int med_sk_index = 0;45 45 pj_status_t status; 46 46 … … 49 49 dest_uri = pj_str((char*)cstr_dest_uri); 50 50 51 /* Find free socket. */52 for ( med_sk_index=0; med_sk_index<PJSUA_MAX_CALLS; ++med_sk_index) {53 if ( !pjsua.med_sock_use[med_sk_index])51 /* Find free call slot. */ 52 for (call_index=0; call_index<pjsua.max_calls; ++call_index) { 53 if (pjsua.calls[call_index].inv == NULL) 54 54 break; 55 55 } 56 56 57 if ( med_sk_index == PJSUA_MAX_CALLS) {57 if (call_index == pjsua.max_calls) { 58 58 PJ_LOG(3,(THIS_FILE, "Error: too many calls!")); 59 59 return PJ_ETOOMANY; 60 60 } 61 61 62 pjsua.med_sock_use[med_sk_index] = 1;63 64 62 /* Create outgoing dialog: */ 65 63 66 status = pjsip_dlg_create_uac( pjsip_ua_instance(), &pjsua.local_uri, 67 &pjsua.contact_uri, &dest_uri, &dest_uri, 64 status = pjsip_dlg_create_uac( pjsip_ua_instance(), 65 &pjsua.acc[acc_index].local_uri, 66 &pjsua.acc[acc_index].contact_uri, 67 &dest_uri, &dest_uri, 68 68 &dlg); 69 69 if (status != PJ_SUCCESS) { … … 74 74 /* Get media capability from media endpoint: */ 75 75 76 status = pjmedia_endpt_create_sdp( pjsua.med_endpt, dlg->pool, 77 1, &pjsua.med_sock_info[med_sk_index],76 status = pjmedia_endpt_create_sdp( pjsua.med_endpt, dlg->pool, 1, 77 &pjsua.calls[call_index].skinfo, 78 78 &offer); 79 79 if (status != PJ_SUCCESS) { … … 93 93 /* Create and associate our data in the session. */ 94 94 95 inv_data = pj_pool_zalloc( dlg->pool, sizeof(struct pjsua_inv_data)); 96 inv_data->inv = inv; 97 inv_data->call_slot = med_sk_index; 98 dlg->mod_data[pjsua.mod.id] = inv_data; 99 inv->mod_data[pjsua.mod.id] = inv_data; 95 pjsua.calls[call_index].inv = inv; 96 97 dlg->mod_data[pjsua.mod.id] = &pjsua.calls[call_index]; 98 inv->mod_data[pjsua.mod.id] = &pjsua.calls[call_index]; 100 99 101 100 102 101 /* Set dialog Route-Set: */ 103 102 104 if (!pj_list_empty(&pjsua. route_set))105 pjsip_dlg_set_route_set(dlg, &pjsua. route_set);103 if (!pj_list_empty(&pjsua.acc[acc_index].route_set)) 104 pjsip_dlg_set_route_set(dlg, &pjsua.acc[acc_index].route_set); 106 105 107 106 … … 122 121 123 122 124 /* Add invite session to the list. */125 126 pj_list_push_back(&pjsua.inv_list, inv_data);127 128 129 123 /* Send initial INVITE: */ 130 124 131 125 status = pjsip_inv_send_msg(inv, tdata, NULL); 132 126 if (status != PJ_SUCCESS) { 133 /*134 * Note:135 * inv_data will be removed from the list in the callback136 */137 127 pjsua_perror(THIS_FILE, "Unable to send initial INVITE request", 138 128 status); … … 142 132 143 133 /* Done. */ 144 if (p_inv_data) 145 *p_inv_data = inv_data; 134 135 ++pjsua.call_cnt; 136 137 if (p_call_index) 138 *p_call_index = call_index; 146 139 147 140 return PJ_SUCCESS; … … 149 142 150 143 on_error: 151 152 144 PJ_TODO(DESTROY_DIALOG_ON_FAIL); 153 pjsua.med_sock_use[med_sk_index] = 0; 145 if (call_index != -1) { 146 pjsua.calls[call_index].inv = NULL; 147 } 154 148 return status; 155 149 } … … 159 153 * Handle incoming INVITE request. 160 154 */ 161 pj_bool_t pjsua_ inv_on_incoming(pjsip_rx_data *rdata)155 pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata) 162 156 { 163 157 pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata); … … 167 161 unsigned options = 0; 168 162 pjsip_inv_session *inv; 169 struct pjsua_inv_data *inv_data; 163 int acc_index; 164 int call_index = -1; 170 165 pjmedia_sdp_session *answer; 171 int med_sk_index;172 166 pj_status_t status; 173 167 … … 215 209 216 210 /* Find free call slot. */ 217 for ( med_sk_index=0; med_sk_index<PJSUA_MAX_CALLS; ++med_sk_index) {218 if ( !pjsua.med_sock_use[med_sk_index])211 for (call_index=0; call_index < pjsua.max_calls; ++call_index) { 212 if (pjsua.calls[call_index].inv == NULL) 219 213 break; 220 214 } 221 215 222 if ( med_sk_index == PJSUA_MAX_CALLS) {216 if (call_index == PJSUA_MAX_CALLS) { 223 217 pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 224 218 PJSIP_SC_BUSY_HERE, NULL, … … 228 222 229 223 230 pjsua.med_sock_use[med_sk_index] = 1;231 232 224 /* Get media capability from media endpoint: */ 233 225 234 status = pjmedia_endpt_create_sdp( pjsua.med_endpt, rdata->tp_info.pool, 235 1, &pjsua.med_sock_info[med_sk_index],226 status = pjmedia_endpt_create_sdp( pjsua.med_endpt, rdata->tp_info.pool, 1, 227 &pjsua.calls[call_index].skinfo, 236 228 &answer ); 237 229 if (status != PJ_SUCCESS) { … … 239 231 NULL, NULL); 240 232 241 /* Free call socket. */242 pjsua.med_sock_use[med_sk_index] = 0;243 233 return PJ_TRUE; 244 234 } 245 235 236 /* TODO: 237 * 238 * Get which account is most likely to be associated with this incoming 239 * call. We need the account to find which contact URI to put for 240 * the call. 241 */ 242 acc_index = 0; 243 246 244 /* Create dialog: */ 247 245 248 246 status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata, 249 &pjsua.contact_uri, &dlg); 247 &pjsua.acc[acc_index].contact_uri, 248 &dlg); 250 249 if (status != PJ_SUCCESS) { 251 250 pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL, 252 251 NULL, NULL); 253 252 254 /* Free call socket. */255 pjsua.med_sock_use[med_sk_index] = 0;256 253 return PJ_TRUE; 257 254 } … … 264 261 265 262 pjsip_dlg_respond(dlg, rdata, 500, NULL); 266 267 /* Free call socket. */268 pjsua.med_sock_use[med_sk_index] = 0;269 263 270 264 // TODO: Need to delete dialog … … 275 269 /* Create and attach pjsua data to the dialog: */ 276 270 277 inv_data = pj_pool_zalloc(dlg->pool, sizeof(struct pjsua_inv_data)); 278 inv_data->inv = inv; 279 inv_data->call_slot = inv_data->call_slot = med_sk_index; 280 dlg->mod_data[pjsua.mod.id] = inv_data; 281 inv->mod_data[pjsua.mod.id] = inv_data; 282 283 pj_list_push_back(&pjsua.inv_list, inv_data); 271 pjsua.calls[call_index].inv = inv; 272 273 dlg->mod_data[pjsua.mod.id] = &pjsua.calls[call_index]; 274 inv->mod_data[pjsua.mod.id] = &pjsua.calls[call_index]; 284 275 285 276 … … 296 287 297 288 pjsip_dlg_respond(dlg, rdata, 500, NULL); 298 299 /* Free call socket. */300 pjsua.med_sock_use[med_sk_index] = 0;301 289 302 290 // TODO: Need to delete dialog … … 329 317 } 330 318 319 ++pjsua.call_cnt; 320 331 321 /* This INVITE request has been handled. */ 332 322 return PJ_TRUE; … … 338 328 * session state has changed. 339 329 */ 340 void pjsua_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e) 341 { 342 struct pjsua_inv_data *inv_data; 343 344 inv_data = inv->dlg->mod_data[pjsua.mod.id]; 330 static void pjsua_call_on_state_changed(pjsip_inv_session *inv, 331 pjsip_event *e) 332 { 333 pjsua_call *call = inv->dlg->mod_data[pjsua.mod.id]; 345 334 346 335 /* If this is an outgoing INVITE that was created because of 347 336 * REFER/transfer, send NOTIFY to transferer. 348 337 */ 349 if (inv_data && inv_data->xfer_sub && e->type==PJSIP_EVENT_TSX_STATE) 350 { 338 if (call && call->xfer_sub && e->type==PJSIP_EVENT_TSX_STATE) { 351 339 int st_code = -1; 352 340 pjsip_evsub_state ev_state = PJSIP_EVSUB_STATE_ACTIVE; 353 341 354 342 355 switch ( inv->state) {343 switch (call->inv->state) { 356 344 case PJSIP_INV_STATE_NULL: 357 345 case PJSIP_INV_STATE_CALLING: … … 383 371 pj_status_t status; 384 372 385 status = pjsip_xfer_notify( inv_data->xfer_sub,373 status = pjsip_xfer_notify( call->xfer_sub, 386 374 ev_state, st_code, 387 375 NULL, &tdata); … … 389 377 pjsua_perror(THIS_FILE, "Unable to create NOTIFY", status); 390 378 } else { 391 status = pjsip_xfer_send_request( inv_data->xfer_sub, tdata);379 status = pjsip_xfer_send_request(call->xfer_sub, tdata); 392 380 if (status != PJ_SUCCESS) { 393 381 pjsua_perror(THIS_FILE, "Unable to send NOTIFY", status); … … 398 386 399 387 388 pjsua_ui_inv_on_state_changed(call->index, e); 389 390 /* call->inv may be NULL now */ 391 400 392 /* Destroy media session when invite session is disconnected. */ 401 393 if (inv->state == PJSIP_INV_STATE_DISCONNECTED) { 402 394 403 pj_assert(inv_data != NULL); 404 405 if (inv_data && inv_data->session) { 406 pjmedia_conf_remove_port(pjsua.mconf, inv_data->conf_slot); 407 pjmedia_session_destroy(inv_data->session); 408 pjsua.med_sock_use[inv_data->call_slot] = 0; 409 inv_data->session = NULL; 395 pj_assert(call != NULL); 396 397 if (call && call->session) { 398 pjmedia_conf_remove_port(pjsua.mconf, call->conf_slot); 399 pjmedia_session_destroy(call->session); 400 call->session = NULL; 410 401 411 402 PJ_LOG(3,(THIS_FILE,"Media session is destroyed")); 412 403 } 413 404 414 if (inv_data) { 415 416 pj_list_erase(inv_data); 417 418 } 419 } 420 421 pjsua_ui_inv_on_state_changed(inv, e); 405 call->inv = NULL; 406 --pjsua.call_cnt; 407 } 422 408 } 423 409 … … 437 423 */ 438 424 if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 439 struct pjsua_inv_data *inv_data;440 441 inv_data= pjsip_evsub_get_mod_data(sub, pjsua.mod.id);442 if (! inv_data)425 pjsua_call *call; 426 427 call = pjsip_evsub_get_mod_data(sub, pjsua.mod.id); 428 if (!call) 443 429 return; 444 430 445 431 pjsip_evsub_set_mod_data(sub, pjsua.mod.id, NULL); 446 inv_data->xfer_sub = NULL;432 call->xfer_sub = NULL; 447 433 448 434 PJ_LOG(3,(THIS_FILE, "Xfer subscription terminated")); … … 459 445 pj_status_t status; 460 446 pjsip_tx_data *tdata; 461 struct pjsua_inv_data *inv_data; 447 pjsua_call *existing_call; 448 int new_call; 462 449 const pj_str_t str_refer_to = { "Refer-To", 8}; 463 450 pjsip_generic_string_hdr *refer_to; … … 465 452 struct pjsip_evsub_user xfer_cb; 466 453 pjsip_evsub *sub; 454 455 existing_call = inv->dlg->mod_data[pjsua.mod.id]; 467 456 468 457 /* Find the Refer-To header */ … … 524 513 525 514 /* Now make the outgoing call. */ 526 status = pjsua_ invite(uri, &inv_data);515 status = pjsua_make_call(existing_call->acc_index, uri, &new_call); 527 516 if (status != PJ_SUCCESS) { 528 517 … … 548 537 * reported back to the server subscription. 549 538 */ 550 inv_data->xfer_sub = sub;539 pjsua.calls[new_call].xfer_sub = sub; 551 540 552 541 /* Put the invite_data in the subscription. */ 553 pjsip_evsub_set_mod_data(sub, pjsua.mod.id, inv_data);542 pjsip_evsub_set_mod_data(sub, pjsua.mod.id, &pjsua.calls[new_call]); 554 543 } 555 544 … … 559 548 * session. We use this to trap incoming REFER request. 560 549 */ 561 void pjsua_inv_on_tsx_state_changed(pjsip_inv_session *inv, 562 pjsip_transaction *tsx, 563 pjsip_event *e) 564 { 550 static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv, 551 pjsip_transaction *tsx, 552 pjsip_event *e) 553 { 554 pjsua_call *call = inv->dlg->mod_data[pjsua.mod.id]; 555 565 556 if (tsx->role==PJSIP_ROLE_UAS && 566 557 tsx->state==PJSIP_TSX_STATE_TRYING && … … 570 561 * Incoming REFER request. 571 562 */ 572 on_call_transfered( inv, e->body.tsx_state.src.rdata);563 on_call_transfered(call->inv, e->body.tsx_state.src.rdata); 573 564 } 574 565 } … … 579 570 * has forked. 580 571 */ 581 void pjsua_inv_on_new_session(pjsip_inv_session *inv, pjsip_event *e) 572 static void pjsua_call_on_forked( pjsip_inv_session *inv, 573 pjsip_event *e) 582 574 { 583 575 PJ_UNUSED_ARG(inv); … … 591 583 * Create inactive SDP for call hold. 592 584 */ 593 static pj_status_t create_inactive_sdp( struct pjsua_inv_data *inv_session,585 static pj_status_t create_inactive_sdp(pjsua_call *call, 594 586 pjmedia_sdp_session **p_answer) 595 587 { … … 601 593 /* Create new offer */ 602 594 status = pjmedia_endpt_create_sdp(pjsua.med_endpt, pjsua.pool, 1, 603 &pjsua.med_sock_info[inv_session->call_slot], 604 &sdp); 595 &call->skinfo, &sdp); 605 596 if (status != PJ_SUCCESS) { 606 597 pjsua_perror(THIS_FILE, "Unable to create local SDP", status); … … 634 625 * Called when session received new offer. 635 626 */ 636 void pjsua_inv_on_rx_offer(pjsip_inv_session *inv,637 638 { 639 struct pjsua_inv_data *inv_data;627 static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, 628 const pjmedia_sdp_session *offer) 629 { 630 pjsua_call *call; 640 631 pjmedia_sdp_conn *conn; 641 632 pjmedia_sdp_session *answer; … … 643 634 pj_status_t status; 644 635 645 inv_data= inv->dlg->mod_data[pjsua.mod.id];636 call = inv->dlg->mod_data[pjsua.mod.id]; 646 637 647 638 /* … … 670 661 /* Supply candidate answer */ 671 662 if (is_remote_active) { 672 status = pjmedia_endpt_create_sdp( pjsua.med_endpt, inv->pool, 1, 673 &pjsua.med_sock_info[inv_data->call_slot], 674 &answer); 663 status = pjmedia_endpt_create_sdp( pjsua.med_endpt, call->inv->pool, 1, 664 &call->skinfo, &answer); 675 665 } else { 676 status = create_inactive_sdp( inv_data, &answer );666 status = create_inactive_sdp( call, &answer ); 677 667 } 678 668 … … 682 672 } 683 673 684 status = pjsip_inv_set_sdp_answer( inv, answer);674 status = pjsip_inv_set_sdp_answer(call->inv, answer); 685 675 if (status != PJ_SUCCESS) { 686 676 pjsua_perror(THIS_FILE, "Unable to set answer", status); … … 696 686 * has succeeded. 697 687 */ 698 void pjsua_inv_on_media_update(pjsip_inv_session *inv, pj_status_t status) 699 { 700 struct pjsua_inv_data *inv_data; 688 static void pjsua_call_on_media_update(pjsip_inv_session *inv, 689 pj_status_t status) 690 { 691 pjsua_call *call; 701 692 const pjmedia_sdp_session *local_sdp; 702 693 const pjmedia_sdp_session *remote_sdp; … … 705 696 char tmp[PJSIP_MAX_URL_SIZE]; 706 697 698 call = inv->dlg->mod_data[pjsua.mod.id]; 699 707 700 if (status != PJ_SUCCESS) { 708 701 … … 714 707 /* Destroy existing media session, if any. */ 715 708 716 inv_data = inv->dlg->mod_data[pjsua.mod.id]; 717 if (inv_data && inv_data->session) { 718 pjmedia_conf_remove_port(pjsua.mconf, inv_data->conf_slot); 719 pjmedia_session_destroy(inv_data->session); 720 pjsua.med_sock_use[inv_data->call_slot] = 0; 721 inv_data->session = NULL; 709 if (call && call->session) { 710 pjmedia_conf_remove_port(pjsua.mconf, call->conf_slot); 711 pjmedia_session_destroy(call->session); 712 call->session = NULL; 722 713 } 723 714 724 715 /* Get local and remote SDP */ 725 716 726 status = pjmedia_sdp_neg_get_active_local( inv->neg, &local_sdp);717 status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &local_sdp); 727 718 if (status != PJ_SUCCESS) { 728 719 pjsua_perror(THIS_FILE, … … 733 724 734 725 735 status = pjmedia_sdp_neg_get_active_remote( inv->neg, &remote_sdp);726 status = pjmedia_sdp_neg_get_active_remote(call->inv->neg, &remote_sdp); 736 727 if (status != PJ_SUCCESS) { 737 728 pjsua_perror(THIS_FILE, … … 748 739 749 740 status = pjmedia_session_create( pjsua.med_endpt, 1, 750 & pjsua.med_sock_info[inv_data->call_slot],741 &call->skinfo, 751 742 local_sdp, remote_sdp, 752 inv_data,753 & inv_data->session );743 call, 744 &call->session ); 754 745 if (status != PJ_SUCCESS) { 755 746 pjsua_perror(THIS_FILE, "Unable to create media session", … … 762 753 * We need the port interface to add to the conference bridge. 763 754 */ 764 pjmedia_session_get_port( inv_data->session, 0, &media_port);755 pjmedia_session_get_port(call->session, 0, &media_port); 765 756 766 757 … … 770 761 port_name.ptr = tmp; 771 762 port_name.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, 772 inv_data->inv->dlg->remote.info->uri,763 call->inv->dlg->remote.info->uri, 773 764 tmp, sizeof(tmp)); 774 765 if (port_name.slen < 1) { 775 766 port_name = pj_str("call"); 776 767 } 777 status = pjmedia_conf_add_port( pjsua.mconf, inv->pool,768 status = pjmedia_conf_add_port( pjsua.mconf, call->inv->pool, 778 769 media_port, 779 770 &port_name, 780 & inv_data->conf_slot);771 &call->conf_slot); 781 772 if (status != PJ_SUCCESS) { 782 773 pjsua_perror(THIS_FILE, "Unable to create conference slot", 783 774 status); 784 pjmedia_session_destroy( inv_data->session);785 inv_data->session = NULL;775 pjmedia_session_destroy(call->session); 776 call->session = NULL; 786 777 return; 787 778 } … … 790 781 * port 791 782 */ 792 if (pjsua.wav_file && inv->role == PJSIP_ROLE_UAS) { 783 if (pjsua.auto_play && pjsua.wav_file && 784 call->inv->role == PJSIP_ROLE_UAS) 785 { 793 786 794 787 pjmedia_conf_connect_port( pjsua.mconf, pjsua.wav_slot, 795 inv_data->conf_slot); 788 call->conf_slot); 789 790 } else if (pjsua.auto_loop && call->inv->role == PJSIP_ROLE_UAS) { 791 792 pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 793 call->conf_slot); 794 795 } else if (pjsua.auto_conf) { 796 797 int i; 798 799 pjmedia_conf_connect_port( pjsua.mconf, 0, call->conf_slot); 800 pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 0); 801 802 for (i=0; i < pjsua.max_calls; ++i) { 803 804 if (!pjsua.calls[i].session) 805 continue; 806 807 pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 808 pjsua.calls[i].conf_slot); 809 pjmedia_conf_connect_port( pjsua.mconf, pjsua.calls[i].conf_slot, 810 call->conf_slot); 811 } 796 812 797 813 } else { … … 800 816 * main conference bridge. 801 817 */ 802 pjmedia_conf_connect_port( pjsua.mconf, 0, inv_data->conf_slot);803 pjmedia_conf_connect_port( pjsua.mconf, inv_data->conf_slot, 0);818 pjmedia_conf_connect_port( pjsua.mconf, 0, call->conf_slot); 819 pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 0); 804 820 } 805 821 … … 812 828 unsigned i; 813 829 814 pjmedia_session_get_info( inv_data->session, &sess_info);830 pjmedia_session_get_info(call->session, &sess_info); 815 831 for (i=0; i<sess_info.stream_cnt; ++i) { 816 832 int len; … … 851 867 * Hangup call. 852 868 */ 853 void pjsua_inv_hangup(struct pjsua_inv_data *inv_session, int code) 854 { 869 void pjsua_call_hangup(int call_index, int code) 870 { 871 pjsua_call *call; 855 872 pj_status_t status; 856 873 pjsip_tx_data *tdata; 857 874 858 status = pjsip_inv_end_session(inv_session->inv, 859 code, NULL, &tdata); 875 876 call = &pjsua.calls[call_index]; 877 878 if (!call->inv) { 879 PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 880 return; 881 } 882 883 status = pjsip_inv_end_session(call->inv, code, NULL, &tdata); 860 884 if (status != PJ_SUCCESS) { 861 885 pjsua_perror(THIS_FILE, … … 872 896 return; 873 897 874 status = pjsip_inv_send_msg( inv_session->inv, tdata, NULL);898 status = pjsip_inv_send_msg(call->inv, tdata, NULL); 875 899 if (status != PJ_SUCCESS) { 876 900 pjsua_perror(THIS_FILE, … … 885 909 * Put call on-Hold. 886 910 */ 887 void pjsua_ inv_set_hold(struct pjsua_inv_data *inv_session)911 void pjsua_call_set_hold(int call_index) 888 912 { 889 913 pjmedia_sdp_session *sdp; 890 pjs ip_inv_session *inv = inv_session->inv;914 pjsua_call *call; 891 915 pjsip_tx_data *tdata; 892 916 pj_status_t status; 893 917 894 if (inv->state != PJSIP_INV_STATE_CONFIRMED) { 918 call = &pjsua.calls[call_index]; 919 920 if (!call->inv) { 921 PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 922 return; 923 } 924 925 if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { 895 926 PJ_LOG(3,(THIS_FILE, "Can not hold call that is not confirmed")); 896 927 return; 897 928 } 898 929 899 status = create_inactive_sdp( inv_session, &sdp);930 status = create_inactive_sdp(call, &sdp); 900 931 if (status != PJ_SUCCESS) 901 932 return; 902 933 903 934 /* Send re-INVITE with new offer */ 904 status = pjsip_inv_reinvite( inv_session->inv, NULL, sdp, &tdata);935 status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata); 905 936 if (status != PJ_SUCCESS) { 906 937 pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); … … 908 939 } 909 940 910 status = pjsip_inv_send_msg( inv_session->inv, tdata, NULL);941 status = pjsip_inv_send_msg( call->inv, tdata, NULL); 911 942 if (status != PJ_SUCCESS) { 912 943 pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); … … 919 950 * re-INVITE. 920 951 */ 921 void pjsua_ inv_reinvite(struct pjsua_inv_data *inv_session)952 void pjsua_call_reinvite(int call_index) 922 953 { 923 954 pjmedia_sdp_session *sdp; 924 955 pjsip_tx_data *tdata; 925 pjs ip_inv_session *inv = inv_session->inv;956 pjsua_call *call; 926 957 pj_status_t status; 927 958 928 929 if (inv->state != PJSIP_INV_STATE_CONFIRMED) { 959 call = &pjsua.calls[call_index]; 960 961 if (!call->inv) { 962 PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 963 return; 964 } 965 966 967 if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { 930 968 PJ_LOG(3,(THIS_FILE, "Can not re-INVITE call that is not confirmed")); 931 969 return; … … 933 971 934 972 /* Create SDP */ 935 status = pjmedia_endpt_create_sdp( pjsua.med_endpt, inv->pool, 1,936 & pjsua.med_sock_info[inv_session->call_slot],937 &sdp); 938 if (status != PJ_SUCCESS) { 939 pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint",status);973 status = pjmedia_endpt_create_sdp( pjsua.med_endpt, call->inv->pool, 1, 974 &call->skinfo, &sdp); 975 if (status != PJ_SUCCESS) { 976 pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint", 977 status); 940 978 return; 941 979 } 942 980 943 981 /* Send re-INVITE with new offer */ 944 status = pjsip_inv_reinvite( inv_session->inv, NULL, sdp, &tdata);982 status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata); 945 983 if (status != PJ_SUCCESS) { 946 984 pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); … … 948 986 } 949 987 950 status = pjsip_inv_send_msg( inv_session->inv, tdata, NULL);988 status = pjsip_inv_send_msg( call->inv, tdata, NULL); 951 989 if (status != PJ_SUCCESS) { 952 990 pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); … … 959 997 * Transfer call. 960 998 */ 961 void pjsua_inv_xfer_call(struct pjsua_inv_data *inv_session, 962 const char *dest) 999 void pjsua_call_xfer(int call_index, const char *dest) 963 1000 { 964 1001 pjsip_evsub *sub; 965 1002 pjsip_tx_data *tdata; 1003 pjsua_call *call; 966 1004 pj_str_t tmp; 967 1005 pj_status_t status; 968 1006 969 1007 1008 call = &pjsua.calls[call_index]; 1009 1010 if (!call->inv) { 1011 PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 1012 return; 1013 } 1014 970 1015 /* Create xfer client subscription. 971 1016 * We're not interested in knowing the transfer result, so we 972 1017 * put NULL as the callback. 973 1018 */ 974 status = pjsip_xfer_create_uac( inv_session->inv->dlg, NULL, &sub);1019 status = pjsip_xfer_create_uac(call->inv->dlg, NULL, &sub); 975 1020 if (status != PJ_SUCCESS) { 976 1021 pjsua_perror(THIS_FILE, "Unable to create xfer", status); … … 1006 1051 void pjsua_inv_shutdown() 1007 1052 { 1008 struct pjsua_inv_data *inv_data, *next; 1009 1010 inv_data = pjsua.inv_list.next; 1011 while (inv_data != &pjsua.inv_list) { 1053 int i; 1054 1055 for (i=0; i<pjsua.max_calls; ++i) { 1012 1056 pjsip_tx_data *tdata; 1013 1014 next = inv_data->next; 1015 1016 if (pjsip_inv_end_session(inv_data->inv, 410, NULL, &tdata)==0) { 1057 pjsua_call *call; 1058 1059 if (pjsua.calls[i].inv == NULL) 1060 continue; 1061 1062 call = &pjsua.calls[i]; 1063 1064 if (pjsip_inv_end_session(call->inv, 410, NULL, &tdata)==0) { 1017 1065 if (tdata) 1018 pjsip_inv_send_msg( inv_data->inv, tdata, NULL);1066 pjsip_inv_send_msg(call->inv, tdata, NULL); 1019 1067 } 1020 1021 inv_data = next; 1022 } 1023 } 1024 1025 1068 } 1069 } 1070 1071 1072 pj_status_t pjsua_call_init(void) 1073 { 1074 /* Initialize invite session callback. */ 1075 pjsip_inv_callback inv_cb; 1076 pj_status_t status; 1077 1078 pj_memset(&inv_cb, 0, sizeof(inv_cb)); 1079 inv_cb.on_state_changed = &pjsua_call_on_state_changed; 1080 inv_cb.on_new_session = &pjsua_call_on_forked; 1081 inv_cb.on_media_update = &pjsua_call_on_media_update; 1082 inv_cb.on_rx_offer = &pjsua_call_on_rx_offer; 1083 inv_cb.on_tsx_state_changed = &pjsua_call_on_tsx_state_changed; 1084 1085 1086 /* Initialize invite session module: */ 1087 status = pjsip_inv_usage_init(pjsua.endpt, &pjsua.mod, &inv_cb); 1088 1089 return status; 1090 } -
pjproject/trunk/pjsip/src/pjsua/pjsua_core.c
r230 r236 46 46 void pjsua_default(void) 47 47 { 48 unsigned i; 49 48 50 49 51 /* Normally need another thread for console application, because main … … 54 56 55 57 /* Default transport settings: */ 56 57 58 pjsua.sip_port = 5060; 58 59 59 60 60 61 /* Default logging settings: */ 61 62 62 pjsua.log_level = 5; 63 63 pjsua.app_log_level = 4; … … 65 65 PJ_LOG_HAS_MICRO_SEC | PJ_LOG_HAS_NEWLINE; 66 66 67 67 68 /* Default: do not use STUN: */ 68 69 69 pjsua.stun_port1 = pjsua.stun_port2 = 0; 70 70 71 /* Default URIs: */ 72 73 pjsua.local_uri = pj_str(PJSUA_LOCAL_URI); 74 75 /* Default registration timeout: */ 76 77 pjsua.reg_timeout = 55; 78 79 /* Default maximum conference ports: */ 80 81 pjsua.max_ports = 8; 82 83 /* Init route set list: */ 84 85 pj_list_init(&pjsua.route_set); 86 87 /* Init invite session list: */ 88 89 pj_list_init(&pjsua.inv_list); 71 /* Init accounts: */ 72 pjsua.acc_cnt = 1; 73 for (i=0; i<PJ_ARRAY_SIZE(pjsua.acc); ++i) { 74 pjsua.acc[i].index = i; 75 pjsua.acc[i].local_uri = pj_str(PJSUA_LOCAL_URI); 76 pjsua.acc[i].reg_timeout = 55; 77 pj_list_init(&pjsua.acc[i].route_set); 78 pj_list_init(&pjsua.acc[i].pres_srv_list); 79 } 80 81 /* Init call array: */ 82 for (i=0; i<PJ_ARRAY_SIZE(pjsua.calls); ++i) 83 pjsua.calls[i].index = i; 84 85 /* Default max nb of calls. */ 86 pjsua.max_calls = 4; 90 87 91 88 /* Init server presence subscription list: */ 92 89 93 pj_list_init(&pjsua.pres_srv_list);94 90 95 91 } … … 111 107 if (rdata->msg_info.msg->line.req.method.id == PJSIP_INVITE_METHOD) { 112 108 113 return pjsua_inv_on_incoming(rdata); 114 109 return pjsua_call_on_incoming(rdata); 115 110 } 116 111 … … 146 141 RTP_START_PORT = 4000, 147 142 RTP_RANDOM_START = 2, 148 RTP_RETRY = 20143 RTP_RETRY = 100 149 144 }; 150 145 enum { … … 241 236 pj_memcpy(&mapped_addr[i], &addr, sizeof(addr)); 242 237 243 if (sip) 244 mapped_addr[SIP_SOCK].sin_port = pj_htons((pj_uint16_t)pjsua.sip_port); 245 mapped_addr[RTP_SOCK].sin_port = pj_htons((pj_uint16_t)rtp_port); 246 mapped_addr[RTCP_SOCK].sin_port = pj_htons((pj_uint16_t)(rtp_port+1)); 238 if (sip) { 239 mapped_addr[SIP_SOCK].sin_port = 240 pj_htons((pj_uint16_t)pjsua.sip_port); 241 } 242 mapped_addr[RTP_SOCK].sin_port=pj_htons((pj_uint16_t)rtp_port); 243 mapped_addr[RTCP_SOCK].sin_port=pj_htons((pj_uint16_t)(rtp_port+1)); 247 244 break; 245 248 246 } else { 249 status = pj_stun_get_mapped_addr(&pjsua.cp.factory, 3, sock,250 251 252 247 status=pj_stun_get_mapped_addr(&pjsua.cp.factory, 3, sock, 248 &pjsua.stun_srv1, pjsua.stun_port1, 249 &pjsua.stun_srv2, pjsua.stun_port2, 250 mapped_addr); 253 251 if (status != PJ_SUCCESS) { 254 252 pjsua_perror(THIS_FILE, "STUN error", status); … … 256 254 } 257 255 258 if (pj_ntohs(mapped_addr[2].sin_port) == pj_ntohs(mapped_addr[1].sin_port)+1) 256 if (pj_ntohs(mapped_addr[2].sin_port) == 257 pj_ntohs(mapped_addr[1].sin_port)+1) 258 { 259 259 break; 260 261 pj_sock_close(sock[RTP_SOCK]); sock[RTP_SOCK] = PJ_INVALID_SOCKET; 262 pj_sock_close(sock[RTCP_SOCK]); sock[RTCP_SOCK] = PJ_INVALID_SOCKET; 260 } 261 262 pj_sock_close(sock[RTP_SOCK]); 263 sock[RTP_SOCK] = PJ_INVALID_SOCKET; 264 265 pj_sock_close(sock[RTCP_SOCK]); 266 sock[RTCP_SOCK] = PJ_INVALID_SOCKET; 263 267 } 264 268 } 265 269 266 270 if (sock[RTP_SOCK] == PJ_INVALID_SOCKET) { 267 PJ_LOG(1,(THIS_FILE, "Unable to find appropriate RTP/RTCP ports combination")); 271 PJ_LOG(1,(THIS_FILE, 272 "Unable to find appropriate RTP/RTCP ports combination")); 268 273 goto on_error; 269 274 } … … 271 276 if (sip) { 272 277 pjsua.sip_sock = sock[SIP_SOCK]; 273 pj_memcpy(&pjsua.sip_sock_name, &mapped_addr[SIP_SOCK], sizeof(pj_sockaddr_in)); 278 pj_memcpy(&pjsua.sip_sock_name, 279 &mapped_addr[SIP_SOCK], 280 sizeof(pj_sockaddr_in)); 274 281 } else { 275 282 pj_sock_close(sock[0]); … … 392 399 /* Initialize invite session module: */ 393 400 394 { 395 396 /* Initialize invite session callback. */ 397 pjsip_inv_callback inv_cb; 398 399 pj_memset(&inv_cb, 0, sizeof(inv_cb)); 400 inv_cb.on_state_changed = &pjsua_inv_on_state_changed; 401 inv_cb.on_new_session = &pjsua_inv_on_new_session; 402 inv_cb.on_media_update = &pjsua_inv_on_media_update; 403 inv_cb.on_rx_offer = &pjsua_inv_on_rx_offer; 404 inv_cb.on_tsx_state_changed = &pjsua_inv_on_tsx_state_changed; 405 406 407 /* Initialize invite session module: */ 408 status = pjsip_inv_usage_init(pjsua.endpt, &pjsua.mod, &inv_cb); 409 if (status != PJ_SUCCESS) { 410 pjsua_perror(THIS_FILE, "Invite usage initialization error", 411 status); 412 goto on_error; 413 } 414 415 } 416 401 status = pjsua_call_init(); 402 if (status != PJ_SUCCESS) { 403 pjsua_perror(THIS_FILE, "Invite usage initialization error", 404 status); 405 goto on_error; 406 } 417 407 418 408 /* Done */ … … 521 511 /* Init conference bridge. */ 522 512 523 status = pjmedia_conf_create(pjsua.pool, pjsua.max_ports, 513 status = pjmedia_conf_create(pjsua.pool, 514 pjsua.max_calls+PJSUA_CONF_MORE_PORTS, 524 515 8000, 160, 16, &pjsua.mconf); 525 516 if (status != PJ_SUCCESS) { … … 548 539 549 540 541 /* 542 * Find account for incoming request. 543 */ 544 int pjsua_find_account_for_incoming(pjsip_rx_data *rdata) 545 { 546 pjsip_uri *uri; 547 pjsip_sip_uri *sip_uri; 548 int acc_index; 549 550 uri = rdata->msg_info.to->uri; 551 552 /* Just return account #0 if To URI is not SIP: */ 553 if (!PJSIP_URI_SCHEME_IS_SIP(uri) && 554 !PJSIP_URI_SCHEME_IS_SIPS(uri)) 555 { 556 return 0; 557 } 558 559 560 sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(uri); 561 562 /* Find account which has matching username and domain. */ 563 for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) { 564 565 pjsua_acc *acc = &pjsua.acc[acc_index]; 566 567 if (pj_stricmp(&acc->user_part, &sip_uri->user)==0 && 568 pj_stricmp(&acc->host_part, &sip_uri->host)==0) 569 { 570 /* Match ! */ 571 return acc_index; 572 } 573 } 574 575 /* No matching, try match domain part only. */ 576 for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) { 577 578 pjsua_acc *acc = &pjsua.acc[acc_index]; 579 580 if (pj_stricmp(&acc->host_part, &sip_uri->host)==0) { 581 /* Match ! */ 582 return acc_index; 583 } 584 } 585 586 /* Still no match, just return account #0 */ 587 return 0; 588 } 589 590 591 /* 592 * Find account for outgoing request. 593 */ 594 int pjsua_find_account_for_outgoing(const pj_str_t *url) 595 { 596 PJ_UNUSED_ARG(url); 597 598 /* Just use account #0 */ 599 return 0; 600 } 601 550 602 551 603 /* … … 589 641 590 642 /* Init sockets (STUN etc): */ 591 for (i=0; i< PJ_ARRAY_SIZE(pjsua.med_sock_info); ++i) {592 status = init_sockets(i==0, &pjsua. med_sock_info[i]);643 for (i=0; i<(int)pjsua.max_calls; ++i) { 644 status = init_sockets(i==0, &pjsua.calls[i].skinfo); 593 645 if (status != PJ_SUCCESS) { 594 646 pjsua_perror(THIS_FILE, "init_sockets() has returned error", 595 647 status); 648 --i; 649 if (i >= 0) 650 pj_sock_close(pjsua.sip_sock); 651 while (i >= 0) { 652 pj_sock_close(pjsua.calls[i].skinfo.rtp_sock); 653 pj_sock_close(pjsua.calls[i].skinfo.rtcp_sock); 654 } 596 655 return status; 597 656 } … … 624 683 625 684 /* Initialize Contact URI, if one is not specified: */ 626 627 if (pjsua.contact_uri.slen == 0 && pjsua.local_uri.slen) { 685 for (i=0; i<pjsua.acc_cnt; ++i) { 628 686 629 687 pjsip_uri *uri; 630 688 pjsip_sip_uri *sip_uri; 631 char contact[128]; 632 int len; 633 634 /* The local Contact is the username@ip-addr, where 635 * - username is taken from the local URI, 636 * - ip-addr in UDP transport's address name (which may have been 637 * resolved from STUN. 638 */ 639 689 640 690 /* Need to parse local_uri to get the elements: */ 641 691 642 uri = pjsip_parse_uri(pjsua.pool, pjsua. local_uri.ptr,643 pjsua. local_uri.slen, 0);692 uri = pjsip_parse_uri(pjsua.pool, pjsua.acc[i].local_uri.ptr, 693 pjsua.acc[i].local_uri.slen, 0); 644 694 if (uri == NULL) { 645 695 pjsua_perror(THIS_FILE, "Invalid local URI", … … 648 698 } 649 699 650 651 700 /* Local URI MUST be a SIP or SIPS: */ 652 701 653 if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) { 702 if (!PJSIP_URI_SCHEME_IS_SIP(uri) && 703 !PJSIP_URI_SCHEME_IS_SIPS(uri)) 704 { 654 705 pjsua_perror(THIS_FILE, "Invalid local URI", 655 706 PJSIP_EINVALIDSCHEME); … … 662 713 sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(uri); 663 714 664 665 /* Build temporary contact string. */ 666 667 if (sip_uri->user.slen) { 668 669 /* With the user part. */ 670 len = pj_snprintf(contact, sizeof(contact), 671 "<sip:%.*s@%.*s:%d>", 672 (int)sip_uri->user.slen, 673 sip_uri->user.ptr, 674 (int)udp_transport->local_name.host.slen, 675 udp_transport->local_name.host.ptr, 676 udp_transport->local_name.port); 677 } else { 678 679 /* Without user part */ 680 681 len = pj_snprintf(contact, sizeof(contact), 682 "<sip:%.*s:%d>", 683 (int)udp_transport->local_name.host.slen, 684 udp_transport->local_name.host.ptr, 685 udp_transport->local_name.port); 686 } 687 688 if (len < 1 || len >= sizeof(contact)) { 689 pjsua_perror(THIS_FILE, "Invalid Contact", PJSIP_EURITOOLONG); 690 return PJSIP_EURITOOLONG; 691 } 692 693 /* Duplicate Contact uri. */ 694 695 pj_strdup2(pjsua.pool, &pjsua.contact_uri, contact); 696 715 pjsua.acc[i].user_part = sip_uri->user; 716 pjsua.acc[i].host_part = sip_uri->host; 717 718 if (pjsua.acc[i].contact_uri.slen == 0 && 719 pjsua.acc[i].local_uri.slen) 720 { 721 char contact[128]; 722 int len; 723 724 /* The local Contact is the username@ip-addr, where 725 * - username is taken from the local URI, 726 * - ip-addr in UDP transport's address name (which may have been 727 * resolved from STUN. 728 */ 729 730 /* Build temporary contact string. */ 731 732 if (sip_uri->user.slen) { 733 734 /* With the user part. */ 735 len = pj_snprintf(contact, sizeof(contact), 736 "<sip:%.*s@%.*s:%d>", 737 (int)sip_uri->user.slen, 738 sip_uri->user.ptr, 739 (int)udp_transport->local_name.host.slen, 740 udp_transport->local_name.host.ptr, 741 udp_transport->local_name.port); 742 } else { 743 744 /* Without user part */ 745 746 len = pj_snprintf(contact, sizeof(contact), 747 "<sip:%.*s:%d>", 748 (int)udp_transport->local_name.host.slen, 749 udp_transport->local_name.host.ptr, 750 udp_transport->local_name.port); 751 } 752 753 if (len < 1 || len >= sizeof(contact)) { 754 pjsua_perror(THIS_FILE, "Invalid Contact", PJSIP_EURITOOLONG); 755 return PJSIP_EURITOOLONG; 756 } 757 758 /* Duplicate Contact uri. */ 759 760 pj_strdup2(pjsua.pool, &pjsua.acc[i].contact_uri, contact); 761 762 } 697 763 } 698 764 … … 715 781 } 716 782 717 pj_list_push_back(&pjsua.route_set, route); 783 for (i=0; i<pjsua.acc_cnt; ++i) { 784 pj_list_push_front(&pjsua.acc[i].route_set, route); 785 } 718 786 } 719 787 … … 737 805 738 806 /* Create client registration session: */ 739 740 status = pjsua_regc_init(); 741 if (status != PJ_SUCCESS) 742 return status; 743 744 /* Perform registration, if required. */ 745 if (pjsua.regc) { 746 pjsua_regc_update(1); 807 for (i=0; i<pjsua.acc_cnt; ++i) { 808 status = pjsua_regc_init(i); 809 if (status != PJ_SUCCESS) 810 return status; 811 812 /* Perform registration, if required. */ 813 if (pjsua.acc[i].regc) { 814 pjsua_regc_update(i, 1); 815 } 816 } 817 818 819 /* Find account for outgoing preence subscription */ 820 for (i=0; i<pjsua.buddy_cnt; ++i) { 821 pjsua.buddies[i].acc_index = 822 pjsua_find_account_for_outgoing(&pjsua.buddies[i].uri); 747 823 } 748 824 … … 777 853 /* Signal threads to quit: */ 778 854 pjsua.quit_flag = 1; 855 856 /* Terminate all calls. */ 857 pjsua_inv_shutdown(); 858 859 /* Terminate all presence subscriptions. */ 860 pjsua_pres_shutdown(); 861 862 /* Unregister, if required: */ 863 for (i=0; i<pjsua.acc_cnt; ++i) { 864 if (pjsua.acc[i].regc) { 865 pjsua_regc_update(i, 0); 866 } 867 } 779 868 780 869 /* Wait worker threads to quit: */ … … 789 878 790 879 791 /* Terminate all calls. */792 pjsua_inv_shutdown();793 794 /* Terminate all presence subscriptions. */795 pjsua_pres_shutdown();796 797 /* Unregister, if required: */798 if (pjsua.regc) {799 pjsua_regc_update(0);800 }801 802 880 /* Wait for some time to allow unregistration to complete: */ 803 881 PJ_LOG(4,(THIS_FILE, "Shutting down...")); -
pjproject/trunk/pjsip/src/pjsua/pjsua_opt.c
r223 r236 44 44 puts(" pjsua [options]"); 45 45 puts(""); 46 puts(" [sip-url] Default URL to invite.");47 puts("");48 46 puts("General options:"); 49 47 puts(" --help Display this help screen"); … … 56 54 puts(" --app-log-level=N Set log max level for stdout display to N"); 57 55 puts(""); 56 puts("SIP Account options:"); 57 puts(" --id=url Set the URL of local ID (used in From header)"); 58 puts(" --contact=url Override the Contact information"); 59 puts(" --proxy=url Set the URL of proxy server"); 60 puts(""); 61 puts("SIP Account Registration Options:"); 62 puts(" --registrar=url Set the URL of registrar server"); 63 puts(" --reg-timeout=secs Set registration interval to secs (default 3600)"); 64 puts(""); 65 puts("SIP Account Control:"); 66 puts(" --next-account Add more account"); 67 puts(""); 58 68 puts("Authentication options:"); 59 69 puts(" --realm=string Set realm"); 60 70 puts(" --username=string Set authentication username"); 61 71 puts(" --password=string Set authentication password"); 62 puts(""); 63 puts("SIP options:"); 64 puts(" --id=url Set the URL of local ID (used in From header)"); 65 puts(" --contact=url Override the Contact information"); 66 puts(" --proxy=url Set the URL of proxy server"); 67 //puts(" --outbound=url Set the URL of outbound proxy server"); 68 puts(""); 69 puts("Registration Options:"); 70 puts(" --registrar=url Set the URL of registrar server"); 71 puts(" --reg-timeout=secs Set registration interval to secs (default 3600)"); 72 puts(" --next-cred Add more credential"); 72 73 puts(""); 73 74 puts("Transport Options:"); 74 puts(" --local-port=port Set TCP/UDP port"); 75 puts(" --local-port=port Set TCP/UDP port"); 76 puts(" --outbound=url Set the URL of outbound proxy server"); 75 77 puts(" --use-stun1=host[:port]"); 76 puts(" --use-stun2=host[:port] Use STUN and set host name and port ofSTUN servers");78 puts(" --use-stun2=host[:port] Resolve local IP with the specified STUN servers"); 77 79 puts(""); 78 80 puts("Media Options:"); 79 81 puts(" --null-audio Use NULL audio device"); 80 //puts(" --wav-file=file Play WAV file in conference bridge"); 82 puts(" --play-file=file Play WAV file in conference bridge"); 83 puts(" --auto-play Automatically play the file (to incoming calls only)"); 84 puts(" --auto-loop Automatically loop incoming RTP to outgoing RTP"); 85 puts(" --auto-conf Automatically put incoming calls to conference"); 81 86 puts(""); 82 87 puts("Buddy List (can be more than one):"); … … 85 90 puts("User Agent options:"); 86 91 puts(" --auto-answer=code Automatically answer incoming calls with code (e.g. 200)"); 87 puts(" -- auto-play=file Automatically play WAVE file to incoming calls");92 puts(" --max-calls=N Maximum number of concurrent calls (default:4, max:255)"); 88 93 puts(""); 89 94 fflush(stdout); … … 200 205 OPT_USE_STUN1, OPT_USE_STUN2, 201 206 OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE, 202 OPT_AUTO_ANSWER, OPT_AUTO_HANGUP, OPT_AUTO_PLAY}; 207 OPT_AUTO_ANSWER, OPT_AUTO_HANGUP, OPT_AUTO_PLAY, OPT_AUTO_LOOP, 208 OPT_AUTO_CONF, 209 OPT_PLAY_FILE, 210 OPT_NEXT_ACCOUNT, OPT_NEXT_CRED, OPT_MAX_CALLS, 211 }; 203 212 struct option long_options[] = { 204 213 { "config-file",1, 0, OPT_CONFIG_FILE}, … … 226 235 { "auto-answer",1, 0, OPT_AUTO_ANSWER}, 227 236 { "auto-hangup",1, 0, OPT_AUTO_HANGUP}, 228 { "auto-play", 1, 0, OPT_AUTO_PLAY}, 237 { "auto-play", 0, 0, OPT_AUTO_PLAY}, 238 { "auto-loop", 0, 0, OPT_AUTO_LOOP}, 239 { "auto-conf", 0, 0, OPT_AUTO_CONF}, 240 { "play-file", 1, 0, OPT_PLAY_FILE}, 241 { "next-account",0,0, OPT_NEXT_ACCOUNT}, 242 { "next-cred", 0, 0, OPT_NEXT_CRED}, 243 { "max-calls", 1, 0, OPT_MAX_CALLS}, 229 244 { NULL, 0, 0, 0} 230 245 }; 231 246 pj_status_t status; 247 pjsua_acc *cur_acc; 248 pjsip_cred_info *cur_cred; 232 249 char *config_file = NULL; 233 250 … … 248 265 return status; 249 266 } 267 268 269 cur_acc = &pjsua.acc[0]; 270 cur_cred = &pjsua.cred_info[0]; 250 271 251 272 … … 308 329 return PJ_EINVAL; 309 330 } 310 pjsua.proxy = pj_str(optarg);331 cur_acc->proxy = pj_str(optarg); 311 332 break; 312 333 … … 324 345 return PJ_EINVAL; 325 346 } 326 pjsua.registrar_uri = pj_str(optarg);347 cur_acc->reg_uri = pj_str(optarg); 327 348 break; 328 349 329 350 case OPT_REG_TIMEOUT: /* reg-timeout */ 330 pjsua.reg_timeout = pj_strtoul(pj_cstr(&tmp,optarg));331 if ( pjsua.reg_timeout < 1 || pjsua.reg_timeout > 3600) {351 cur_acc->reg_timeout = pj_strtoul(pj_cstr(&tmp,optarg)); 352 if (cur_acc->reg_timeout < 1 || cur_acc->reg_timeout > 3600) { 332 353 printf("Error: invalid value for --reg-timeout (expecting 1-3600)\n"); 333 354 return PJ_EINVAL; … … 340 361 return PJ_EINVAL; 341 362 } 342 pjsua.local_uri = pj_str(optarg);363 cur_acc->local_uri = pj_str(optarg); 343 364 break; 344 365 … … 348 369 return PJ_EINVAL; 349 370 } 350 pjsua.contact_uri = pj_str(optarg); 371 cur_acc->contact_uri = pj_str(optarg); 372 break; 373 374 case OPT_NEXT_ACCOUNT: /* Add more account. */ 375 pjsua.acc_cnt++; 376 cur_acc = &pjsua.acc[pjsua.acc_cnt - 1]; 351 377 break; 352 378 353 379 case OPT_USERNAME: /* Default authentication user */ 354 if ( !pjsua.cred_count) pjsua.cred_count =1;355 pjsua.cred_info[0].username = pj_str(optarg);380 if (pjsua.cred_count==0) pjsua.cred_count=1; 381 cur_cred->username = pj_str(optarg); 356 382 break; 357 383 358 384 case OPT_REALM: /* Default authentication realm. */ 359 if ( !pjsua.cred_count) pjsua.cred_count =1;360 pjsua.cred_info[0].realm = pj_str(optarg);385 if (pjsua.cred_count==0) pjsua.cred_count=1; 386 cur_cred->realm = pj_str(optarg); 361 387 break; 362 388 363 389 case OPT_PASSWORD: /* authentication password */ 364 if (!pjsua.cred_count) pjsua.cred_count = 1; 365 pjsua.cred_info[0].data_type = 0; 366 pjsua.cred_info[0].data = pj_str(optarg); 390 if (pjsua.cred_count==0) pjsua.cred_count=1; 391 cur_cred->data_type = 0; 392 cur_cred->data = pj_str(optarg); 393 break; 394 395 case OPT_NEXT_CRED: /* Next credential */ 396 pjsua.cred_count++; 397 cur_cred = &pjsua.cred_info[pjsua.cred_count - 1]; 367 398 break; 368 399 … … 412 443 413 444 case OPT_AUTO_PLAY: 445 pjsua.auto_play = 1; 446 break; 447 448 case OPT_AUTO_LOOP: 449 pjsua.auto_loop = 1; 450 break; 451 452 case OPT_AUTO_CONF: 453 pjsua.auto_conf = 1; 454 break; 455 456 case OPT_PLAY_FILE: 414 457 pjsua.wav_file = optarg; 415 458 break; … … 422 465 } 423 466 break; 467 468 case OPT_MAX_CALLS: 469 pjsua.max_calls = atoi(optarg); 470 if (pjsua.max_calls < 1 || pjsua.max_calls > 255) { 471 puts("Too many calls for max-calls (1-255)"); 472 return -1; 473 } 474 break; 424 475 } 425 476 } … … 430 481 } 431 482 432 if (pjsua.reg_timeout == 0)433 pjsua.reg_timeout = 3600;434 435 436 483 return PJ_SUCCESS; 437 484 } … … 439 486 440 487 441 static void print_ invite_session(const char *title,442 struct pjsua_inv_data *inv_data,443 488 static void print_call(const char *title, 489 int call_index, 490 char *buf, pj_size_t size) 444 491 { 445 492 int len; 446 pjsip_inv_session *inv = inv_data->inv;493 pjsip_inv_session *inv = pjsua.calls[call_index].inv; 447 494 pjsip_dialog *dlg = inv->dlg; 448 495 char userinfo[128]; … … 516 563 void pjsua_dump(void) 517 564 { 518 struct pjsua_inv_data *inv_data;519 565 char buf[128]; 520 566 unsigned old_decor; … … 534 580 PJ_LOG(3,(THIS_FILE, "Dumping invite sessions:")); 535 581 536 if (pj _list_empty(&pjsua.inv_list)) {582 if (pjsua.call_cnt == 0) { 537 583 538 584 PJ_LOG(3,(THIS_FILE, " - no sessions -")); 539 585 540 586 } else { 541 542 inv_data = pjsua.inv_list.next; 543 544 while (inv_data != &pjsua.inv_list) { 545 546 print_invite_session(" ", inv_data, buf, sizeof(buf)); 587 int i; 588 589 for (i=0; i<pjsua.max_calls; ++i) { 590 591 if (pjsua.calls[i].inv == NULL) 592 continue; 593 594 print_call(" ", i, buf, sizeof(buf)); 547 595 PJ_LOG(3,(THIS_FILE, "%s", buf)); 548 596 549 if (inv_data->session) 550 dump_media_session(inv_data->session); 551 552 inv_data = inv_data->next; 597 if (pjsua.calls[i].session) 598 dump_media_session(pjsua.calls[i].session); 553 599 } 554 600 } … … 576 622 577 623 /* 578 * Save settings.624 * Save account settings 579 625 */ 580 pj_status_t pjsua_save_settings(const char *filename) 581 { 582 unsigned i; 626 static void save_account_settings(int acc_index, pj_str_t *result) 627 { 628 char line[128]; 629 pjsua_acc *acc = &pjsua.acc[acc_index]; 630 631 632 pj_ansi_sprintf(line, "#\n# Account %d:\n#\n", acc_index); 633 pj_strcat2(result, line); 634 635 636 /* Identity */ 637 if (acc->local_uri.slen) { 638 pj_ansi_sprintf(line, "--id %.*s\n", 639 (int)acc->local_uri.slen, 640 acc->local_uri.ptr); 641 pj_strcat2(result, line); 642 } 643 644 /* Registrar server */ 645 if (acc->reg_uri.slen) { 646 pj_ansi_sprintf(line, "--registrar %.*s\n", 647 (int)acc->reg_uri.slen, 648 acc->reg_uri.ptr); 649 pj_strcat2(result, line); 650 651 pj_ansi_sprintf(line, "--reg-timeout %u\n", 652 acc->reg_timeout); 653 pj_strcat2(result, line); 654 } 655 656 657 /* Proxy */ 658 if (acc->proxy.slen) { 659 pj_ansi_sprintf(line, "--proxy %.*s\n", 660 (int)acc->proxy.slen, 661 acc->proxy.ptr); 662 pj_strcat2(result, line); 663 } 664 } 665 666 667 668 /* 669 * Dump settings. 670 */ 671 int pjsua_dump_settings(char *buf, pj_size_t max) 672 { 673 int acc_index; 674 int i; 583 675 pj_str_t cfg; 584 676 char line[128]; 585 pj_pool_t *pool; 586 FILE *fhnd; 587 588 /* Create pool for temporary buffer. */ 589 pool = pj_pool_create(&pjsua.cp.factory, "settings", 4000, 0, NULL); 590 if (!pool) 591 return PJ_ENOMEM; 592 593 594 cfg.ptr = pj_pool_alloc(pool, 3800); 595 if (!cfg.ptr) { 596 pj_pool_release(pool); 597 return PJ_EBUG; 598 } 677 678 cfg.ptr = buf; 599 679 cfg.slen = 0; 600 680 601 681 602 /* Identity */ 603 if (pjsua.local_uri.slen) { 604 pj_ansi_sprintf(line, "--id %.*s\n", 605 (int)pjsua.local_uri.slen, 606 pjsua.local_uri.ptr); 607 pj_strcat2(&cfg, line); 682 /* Logging. */ 683 pj_strcat2(&cfg, "#\n# Logging options:\n#\n"); 684 pj_ansi_sprintf(line, "--log-level %d\n", 685 pjsua.log_level); 686 pj_strcat2(&cfg, line); 687 688 pj_ansi_sprintf(line, "--app-log-level %d\n", 689 pjsua.app_log_level); 690 pj_strcat2(&cfg, line); 691 692 if (pjsua.log_filename) { 693 pj_ansi_sprintf(line, "--log-file %s\n", 694 pjsua.log_filename); 695 pj_strcat2(&cfg, line); 696 } 697 698 699 /* Save account settings. */ 700 for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) { 701 702 save_account_settings(acc_index, &cfg); 703 704 if (acc_index < pjsua.acc_cnt-1) 705 pj_strcat2(&cfg, "--next-account\n"); 608 706 } 609 707 610 708 /* Credentials. */ 611 709 for (i=0; i<pjsua.cred_count; ++i) { 710 711 pj_ansi_sprintf(line, "#\n# Credential %d:\n#\n", i); 712 pj_strcat2(&cfg, line); 713 612 714 if (pjsua.cred_info[i].realm.slen) { 613 715 pj_ansi_sprintf(line, "--realm %.*s\n", … … 626 728 pjsua.cred_info[i].data.ptr); 627 729 pj_strcat2(&cfg, line); 628 } 629 630 /* Registrar server */ 631 if (pjsua.registrar_uri.slen) { 632 pj_ansi_sprintf(line, "--registrar %.*s\n", 633 (int)pjsua.registrar_uri.slen, 634 pjsua.registrar_uri.ptr); 635 pj_strcat2(&cfg, line); 636 } 637 730 731 if (i < pjsua.cred_count-1) 732 pj_strcat2(&cfg, "--next-cred\n"); 733 } 734 735 736 pj_strcat2(&cfg, "#\n# Network settings:\n#\n"); 638 737 639 738 /* Outbound proxy */ … … 644 743 pj_strcat2(&cfg, line); 645 744 } 646 647 /* Media */648 if (pjsua.null_audio)649 pj_strcat2(&cfg, "--null-audio\n");650 745 651 746 … … 673 768 674 769 770 pj_strcat2(&cfg, "#\n# Media settings:\n#\n"); 771 772 773 /* Media */ 774 if (pjsua.null_audio) 775 pj_strcat2(&cfg, "--null-audio\n"); 776 if (pjsua.auto_play) 777 pj_strcat2(&cfg, "--auto-play\n"); 778 if (pjsua.auto_loop) 779 pj_strcat2(&cfg, "--auto-loop\n"); 780 if (pjsua.auto_conf) 781 pj_strcat2(&cfg, "--auto-conf\n"); 782 if (pjsua.wav_file) { 783 pj_ansi_sprintf(line, "--play-file %s\n", 784 pjsua.wav_file); 785 pj_strcat2(&cfg, line); 786 } 787 788 789 pj_strcat2(&cfg, "#\n# User agent:\n#\n"); 790 791 /* Auto-answer. */ 792 if (pjsua.auto_answer != 0) { 793 pj_ansi_sprintf(line, "--auto-answer %d\n", 794 pjsua.auto_answer); 795 pj_strcat2(&cfg, line); 796 } 797 798 /* Max calls. */ 799 pj_ansi_sprintf(line, "--max-calls %d\n", 800 pjsua.max_calls); 801 pj_strcat2(&cfg, line); 802 803 804 pj_strcat2(&cfg, "#\n# Buddies:\n#\n"); 805 675 806 /* Add buddies. */ 676 807 for (i=0; i<pjsua.buddy_cnt; ++i) { … … 682 813 683 814 815 *(cfg.ptr + cfg.slen) = '\0'; 816 return cfg.slen; 817 } 818 819 /* 820 * Save settings. 821 */ 822 pj_status_t pjsua_save_settings(const char *filename) 823 { 824 pj_str_t cfg; 825 pj_pool_t *pool; 826 FILE *fhnd; 827 828 /* Create pool for temporary buffer. */ 829 pool = pj_pool_create(&pjsua.cp.factory, "settings", 4000, 0, NULL); 830 if (!pool) 831 return PJ_ENOMEM; 832 833 834 cfg.ptr = pj_pool_alloc(pool, 3800); 835 if (!cfg.ptr) { 836 pj_pool_release(pool); 837 return PJ_EBUG; 838 } 839 840 841 cfg.slen = pjsua_dump_settings(cfg.ptr, 3800); 842 if (cfg.slen < 1) { 843 pj_pool_release(pool); 844 return PJ_ENOMEM; 845 } 846 847 684 848 /* Write to file. */ 685 849 fhnd = fopen(filename, "wt"); -
pjproject/trunk/pjsip/src/pjsua/pjsua_pres.c
r230 r236 80 80 static pj_bool_t pres_on_rx_request(pjsip_rx_data *rdata) 81 81 { 82 int acc_index; 82 83 pjsip_method *req_method = &rdata->msg_info.msg->line.req.method; 83 84 pjsua_srv_pres *uapres; … … 94 95 /* Incoming SUBSCRIBE: */ 95 96 97 /* Find which account for the incoming request. */ 98 acc_index = pjsua_find_account_for_incoming(rdata); 99 96 100 /* Create UAS dialog: */ 97 101 status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata, 98 &pjsua.contact_uri, &dlg); 102 &pjsua.acc[acc_index].contact_uri, 103 &dlg); 99 104 if (status != PJ_SUCCESS) { 100 105 pjsua_perror(THIS_FILE, … … 131 136 132 137 /* Add server subscription to the list: */ 133 pj_list_push_back(&pjsua. pres_srv_list, uapres);138 pj_list_push_back(&pjsua.acc[acc_index].pres_srv_list, uapres); 134 139 135 140 … … 147 152 pj_memset(&pres_status, 0, sizeof(pres_status)); 148 153 pres_status.info_cnt = 1; 149 pres_status.info[0].basic_open = pjsua. online_status;154 pres_status.info[0].basic_open = pjsua.acc[acc_index].online_status; 150 155 //Both pjsua.local_uri and pjsua.contact_uri are enclosed in "<" and ">" 151 156 //causing XML parsing to fail. … … 175 180 176 181 /* Refresh subscription (e.g. when our online status has changed) */ 177 static void refresh_server_subscription( )182 static void refresh_server_subscription(int acc_index) 178 183 { 179 184 pjsua_srv_pres *uapres; 180 185 181 uapres = pjsua. pres_srv_list.next;182 183 while (uapres != &pjsua. pres_srv_list) {186 uapres = pjsua.acc[acc_index].pres_srv_list.next; 187 188 while (uapres != &pjsua.acc[acc_index].pres_srv_list) { 184 189 185 190 pjsip_pres_status pres_status; … … 187 192 188 193 pjsip_pres_get_status(uapres->sub, &pres_status); 189 if (pres_status.info[0].basic_open != pjsua. online_status) {190 pres_status.info[0].basic_open = pjsua. online_status;194 if (pres_status.info[0].basic_open != pjsua.acc[acc_index].online_status) { 195 pres_status.info[0].basic_open = pjsua.acc[acc_index].online_status; 191 196 pjsip_pres_set_status(uapres->sub, &pres_status); 192 197 … … 299 304 static void subscribe_buddy_presence(unsigned index) 300 305 { 306 int acc_index; 301 307 pjsip_dialog *dlg; 302 308 pjsip_tx_data *tdata; 303 309 pj_status_t status; 304 310 311 acc_index = pjsua.buddies[index].acc_index; 312 305 313 status = pjsip_dlg_create_uac( pjsip_ua_instance(), 306 &pjsua. local_uri,307 &pjsua. contact_uri,314 &pjsua.acc[acc_index].local_uri, 315 &pjsua.acc[acc_index].contact_uri, 308 316 &pjsua.buddies[index].uri, 309 317 NULL, &dlg); … … 326 334 &pjsua.buddies[index]); 327 335 328 status = pjsip_pres_initiate(pjsua.buddies[index].sub, 60, &tdata);336 status = pjsip_pres_initiate(pjsua.buddies[index].sub, -1, &tdata); 329 337 if (status != PJ_SUCCESS) { 330 338 pjsua.buddies[index].sub = NULL; … … 382 390 static void refresh_client_subscription(void) 383 391 { 384 unsignedi;392 int i; 385 393 386 394 for (i=0; i<pjsua.buddy_cnt; ++i) { … … 416 424 * Refresh presence 417 425 */ 418 void pjsua_pres_refresh( void)426 void pjsua_pres_refresh(int acc_index) 419 427 { 420 428 refresh_client_subscription(); 421 refresh_server_subscription( );429 refresh_server_subscription(acc_index); 422 430 } 423 431 … … 428 436 void pjsua_pres_shutdown(void) 429 437 { 430 unsigned i; 431 432 pjsua.online_status = 0; 438 int acc_index; 439 int i; 440 441 for (acc_index=0; acc_index<pjsua.acc_cnt; ++acc_index) { 442 pjsua.acc[acc_index].online_status = 0; 443 } 444 433 445 for (i=0; i<pjsua.buddy_cnt; ++i) { 434 446 pjsua.buddies[i].monitor = 0; 435 447 } 436 pjsua_pres_refresh(); 448 449 for (acc_index=0; acc_index<pjsua.acc_cnt; ++acc_index) { 450 pjsua_pres_refresh(acc_index); 451 } 437 452 } 438 453 … … 442 457 void pjsua_pres_dump(void) 443 458 { 444 unsigned i; 459 int acc_index; 460 int i; 445 461 446 462 PJ_LOG(3,(THIS_FILE, "Dumping pjsua server subscriptions:")); 447 if (pj_list_empty(&pjsua.pres_srv_list)) { 448 PJ_LOG(3,(THIS_FILE, " - none - ")); 449 } else { 450 struct pjsua_srv_pres *uapres; 451 452 uapres = pjsua.pres_srv_list.next; 453 while (uapres != &pjsua.pres_srv_list) { 454 455 PJ_LOG(3,(THIS_FILE, " %10s %s", 456 pjsip_evsub_get_state_name(uapres->sub), 457 uapres->remote)); 458 459 uapres = uapres->next; 463 for (acc_index=0; acc_index < pjsua.acc_cnt; ++acc_index) { 464 465 PJ_LOG(3,(THIS_FILE, " %.*s", 466 (int)pjsua.acc[acc_index].local_uri.slen, 467 pjsua.acc[acc_index].local_uri.ptr)); 468 469 if (pj_list_empty(&pjsua.acc[acc_index].pres_srv_list)) { 470 PJ_LOG(3,(THIS_FILE, " - none - ")); 471 } else { 472 struct pjsua_srv_pres *uapres; 473 474 uapres = pjsua.acc[acc_index].pres_srv_list.next; 475 while (uapres != &pjsua.acc[acc_index].pres_srv_list) { 476 477 PJ_LOG(3,(THIS_FILE, " %10s %s", 478 pjsip_evsub_get_state_name(uapres->sub), 479 uapres->remote)); 480 481 uapres = uapres->next; 482 } 460 483 } 461 484 } -
pjproject/trunk/pjsip/src/pjsua/pjsua_reg.c
r201 r236 35 35 static void regc_cb(struct pjsip_regc_cbparam *param) 36 36 { 37 38 pjsua_acc *acc = param->token; 39 37 40 /* 38 41 * Print registration status. … … 41 44 pjsua_perror(THIS_FILE, "SIP registration error", 42 45 param->status); 43 pjsua.regc = NULL; 46 pjsip_regc_destroy(acc->regc); 47 acc->regc = NULL; 44 48 45 49 } else if (param->code < 0 || param->code >= 300) { … … 47 51 param->code, 48 52 pjsip_get_status_text(param->code)->ptr)); 49 pjsua.regc = NULL; 53 pjsip_regc_destroy(acc->regc); 54 acc->regc = NULL; 50 55 51 56 } else if (PJSIP_IS_STATUS_IN_CLASS(param->code, 200)) { 52 PJ_LOG(3, (THIS_FILE, "SIP registration success, status=%d (%s), " 53 "will re-register in %d seconds", 54 param->code, 55 pjsip_get_status_text(param->code)->ptr, 56 param->expiration)); 57 58 if (param->expiration < 1) { 59 pjsip_regc_destroy(acc->regc); 60 acc->regc = NULL; 61 PJ_LOG(3,(THIS_FILE, "%s: unregistration success", 62 acc->local_uri.ptr)); 63 } else { 64 PJ_LOG(3, (THIS_FILE, 65 "%s: registration success, status=%d (%s), " 66 "will re-register in %d seconds", 67 acc->local_uri.ptr, 68 param->code, 69 pjsip_get_status_text(param->code)->ptr, 70 param->expiration)); 71 } 57 72 58 73 } else { … … 60 75 } 61 76 62 pjsua.regc_last_err = param->status;63 pjsua.regc_last_code = param->code;77 acc->reg_last_err = param->status; 78 acc->reg_last_code = param->code; 64 79 65 pjsua_ui_regc_on_state_changed( pjsua.regc_last_code);80 pjsua_ui_regc_on_state_changed(acc->index); 66 81 } 67 82 … … 70 85 * Update registration. If renew is false, then unregistration will be performed. 71 86 */ 72 void pjsua_regc_update( pj_bool_t renew)87 void pjsua_regc_update(int acc_index, pj_bool_t renew) 73 88 { 74 89 pj_status_t status; … … 76 91 77 92 if (renew) { 78 if (pjsua. regc == NULL) {79 status = pjsua_regc_init( );93 if (pjsua.acc[acc_index].regc == NULL) { 94 status = pjsua_regc_init(acc_index); 80 95 if (status != PJ_SUCCESS) { 81 96 pjsua_perror(THIS_FILE, "Unable to create registration", … … 84 99 } 85 100 } 86 status = pjsip_regc_register(pjsua. regc, 1, &tdata);101 status = pjsip_regc_register(pjsua.acc[acc_index].regc, 1, &tdata); 87 102 } else { 88 if (pjsua. regc == NULL) {103 if (pjsua.acc[acc_index].regc == NULL) { 89 104 PJ_LOG(3,(THIS_FILE, "Currently not registered")); 90 105 return; 91 106 } 92 status = pjsip_regc_unregister(pjsua. regc, &tdata);107 status = pjsip_regc_unregister(pjsua.acc[acc_index].regc, &tdata); 93 108 } 94 109 95 110 if (status == PJ_SUCCESS) 96 status = pjsip_regc_send( pjsua. regc, tdata );111 status = pjsip_regc_send( pjsua.acc[acc_index].regc, tdata ); 97 112 98 113 if (status != PJ_SUCCESS) { … … 108 123 * Initialize client registration. 109 124 */ 110 pj_status_t pjsua_regc_init( void)125 pj_status_t pjsua_regc_init(int acc_index) 111 126 { 112 127 pj_status_t status; 113 128 114 129 /* initialize SIP registration if registrar is configured */ 115 if (pjsua. registrar_uri.slen) {130 if (pjsua.acc[acc_index].reg_uri.slen) { 116 131 117 status = pjsip_regc_create( pjsua.endpt, NULL, ®c_cb, &pjsua.regc); 132 status = pjsip_regc_create( pjsua.endpt, 133 &pjsua.acc[acc_index], 134 ®c_cb, 135 &pjsua.acc[acc_index].regc); 118 136 119 137 if (status != PJ_SUCCESS) { … … 124 142 125 143 126 status = pjsip_regc_init( pjsua.regc, &pjsua.registrar_uri, 127 &pjsua.local_uri, 128 &pjsua.local_uri, 129 1, &pjsua.contact_uri, 130 pjsua.reg_timeout); 144 status = pjsip_regc_init( pjsua.acc[acc_index].regc, 145 &pjsua.acc[acc_index].reg_uri, 146 &pjsua.acc[acc_index].local_uri, 147 &pjsua.acc[acc_index].local_uri, 148 1, &pjsua.acc[acc_index].contact_uri, 149 pjsua.acc[acc_index].reg_timeout); 131 150 if (status != PJ_SUCCESS) { 132 151 pjsua_perror(THIS_FILE, … … 136 155 } 137 156 138 pjsip_regc_set_credentials( pjsua.regc, pjsua.cred_count, 157 pjsip_regc_set_credentials( pjsua.acc[acc_index].regc, 158 pjsua.cred_count, 139 159 pjsua.cred_info ); 140 160 141 pjsip_regc_set_route_set( pjsua.regc, &pjsua.route_set ); 161 pjsip_regc_set_route_set( pjsua.acc[acc_index].regc, 162 &pjsua.acc[acc_index].route_set ); 142 163 } 143 164
Note: See TracChangeset
for help on using the changeset viewer.