Ticket #539: ticket539.patch
File ticket539.patch, 34.7 KB (added by bennylp, 16 years ago) |
---|
-
pjsip/include/pjsua-lib/pjsua_internal.h
26 26 27 27 PJ_BEGIN_DECL 28 28 29 /** 30 * Structure to be attached to media transport. 31 */ 32 typedef struct pjsua_med_tp_data 33 { 34 pjmedia_transport *tp; /**< The media transport */ 35 pjsua_call_id cid; /**< Call-ID (may be -1) */ 36 pjsip_dialog *dlg; /**< SIP dialog (useful when cid is -1) */ 37 pj_status_t status; /**< Transport status. */ 38 39 /** Incoming call data */ 40 struct in { 41 pjmedia_sdp_session *rem_sdp; /**< Cached remote SDP */ 42 pjsip_dialog *replaced_dlg;/**< call xfer */ 43 pjsip_rx_data *rdata; /**< rdata */ 44 pj_bool_t rdata_copy; /**< was rdata copied? */ 45 } in; 46 47 /** Outgoing call data */ 48 struct out { 49 pjsua_msg_data *msg_data; /**< Saved outgoing msg_data */ 50 } out; 51 52 53 } pjsua_med_tp_data; 54 55 29 56 /** 30 57 * Structure to be attached to invite dialog. 31 58 * Given a dialog "dlg", application can retrieve this structure … … 51 78 int conf_slot; /**< Slot # in conference bridge. */ 52 79 pjsip_evsub *xfer_sub; /**< Xfer server subscription, if this 53 80 call was triggered by xfer. */ 54 pjmedia_transport *med_tp; /**< Current media transport. */ 55 pj_status_t med_tp_st; /**< Media transport status. */ 56 pjmedia_transport *med_orig; /**< Original media transport */ 81 82 pjsua_med_tp_data med_tp_data;/**< Media transport data */ 83 pjsua_msg_data *inv_msg_data;/**< Saved make_call() msg_data */ 84 57 85 pj_timer_entry refresh_tm;/**< Timer to send re-INVITE. */ 58 86 pj_timer_entry hangup_tm; /**< Timer to hangup call. */ 59 87 pj_stun_nat_type rem_nat_type; /**< NAT type of remote endpoint. */ … … 316 344 /* 317 345 * Media channel. 318 346 */ 319 pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, 320 pjsip_role_e role, 321 int security_level, 322 int *sip_err_code); 347 348 /* Create. This may return PJ_EPENDING if transport creation can't 349 * complete immediately (e.g. STUN, ICE) */ 350 pj_status_t pjsua_media_channel_create(pjsua_call_id call_id, 351 pjsip_role_e role, 352 int security_level, 353 const pjmedia_sdp_session *rem_sdp, 354 int *sip_err_code); 323 355 pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, 324 356 pj_pool_t *pool, 325 357 const pjmedia_sdp_session *rem_sdp, … … 330 362 const pjmedia_sdp_session *remote_sdp); 331 363 pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id); 332 364 365 void pjsua_on_media_channel_created(pjsua_call_id call_id, 366 pj_status_t status); 333 367 368 334 369 /** 335 370 * Init presence. 336 371 */ … … 422 457 */ 423 458 pjsip_accept_hdr* pjsua_im_create_accept(pj_pool_t *pool); 424 459 460 /* Duplicate msg_data */ 461 void pjsua_msg_data_dup(pj_pool_t *pool, pjsua_msg_data *dst, 462 const pjsua_msg_data *src); 463 425 464 /* 426 465 * Add additional headers etc in msg_data specified by application 427 466 * when sending requests. -
pjsip/include/pjsip-ua/sip_inv.h
554 554 555 555 556 556 /** 557 * Set local offer to be carried by subsequent response (or request). 558 * 559 * @param inv The invite session. 560 * @param sdp The SDP offer. 561 * 562 * @return PJ_SUCCESS if local offer can be accepted by 563 * SDP negotiator. 564 */ 565 PJ_DECL(pj_status_t) pjsip_inv_set_sdp_offer(pjsip_inv_session *inv, 566 const pjmedia_sdp_session *sdp ); 567 568 569 /** 557 570 * Create a SIP message to initiate invite session termination. Depending on 558 571 * the state of the session, this function may return CANCEL request, 559 572 * a non-2xx final response, or a BYE request. If the session has not answered -
pjsip/src/pjsua-lib/pjsua_core.c
56 56 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.tpdata); ++i) 57 57 pjsua_var.tpdata[i].index = i; 58 58 59 for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.calls); ++i) { 60 pjsua_var.calls[i].med_tp_data.cid = PJSUA_INVALID_ID; 61 } 62 59 63 pjsua_var.stun_status = PJ_EUNKNOWN; 60 64 pjsua_var.nat_status = PJ_EPENDING; 61 65 } … … 526 530 527 531 /* Add hostname */ 528 532 hostname = pj_gethostname(); 529 seed = pj_hash_calc(seed, hostname->ptr, (int)hostname->slen); 533 if (hostname) 534 seed = pj_hash_calc(seed, hostname->ptr, (int)hostname->slen); 530 535 531 /* Add primary IP address*/536 /* Add primary IPv4 address, if any */ 532 537 if (pj_gethostip(pj_AF_INET(), &addr)==PJ_SUCCESS) 533 seed = pj_hash_calc(seed, &addr .ipv4.sin_addr, 4);538 seed = pj_hash_calc(seed, &addr, pj_sockaddr_get_len(&addr)); 534 539 540 /* Add primary IPv6 address, if any */ 541 #if PJ_HAS_IPV6 542 if (pj_gethostip(pj_AF_INET6(), &addr)==PJ_SUCCESS) 543 seed = pj_hash_calc(seed, &addr, pj_sockaddr_get_len(&addr)); 544 #endif 545 535 546 /* Get timeofday */ 536 547 pj_gettimeofday(&t); 537 548 seed = pj_hash_calc(seed, &t, sizeof(t)); … … 1819 1830 } 1820 1831 1821 1832 1833 /* Duplicate msg_data */ 1834 void pjsua_msg_data_dup(pj_pool_t *pool, pjsua_msg_data *dst, 1835 const pjsua_msg_data *src) 1836 { 1837 const pjsip_hdr *hsrc; 1838 1839 pjsua_msg_data_init(dst); 1840 1841 /* Duplicate headers */ 1842 hsrc = src->hdr_list.next; 1843 while (hsrc != &src->hdr_list) { 1844 pjsip_hdr *hdst = (pjsip_hdr*) pjsip_hdr_clone(pool, hsrc); 1845 pj_list_push_back(&dst->hdr_list, hdst); 1846 hsrc = hsrc->next; 1847 } 1848 1849 /* Duplicate mime types and body */ 1850 pj_strdup(pool, &dst->content_type, &src->content_type); 1851 pj_strdup(pool, &dst->msg_body, &src->msg_body); 1852 } 1853 1822 1854 /* 1823 1855 * Add additional headers etc in msg_data specified by application 1824 1856 * when sending requests. -
pjsip/src/pjsua-lib/pjsua_call.c
71 71 static pj_status_t create_inactive_sdp(pjsua_call *call, 72 72 pjmedia_sdp_session **p_answer); 73 73 74 /* Disconnect call */ 75 static void call_disconnect(pjsip_inv_session *inv, int code, 76 const char *reason, const char *warn_text, 77 pj_status_t warn_status); 78 74 79 /* Update SDP version in the offer */ 75 80 static void update_sdp_version(pjsua_call *call, 76 81 pjmedia_sdp_session *sdp) … … 115 120 call->res_time.sec = 0; 116 121 call->res_time.msec = 0; 117 122 call->rem_nat_type = PJ_STUN_NAT_TYPE_UNKNOWN; 123 124 pj_bzero(&call->med_tp_data, sizeof(call->med_tp_data)); 125 call->med_tp_data.status = PJ_EPENDING; 126 call->med_tp_data.cid = PJSUA_INVALID_ID; 118 127 } 119 128 120 129 … … 329 338 pjsua_call_id *p_call_id) 330 339 { 331 340 pjsip_dialog *dlg = NULL; 332 pjmedia_sdp_session *offer;333 341 pjsip_inv_session *inv = NULL; 334 342 pjsua_acc *acc; 335 343 pjsua_call *call; 336 344 int call_id = -1; 337 345 pj_str_t contact; 338 pjsip_tx_data *tdata;339 346 pj_status_t status; 340 347 341 348 … … 366 373 } 367 374 368 375 call = &pjsua_var.calls[call_id]; 376 reset_call(call_id); 369 377 370 378 /* Verify that destination URI is valid before calling 371 379 * pjsua_acc_create_uac_contact, or otherwise there … … 426 434 &acc->cfg.id, &contact, 427 435 dest_uri, dest_uri, &dlg); 428 436 if (status != PJ_SUCCESS) { 437 PJSUA_UNLOCK(); 429 438 pjsua_perror(THIS_FILE, "Dialog creation failed", status); 430 PJSUA_UNLOCK();431 439 return status; 432 440 } 433 441 434 /* Calculate call's secure level */435 call->secure_level = get_secure_level(acc_id, dest_uri);436 442 437 /* Init media channel */438 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC,439 call->secure_level, NULL);440 if (status != PJ_SUCCESS) {441 pjsua_perror(THIS_FILE, "Error initializing media channel", status);442 goto on_error;443 }444 445 /* Create SDP offer */446 #if LATE_SDP447 offer = NULL;448 #else449 status = pjsua_media_channel_create_sdp(call->index, dlg->pool, NULL,450 &offer, NULL);451 if (status != PJ_SUCCESS) {452 pjsua_perror(THIS_FILE, "pjmedia unable to create SDP", status);453 goto on_error;454 }455 #endif456 457 443 /* Create the INVITE session: */ 458 444 options |= PJSIP_INV_SUPPORT_100REL; 459 445 if (acc->cfg.require_100rel) 460 446 options |= PJSIP_INV_REQUIRE_100REL; 461 447 462 status = pjsip_inv_create_uac( dlg, offer, options, &inv);448 status = pjsip_inv_create_uac( dlg, NULL, options, &inv); 463 449 if (status != PJ_SUCCESS) { 450 pjsip_dlg_terminate(dlg); 451 PJSUA_UNLOCK(); 464 452 pjsua_perror(THIS_FILE, "Invite session creation failed", status); 465 goto on_error;453 return status; 466 454 } 467 455 468 469 456 /* Create and associate our data in the session. */ 470 457 call->acc_id = acc_id; 471 458 call->inv = inv; … … 500 487 /* Set authentication preference */ 501 488 pjsip_auth_clt_set_prefs(&dlg->auth_sess, &acc->cfg.auth_pref); 502 489 503 /* Create initial INVITE: */ 504 505 status = pjsip_inv_invite(inv, &tdata); 506 if (status != PJ_SUCCESS) { 507 pjsua_perror(THIS_FILE, "Unable to create initial INVITE request", 508 status); 509 goto on_error; 490 /* Save msg_data for later, if any */ 491 if (msg_data) { 492 call->med_tp_data.out.msg_data = PJ_POOL_ALLOC_T(dlg->pool, 493 pjsua_msg_data); 494 pjsua_msg_data_dup(inv->pool, call->med_tp_data.out.msg_data, 495 msg_data); 496 } else { 497 call->med_tp_data.out.msg_data = NULL; 510 498 } 511 499 512 500 513 /* Add additional headers etc */ 501 /* Calculate call's secure level */ 502 call->secure_level = get_secure_level(acc_id, dest_uri); 514 503 515 pjsua_process_msg_data( tdata, msg_data); 504 /* Create the media channel. Further processing to this call will 505 * be done in pjsua_on_media_channel_created() when media channel 506 * creation completes. 507 */ 508 call->med_tp_data.status = PJ_EPENDING; 509 status = pjsua_media_channel_create(call->index, PJSIP_ROLE_UAC, 510 call->secure_level, NULL, NULL); 511 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 512 if (call->inv != NULL) { 513 pjsip_inv_terminate(call->inv, PJSIP_SC_OK, PJ_FALSE); 514 } 515 reset_call(call_id); 516 PJSUA_UNLOCK(); 517 pjsua_perror(THIS_FILE, "Error initializing media channel", status); 518 return status; 519 } 516 520 517 /* Must increment call counter now*/521 /* Increment call counter */ 518 522 ++pjsua_var.call_cnt; 519 523 520 /* Send initial INVITE: */ 524 if (p_call_id) 525 *p_call_id = call_id; 521 526 522 status = pjsip_inv_send_msg(inv, tdata); 527 PJSUA_UNLOCK(); 528 529 return PJ_SUCCESS; 530 } 531 532 533 void pjsua_on_media_channel_created(pjsua_call_id call_id, 534 pj_status_t med_status) 535 { 536 pjsua_call *call; 537 pjsip_dialog *dlg; 538 pjsip_inv_session *inv; 539 pj_status_t status; 540 541 status = acquire_call("pjsua_on_media_channel_created", call_id, 542 &call, &dlg); 523 543 if (status != PJ_SUCCESS) { 524 pjsua_perror(THIS_FILE, "Unable to send initial INVITE request", 525 status); 544 pj_assert(!"Unexpected!"); 545 return; 546 } 526 547 527 /* Upon failure to send first request, both dialog and invite 528 * session would have been cleared. 548 call->med_tp_data.status = med_status; 549 inv = call->inv; 550 551 if (inv->role == PJSIP_ROLE_UAC) { 552 /* 553 * Outgoing call 529 554 */ 530 inv = NULL; 531 dlg = NULL; 532 goto on_error; 533 } 555 pjmedia_sdp_session *offer; 556 pjsip_tx_data *tdata; 534 557 535 /* Done. */ 558 /* Handle failure to start media channel */ 559 if (med_status != PJ_SUCCESS) { 560 pjsip_inv_terminate(call->inv, PJSIP_SC_OK, PJ_FALSE); 561 reset_call(call->index); 562 goto on_return; 563 } 536 564 537 if (p_call_id) 538 *p_call_id = call_id; 565 /* Create SDP offer */ 566 #if LATE_SDP 567 offer = NULL; 568 #else 569 status = pjsua_media_channel_create_sdp(call->index, dlg->pool, NULL, 570 &offer, NULL); 571 if (status != PJ_SUCCESS) { 572 pjsip_inv_terminate(call->inv, PJSIP_SC_OK, PJ_FALSE); 573 reset_call(call->index); 574 pjsua_perror(THIS_FILE, "pjmedia unable to create SDP", status); 575 goto on_return; 576 } 539 577 540 PJSUA_UNLOCK(); 578 status = pjsip_inv_set_sdp_offer(inv, offer); 579 #endif 541 580 542 return PJ_SUCCESS; 581 /* Create initial INVITE: */ 582 status = pjsip_inv_invite(inv, &tdata); 583 if (status != PJ_SUCCESS) { 584 pjsip_inv_terminate(call->inv, PJSIP_SC_OK, PJ_FALSE); 585 reset_call(call->index); 586 pjsua_perror(THIS_FILE, "Unable to create initial INVITE request", 587 status); 588 goto on_return; 589 } 543 590 591 /* Add additional headers etc */ 592 pjsua_process_msg_data(tdata, call->med_tp_data.out.msg_data); 544 593 545 on_error: 546 if (inv != NULL) { 547 pjsip_inv_terminate(inv, PJSIP_SC_OK, PJ_FALSE); 548 } else if (dlg) { 549 pjsip_dlg_terminate(dlg); 550 } 594 /* Send initial INVITE: */ 595 status = pjsip_inv_send_msg(inv, tdata); 596 if (status != PJ_SUCCESS) { 597 pjsua_perror(THIS_FILE, "Unable to send initial INVITE request", 598 status); 551 599 552 if (call_id != -1) { 553 reset_call(call_id); 554 pjsua_media_channel_deinit(call_id); 600 /* Upon failure to send first request, both dialog and invite 601 * session would have been cleared. 602 */ 603 inv = NULL; 604 dlg = NULL; 605 goto on_return; 606 } 607 608 } else { 609 /* 610 * Incoming call 611 */ 612 pjmedia_sdp_session *answer; 613 int sip_err_code; 614 615 /* Handle failure to start media channel */ 616 if (med_status != PJ_SUCCESS) { 617 call_disconnect(inv, 500, "Media Error", NULL, 618 med_status); 619 goto on_return; 620 } 621 622 /* Get media channel's SDP */ 623 status = pjsua_media_channel_create_sdp(call_id, inv->pool, 624 call->med_tp_data.in.rem_sdp, 625 &answer, &sip_err_code); 626 if (status != PJ_SUCCESS) { 627 call_disconnect(inv, sip_err_code, NULL, 628 "SDP creation/negotiation failed", status); 629 goto on_return; 630 } 631 632 /* Set SDP to the invite session */ 633 if (inv->neg) { 634 status = pjsip_inv_set_sdp_answer(inv, answer); 635 } else { 636 status = pjsip_inv_set_sdp_offer(inv, answer); 637 } 638 639 if (status != PJ_SUCCESS) { 640 call_disconnect(inv, sip_err_code, NULL, "Unable to set SDP", 641 status); 642 goto on_return; 643 } 644 645 /* Check if this request should replace existing call */ 646 if (call->med_tp_data.in.replaced_dlg) { 647 pjsip_dialog *replaced_dlg = call->med_tp_data.in.replaced_dlg; 648 pjsip_inv_session *replaced_inv; 649 struct pjsua_call *replaced_call; 650 pjsip_tx_data *tdata; 651 652 /* Get the invite session in the dialog */ 653 replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg); 654 655 /* Get the replaced call instance */ 656 replaced_call = (pjsua_call*) replaced_dlg->mod_data[pjsua_var.mod.id]; 657 658 /* Notify application */ 659 if (pjsua_var.ua_cfg.cb.on_call_replaced) 660 pjsua_var.ua_cfg.cb.on_call_replaced(replaced_call->index, 661 call_id); 662 663 PJ_LOG(4,(THIS_FILE, "Answering replacement call %d with 200/OK", 664 call_id)); 665 666 /* Answer the new call with 200 response */ 667 status = pjsip_inv_answer(inv, 200, NULL, NULL, &tdata); 668 if (status == PJ_SUCCESS) 669 status = pjsip_inv_send_msg(inv, tdata); 670 671 if (status != PJ_SUCCESS) 672 pjsua_perror(THIS_FILE, "Error answering session", status); 673 674 /* Note that inv may be invalid if 200/OK has caused error in 675 * starting the media. 676 */ 677 678 PJ_LOG(4,(THIS_FILE, "Disconnecting replaced call %d", 679 replaced_call->index)); 680 681 /* Disconnect replaced invite session */ 682 status = pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, NULL, 683 &tdata); 684 if (status == PJ_SUCCESS && tdata) 685 status = pjsip_inv_send_msg(replaced_inv, tdata); 686 687 if (status != PJ_SUCCESS) 688 pjsua_perror(THIS_FILE, "Error terminating session", status); 689 690 691 } else { 692 693 /* Notify application if on_incoming_call() is overriden, 694 * otherwise hangup the call with 480 695 */ 696 if (pjsua_var.ua_cfg.cb.on_incoming_call) { 697 pjsua_var.ua_cfg.cb.on_incoming_call(call->acc_id, call_id, 698 rdata); 699 } else { 700 pjsua_call_hangup(call_id, PJSIP_SC_TEMPORARILY_UNAVAILABLE, 701 NULL, NULL); 702 } 703 } 704 555 705 } 556 706 557 PJSUA_UNLOCK(); 558 return status; 707 on_return: 708 pjsip_dlg_dec_lock(dlg); 709 return; 559 710 } 560 711 561 712 … … 595 746 pjsua_call *call; 596 747 int call_id = -1; 597 748 int sip_err_code; 598 pjmedia_sdp_session *offer, * answer;749 pjmedia_sdp_session *offer, *test_answer = NULL; 599 750 pj_status_t status; 600 751 601 752 /* Don't want to handle anything but INVITE */ … … 658 809 return PJ_TRUE; 659 810 } 660 811 812 call->med_tp_data.in.replaced_dlg = replaced_dlg; 813 661 814 /* If this INVITE request contains Replaces header, notify application 662 815 * about the request so that application can do subsequent checking 663 816 * if it wants to. … … 697 850 */ 698 851 acc_id = call->acc_id = pjsua_acc_find_for_incoming(rdata); 699 852 700 /* Get call's secure level */701 if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri))702 call->secure_level = 2;703 else if (PJSIP_TRANSPORT_IS_SECURE(rdata->tp_info.transport))704 call->secure_level = 1;705 else706 call->secure_level = 0;707 708 /* Init media channel */709 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS,710 call->secure_level, &sip_err_code);711 if (status != PJ_SUCCESS) {712 pjsua_perror(THIS_FILE, "Error initializing media channel", status);713 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,714 sip_err_code, NULL,715 NULL, NULL);716 PJSUA_UNLOCK();717 return PJ_TRUE;718 }719 720 853 /* Parse SDP from incoming request */ 721 854 if (rdata->msg_info.msg->body) { 855 pjmedia_sock_info sock_info; 856 722 857 status = pjmedia_sdp_parse(rdata->tp_info.pool, 723 858 (char*)rdata->msg_info.msg->body->data, 724 859 rdata->msg_info.msg->body->len, &offer); … … 744 879 return PJ_TRUE; 745 880 } 746 881 882 /* Create a template SDP answer to verify incoming SDP */ 883 pj_bzero(&sock_info, sizeof(sock_info)); 884 pj_sockaddr_in_init(&sock_info.rtp_addr_name.ipv4, NULL, 4000); 885 pj_sockaddr_in_init(&sock_info.rtcp_addr_name.ipv4, NULL, 4001); 886 status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, 887 rdata->tp_info.pool, 888 1, &sock_info, &test_answer); 747 889 } else { 748 890 offer = NULL; 891 test_answer = NULL; 749 892 } 750 893 751 /* Get media capability from media endpoint: */752 status = pjsua_media_channel_create_sdp(call->index, rdata->tp_info.pool,753 offer, &answer, &sip_err_code);754 if (status != PJ_SUCCESS) {755 pjsua_perror(THIS_FILE, "Error creating SDP answer", status);756 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,757 sip_err_code, NULL,758 NULL, NULL);759 pjsua_media_channel_deinit(call->index);760 PJSUA_UNLOCK();761 return PJ_TRUE;762 }763 764 894 /* Verify that we can handle the request. */ 765 895 options |= PJSIP_INV_SUPPORT_100REL; 766 896 if (pjsua_var.acc[acc_id].cfg.require_100rel) 767 897 options |= PJSIP_INV_REQUIRE_100REL; 768 898 769 status = pjsip_inv_verify_request2(rdata, &options, offer, answer, NULL,770 pjsua_var.endpt, &response);899 status = pjsip_inv_verify_request2(rdata, &options, offer, test_answer, 900 NULL, pjsua_var.endpt, &response); 771 901 if (status != PJ_SUCCESS) { 772 902 773 903 /* … … 792 922 return PJ_TRUE; 793 923 } 794 924 795 796 925 /* Get suitable Contact header */ 797 926 if (pjsua_var.acc[acc_id].contact.slen) { 798 927 contact = pjsua_var.acc[acc_id].contact; … … 833 962 &pjsua_var.acc[acc_id].cfg.auth_pref); 834 963 835 964 /* Create invite session: */ 836 status = pjsip_inv_create_uas( dlg, rdata, answer, options, &inv);965 status = pjsip_inv_create_uas( dlg, rdata, NULL, options, &inv); 837 966 if (status != PJ_SUCCESS) { 838 967 pjsip_hdr hdr_list; 839 968 pjsip_warning_hdr *w; … … 857 986 /* Update NAT type of remote endpoint, only when there is SDP in 858 987 * incoming INVITE! 859 988 */ 860 if (pjsua_var.ua_cfg.nat_type_in_sdp && 861 pjmedia_sdp_neg_get_state(inv->neg) > PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) 862 { 863 const pjmedia_sdp_session *remote_sdp; 864 865 if (pjmedia_sdp_neg_get_neg_remote(inv->neg, &remote_sdp)==PJ_SUCCESS) 866 update_remote_nat_type(call, remote_sdp); 989 if (pjsua_var.ua_cfg.nat_type_in_sdp && offer != NULL) { 990 update_remote_nat_type(call, offer); 867 991 } 868 992 869 993 /* Create and attach pjsua_var data to the dialog: */ … … 903 1027 } 904 1028 } 905 1029 906 ++pjsua_var.call_cnt; 1030 /* Save state */ 1031 call->med_tp_data.status = PJ_EPENDING; 1032 if (offer) { 1033 call->med_tp_data.in.rem_sdp = 1034 pjmedia_sdp_session_clone(inv->pool, offer); 1035 } 907 1036 1037 /* Get call's secure level */ 1038 if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri)) 1039 call->secure_level = 2; 1040 else if (PJSIP_TRANSPORT_IS_SECURE(rdata->tp_info.transport)) 1041 call->secure_level = 1; 1042 else 1043 call->secure_level = 0; 908 1044 909 /* Check if this request should replace existing call */910 if (replaced_dlg) {911 pjsip_inv_session *replaced_inv;912 struct pjsua_call *replaced_call;913 pjsip_tx_data *tdata;914 1045 915 /* Get the invite session in the dialog */ 916 replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg); 917 918 /* Get the replaced call instance */ 919 replaced_call = (pjsua_call*) replaced_dlg->mod_data[pjsua_var.mod.id]; 920 921 /* Notify application */ 922 if (pjsua_var.ua_cfg.cb.on_call_replaced) 923 pjsua_var.ua_cfg.cb.on_call_replaced(replaced_call->index, 924 call_id); 925 926 PJ_LOG(4,(THIS_FILE, "Answering replacement call %d with 200/OK", 927 call_id)); 928 929 /* Answer the new call with 200 response */ 930 status = pjsip_inv_answer(inv, 200, NULL, NULL, &tdata); 931 if (status == PJ_SUCCESS) 932 status = pjsip_inv_send_msg(inv, tdata); 933 934 if (status != PJ_SUCCESS) 935 pjsua_perror(THIS_FILE, "Error answering session", status); 936 937 /* Note that inv may be invalid if 200/OK has caused error in 938 * starting the media. 939 */ 940 941 PJ_LOG(4,(THIS_FILE, "Disconnecting replaced call %d", 942 replaced_call->index)); 943 944 /* Disconnect replaced invite session */ 945 status = pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, NULL, 946 &tdata); 947 if (status == PJ_SUCCESS && tdata) 948 status = pjsip_inv_send_msg(replaced_inv, tdata); 949 950 if (status != PJ_SUCCESS) 951 pjsua_perror(THIS_FILE, "Error terminating session", status); 952 953 954 } else { 955 956 /* Notify application if on_incoming_call() is overriden, 957 * otherwise hangup the call with 480 958 */ 959 if (pjsua_var.ua_cfg.cb.on_incoming_call) { 960 pjsua_var.ua_cfg.cb.on_incoming_call(acc_id, call_id, rdata); 961 } else { 962 pjsua_call_hangup(call_id, PJSIP_SC_TEMPORARILY_UNAVAILABLE, 963 NULL, NULL); 964 } 1046 /* Create the media channel. Further processing to this call will 1047 * be done in pjsua_on_media_channel_created() when media channel 1048 * creation completes. 1049 */ 1050 status = pjsua_media_channel_create(call->index, PJSIP_ROLE_UAS, 1051 call->secure_level, &sip_err_code); 1052 if (status != PJ_SUCCESS) { 1053 pjsua_perror(THIS_FILE, "Error initializing media channel", status); 1054 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 1055 sip_err_code, NULL, 1056 NULL, NULL); 1057 PJSUA_UNLOCK(); 1058 return PJ_TRUE; 965 1059 } 966 1060 1061 ++pjsua_var.call_cnt; 967 1062 968 1063 /* This INVITE request has been handled. */ 969 1064 PJSUA_UNLOCK(); … … 2290 2385 *p = '\0'; 2291 2386 } 2292 2387 2388 /* Only print media when media channel/transport is ready */ 2389 if (call->med_tp_data.tp==NULL || call->med_tp_data.status!=PJ_SUCCESS) 2390 return PJ_SUCCESS; 2391 2293 2392 /* Get SRTP status */ 2294 2393 pjmedia_transport_info_init(&tp_info); 2295 2394 pjmedia_transport_get_info(call->med_tp, &tp_info); … … 2482 2581 /* 2483 2582 * Disconnect call upon error. 2484 2583 */ 2485 static void call_disconnect( pjsip_inv_session *inv, 2486 int code ) 2584 static void call_disconnect(pjsip_inv_session *inv, int code, 2585 const char *res, const char *warn_text, 2586 pj_status_t warn_status) 2487 2587 { 2488 2588 pjsua_call *call; 2589 pj_str_t str; 2489 2590 pjsip_tx_data *tdata; 2490 2591 pj_status_t status; 2491 2592 2492 2593 call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id]; 2493 2594 2494 status = pjsip_inv_end_session(inv, code, NULL, &tdata); 2595 status = pjsip_inv_end_session(inv, code, res ? pj_cstr(&str, res) : NULL, 2596 &tdata); 2495 2597 if (status != PJ_SUCCESS) 2496 2598 return; 2497 2599 2600 if (warn_text) { 2601 pjsip_warning_hdr *whdr; 2602 whdr = pjsip_warning_hdr_create(tdata->pool, 399, 2603 pjsip_endpt_name(pjsua_var.endpt), 2604 pj_cstr(&str, warn_text)); 2605 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) whdr); 2606 } 2607 2608 if (warn_status) { 2609 pjsip_warning_hdr *whdr; 2610 whdr = pjsip_warning_hdr_create_from_status( 2611 tdata->pool, 2612 pjsip_endpt_name(pjsua_var.endpt), 2613 warn_status); 2614 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) whdr); 2615 } 2616 2498 2617 /* Add SDP in 488 status */ 2499 2618 if (call && call->med_tp && tdata->msg->type==PJSIP_RESPONSE_MSG && 2500 2619 code==PJSIP_SC_NOT_ACCEPTABLE_HERE) … … 2545 2664 if (inv->state != PJSIP_INV_STATE_NULL && 2546 2665 inv->state != PJSIP_INV_STATE_CONFIRMED) 2547 2666 { 2548 call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 2667 call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE, 2668 NULL, NULL, status); 2549 2669 } 2550 2670 2551 2671 PJSUA_UNLOCK(); … … 2585 2705 if (status != PJ_SUCCESS) { 2586 2706 pjsua_perror(THIS_FILE, "Unable to create media session", 2587 2707 status); 2588 call_disconnect(inv, PJSIP_SC_NOT_ACCEPTABLE_HERE); 2708 call_disconnect(inv, PJSIP_SC_NOT_ACCEPTABLE_HERE, NULL, NULL, 2709 status); 2589 2710 pjsua_media_channel_deinit(call->index); 2590 2711 PJSUA_UNLOCK(); 2591 2712 return; -
pjsip/src/pjsip-ua/sip_inv.c
1726 1726 pj_status_t status; 1727 1727 1728 1728 PJ_ASSERT_RETURN(inv && sdp, PJ_EINVAL); 1729 PJ_ASSERT_RETURN(inv->neg, PJ_EINVALIDOP); 1730 PJ_ASSERT_RETURN(pjmedia_sdp_neg_get_state(inv->neg) == 1731 PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER, 1732 PJ_EINVALIDOP); 1729 1733 1730 1734 pjsip_dlg_inc_lock(inv->dlg); 1731 1735 status = pjmedia_sdp_neg_set_local_answer( inv->pool, inv->neg, sdp); … … 1736 1740 1737 1741 1738 1742 /* 1743 * Set SDP offer. 1744 */ 1745 PJ_DEF(pj_status_t) pjsip_inv_set_sdp_offer(pjsip_inv_session *inv, 1746 const pjmedia_sdp_session *sdp) 1747 { 1748 pj_status_t status; 1749 1750 PJ_ASSERT_RETURN(inv && sdp, PJ_EINVAL); 1751 1752 pjsip_dlg_inc_lock(inv->dlg); 1753 if (inv->neg == NULL) { 1754 status = pjmedia_sdp_neg_create_w_local_offer(inv->pool, sdp, 1755 &inv->neg); 1756 } else { 1757 PJ_ASSERT_ON_FAIL(pjmedia_sdp_neg_get_state(inv->neg) == 1758 PJMEDIA_SDP_NEG_STATE_DONE, 1759 {pjsip_dlg_dec_lock(inv->dlg); 1760 return PJ_EINVALIDOP; }); 1761 1762 status = pjmedia_sdp_neg_modify_local_offer(inv->pool, inv->neg, 1763 sdp); 1764 } 1765 pjsip_dlg_dec_lock(inv->dlg); 1766 1767 return status; 1768 } 1769 1770 /* 1739 1771 * End session. 1740 1772 */ 1741 1773 PJ_DEF(pj_status_t) pjsip_inv_end_session( pjsip_inv_session *inv, -
pjmedia/include/pjmedia/transport.h
249 249 pjmedia_transport_info *info); 250 250 251 251 /** 252 * Manage the application data. Application should use 253 * #pjmedia_transport_get_app_data() and #pjmedia_transport_set_app_data() 254 * instead. 255 * 256 * This function returns the old application data in the transport. 257 * If \a set argument is non-zero, new application data will be set 258 * from \a app_data argument, otherwise the app_data will not be 259 * changed. 260 */ 261 void* (*set_app_data)(pjmedia_transport *tp, pj_bool_t set, 262 void *app_data); 263 264 /** 252 265 * This function is called by the stream when the transport is about 253 266 * to be used by the stream for the first time, and it tells the transport 254 267 * about remote RTP address to send the packet and some callbacks to be … … 396 409 * stacked with other transport to enable encryption on the underlying 397 410 * transport. 398 411 */ 399 PJMEDIA_TRANSPORT_TYPE_SRTP 412 PJMEDIA_TRANSPORT_TYPE_SRTP, 400 413 414 /** Start of user defined transport type */ 415 PJMEDIA_TRANSPORT_TYPE_USER = 16 416 401 417 } pjmedia_transport_type; 402 418 403 419 … … 504 520 505 521 506 522 /** 523 * Get the application data attached to the transport. The application data 524 * is set when the transport is created and it can be changed by using 525 * #pjmedia_transport_set_app_data(). 526 * 527 * @param tp The media transport. 528 * 529 * @return The application data. 530 */ 531 PJ_INLINE(void*) pjmedia_transport_get_app_data(pjmedia_transport *tp) 532 { 533 return tp->op->set_app_data(tp, PJ_FALSE, NULL); 534 } 535 536 537 /** 538 * Set new application data value to the media transport. 539 * 540 * @param tp The media transport. 541 * @param app_data New application data. 542 * 543 * @return The old application data. 544 */ 545 PJ_INLINE(void*) pjmedia_transport_set_app_data(pjmedia_transport *tp, 546 void *app_data) 547 { 548 return tp->op->set_app_data(tp, PJ_TRUE, app_data); 549 } 550 551 552 /** 507 553 * Attach callbacks to be called on receipt of incoming RTP/RTCP packets. 508 554 * This is just a simple wrapper which calls <tt>attach()</tt> member of 509 555 * the transport. -
pjmedia/include/pjmedia/transport_ice.h
66 66 * @param comp_cnt Number of components to be created. 67 67 * @param cfg Pointer to configuration settings. 68 68 * @param cb Optional callbacks. 69 * @param app_data Optional application data. 69 70 * @param p_tp Pointer to receive the media transport instance. 70 71 * 71 72 * @return PJ_SUCCESS on success, or the appropriate error code. … … 75 76 unsigned comp_cnt, 76 77 const pj_ice_strans_cfg *cfg, 77 78 const pjmedia_ice_cb *cb, 79 void *app_data, 78 80 pjmedia_transport **p_tp); 79 81 80 82 PJ_END_DECL -
pjmedia/src/pjmedia/transport_udp.c
51 51 52 52 pj_pool_t *pool; /**< Memory pool */ 53 53 unsigned options; /**< Transport options. */ 54 void *app_data; /**< Application data. */ 54 55 unsigned media_options; /**< Transport media options. */ 55 56 void *user_data; /**< Only valid when attached */ 56 57 pj_bool_t attached; /**< Has attachment? */ … … 102 103 */ 103 104 static pj_status_t transport_get_info (pjmedia_transport *tp, 104 105 pjmedia_transport_info *info); 106 static void* transport_set_app_data(pjmedia_transport *tp, 107 pj_bool_t set, void *app_data); 105 108 static pj_status_t transport_attach (pjmedia_transport *tp, 106 109 void *user_data, 107 110 const pj_sockaddr_t *rem_addr, … … 147 150 static pjmedia_transport_op transport_udp_op = 148 151 { 149 152 &transport_get_info, 153 &transport_set_app_data, 150 154 &transport_attach, 151 155 &transport_detach, 152 156 &transport_send_rtp, … … 604 608 } 605 609 606 610 611 /* Get/set application data */ 612 static void* transport_set_app_data(pjmedia_transport *tp, 613 pj_bool_t set, void *app_data) 614 { 615 struct transport_udp *udp = (struct transport_udp*)tp; 616 void *old_app_data; 617 618 PJ_ASSERT_RETURN(tp, NULL); 619 620 old_app_data = udp->app_data; 621 if (set) 622 udp->app_data = app_data; 623 624 return old_app_data; 625 } 626 607 627 /* Called by application to initialize the transport */ 608 628 static pj_status_t transport_attach( pjmedia_transport *tp, 609 629 void *user_data, -
pjmedia/src/pjmedia/transport_ice.c
30 30 { 31 31 pjmedia_transport base; 32 32 pj_pool_t *pool; 33 void *app_data; 33 34 int af; 34 35 unsigned comp_cnt; 35 36 pj_ice_strans *ice_st; … … 57 58 */ 58 59 static pj_status_t transport_get_info (pjmedia_transport *tp, 59 60 pjmedia_transport_info *info); 61 static void* transport_set_app_data(pjmedia_transport *tp, 62 pj_bool_t set, void *app_data); 60 63 static pj_status_t transport_attach (pjmedia_transport *tp, 61 64 void *user_data, 62 65 const pj_sockaddr_t *rem_addr, … … 114 117 static pjmedia_transport_op transport_ice_op = 115 118 { 116 119 &transport_get_info, 120 &transport_set_app_data, 117 121 &transport_attach, 118 122 &transport_detach, 119 123 &transport_send_rtp, … … 139 143 unsigned comp_cnt, 140 144 const pj_ice_strans_cfg *cfg, 141 145 const pjmedia_ice_cb *cb, 146 void *app_data, 142 147 pjmedia_transport **p_tp) 143 148 { 144 149 pj_pool_t *pool; … … 154 159 tp_ice->pool = pool; 155 160 tp_ice->af = cfg->af; 156 161 tp_ice->comp_cnt = comp_cnt; 162 tp_ice->app_data = app_data; 157 163 pj_ansi_strcpy(tp_ice->base.name, pool->obj_name); 158 164 tp_ice->base.op = &transport_ice_op; 159 165 tp_ice->base.type = PJMEDIA_TRANSPORT_TYPE_ICE; … … 675 681 } 676 682 677 683 684 static void* transport_set_app_data(pjmedia_transport *tp, 685 pj_bool_t set, void *app_data) 686 { 687 struct transport_ice *tp_ice = (struct transport_ice*)tp; 688 void *old_app_data; 689 690 PJ_ASSERT_RETURN(tp, NULL); 691 692 old_app_data = tp_ice->app_data; 693 if (set) 694 tp_ice->app_data = app_data; 695 696 return old_app_data; 697 } 698 699 678 700 static pj_status_t transport_attach (pjmedia_transport *tp, 679 701 void *stream, 680 702 const pj_sockaddr_t *rem_addr, -
pjmedia/src/pjmedia/transport_srtp.c
78 78 pjmedia_transport base; /**< Base transport interface. */ 79 79 pj_pool_t *pool; 80 80 pj_lock_t *mutex; 81 void *app_data; 81 82 char tx_buffer[MAX_BUFFER_LEN]; 82 83 pjmedia_srtp_setting setting; 83 84 unsigned media_option; … … 126 127 */ 127 128 static pj_status_t transport_get_info (pjmedia_transport *tp, 128 129 pjmedia_transport_info *info); 130 static void* transport_set_app_data(pjmedia_transport *tp, 131 pj_bool_t set, void *app_data); 129 132 static pj_status_t transport_attach (pjmedia_transport *tp, 130 133 void *user_data, 131 134 const pj_sockaddr_t *rem_addr, … … 172 175 static pjmedia_transport_op transport_srtp_op = 173 176 { 174 177 &transport_get_info, 178 &transport_set_app_data, 175 179 &transport_attach, 176 180 &transport_detach, 177 181 &transport_send_rtp, … … 582 586 return pjmedia_transport_get_info(srtp->real_tp, info); 583 587 } 584 588 589 static void* transport_set_app_data(pjmedia_transport *tp, 590 pj_bool_t set, void *app_data) 591 { 592 struct transport_srtp *srtp = (struct transport_srtp*)tp; 593 void *old_app_data; 594 595 PJ_ASSERT_RETURN(tp, NULL); 596 597 old_app_data = srtp->app_data; 598 if (set) 599 srtp->app_data = app_data; 600 601 return old_app_data; 602 } 603 585 604 static pj_status_t transport_attach(pjmedia_transport *tp, 586 605 void *user_data, 587 606 const pj_sockaddr_t *rem_addr,