diff --git a/pjlib-util/src/pjlib-util/resolver.c b/pjlib-util/src/pjlib-util/resolver.c index dcdeff83f5..b18a9fff4d 100644 --- a/pjlib-util/src/pjlib-util/resolver.c +++ b/pjlib-util/src/pjlib-util/resolver.c @@ -1840,15 +1840,15 @@ PJ_DEF(pj_status_t) pj_dns_resolver_add_entry( pj_dns_resolver *resolver, pj_bzero(&key, sizeof(struct res_key)); if (pkt->hdr.anscount) { /* Make sure name is not too long. */ - PJ_ASSERT_RETURN(pkt->ans[0].name.slen < PJ_MAX_HOSTNAME, - PJ_ENAMETOOLONG); + PJ_ASSERT_ON_FAIL(pkt->ans[0].name.slen < PJ_MAX_HOSTNAME, + { pj_grp_lock_release(resolver->grp_lock); return PJ_ENAMETOOLONG; }); init_res_key(&key, pkt->ans[0].type, &pkt->ans[0].name); } else { /* Make sure name is not too long. */ - PJ_ASSERT_RETURN(pkt->q[0].name.slen < PJ_MAX_HOSTNAME, - PJ_ENAMETOOLONG); + PJ_ASSERT_ON_FAIL(pkt->q[0].name.slen < PJ_MAX_HOSTNAME, + { pj_grp_lock_release(resolver->grp_lock); return PJ_ENAMETOOLONG; }); init_res_key(&key, pkt->q[0].type, &pkt->q[0].name); } diff --git a/pjlib/include/pj/list.h b/pjlib/include/pj/list.h index fa667296df..1ca6445c7c 100644 --- a/pjlib/include/pj/list.h +++ b/pjlib/include/pj/list.h @@ -170,6 +170,27 @@ PJ_IDECL(void) pj_list_insert_nodes_after(pj_list_type *lst, pj_list_type *nodes); +/** + * Insert a list to another list before the specified element position. + * + * @param pos The element to which the node will be inserted before. + * @param lst The list to be inserted. + */ +PJ_IDECL(void) pj_list_insert_list_before(pj_list_type *pos, + pj_list_type *lst); + + +/** + * Insert a list to another list after the specified element position. + * + * @param pos The element in the list which will precede the inserted + * list. + * @param lst The list to be inserted. + */ +PJ_IDECL(void) pj_list_insert_list_after(pj_list_type *pos, + pj_list_type *lst); + + /** * Remove elements from the source list, and insert them to the destination * list. The elements of the source list will occupy the diff --git a/pjlib/include/pj/list_i.h b/pjlib/include/pj/list_i.h index 90718d74dd..cb134f264e 100644 --- a/pjlib/include/pj/list_i.h +++ b/pjlib/include/pj/list_i.h @@ -54,6 +54,23 @@ PJ_IDEF(void) pj_list_insert_nodes_before(pj_list_type *pos, pj_list_type *lst) pj_list_insert_nodes_after(((pj_list*)pos)->prev, lst); } +PJ_IDEF(void) pj_list_insert_list_after(pj_list_type *pos, pj_list_type *lst) +{ + if (!pj_list_empty(lst)) { + pj_list *lst_last = (pj_list *) ((pj_list*)lst)->prev; + pj_list *pos_next = (pj_list *) ((pj_list*)pos)->next; + + pj_link_node(pos, (pj_list *) ((pj_list*)lst)->next); + pj_link_node(lst_last, pos_next); + pj_list_init(lst); + } +} + +PJ_IDEF(void) pj_list_insert_list_before(pj_list_type *pos, pj_list_type *lst) +{ + pj_list_insert_list_after(((pj_list*)pos)->prev, lst); +} + PJ_IDEF(void) pj_list_merge_last(pj_list_type *lst1, pj_list_type *lst2) { if (!pj_list_empty(lst2)) { diff --git a/pjlib/src/pj/ioqueue_winnt.c b/pjlib/src/pj/ioqueue_winnt.c index d2a45dbcc8..11b6573bc7 100644 --- a/pjlib/src/pj/ioqueue_winnt.c +++ b/pjlib/src/pj/ioqueue_winnt.c @@ -495,6 +495,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_destroy( pj_ioqueue_t *ioqueue ) } #endif + pj_lock_release(ioqueue->lock); if (ioqueue->auto_delete_lock) pj_lock_destroy(ioqueue->lock); diff --git a/pjlib/src/pj/pool_caching.c b/pjlib/src/pj/pool_caching.c index 0d55e1dfb4..c30cfd6aa3 100644 --- a/pjlib/src/pj/pool_caching.c +++ b/pjlib/src/pj/pool_caching.c @@ -219,6 +219,7 @@ static void cpool_release_pool( pj_pool_factory *pf, pj_pool_t *pool) #if PJ_SAFE_POOL /* Make sure pool is still in our used list */ if (pj_list_find_node(&cp->used_list, pool) != pool) { + pj_lock_release(cp->lock); pj_assert(!"Attempt to destroy pool that has been destroyed before"); return; } diff --git a/pjnath/src/pjnath/turn_session.c b/pjnath/src/pjnath/turn_session.c index d14204aef8..c1437cde1e 100644 --- a/pjnath/src/pjnath/turn_session.c +++ b/pjnath/src/pjnath/turn_session.c @@ -664,7 +664,9 @@ PJ_DEF(pj_status_t) pj_turn_session_set_server( pj_turn_session *sess, unsigned i, cnt; /* Default port must be specified */ - PJ_ASSERT_RETURN(default_port>0 && default_port<65536, PJ_EINVAL); + PJ_ASSERT_ON_FAIL(default_port>0 && default_port<65536, + {status=PJ_EINVAL; goto on_return;}); + sess->default_port = (pj_uint16_t)default_port; cnt = PJ_TURN_MAX_DNS_SRV_CNT; diff --git a/pjsip-apps/src/pjsua/pjsua_app.c b/pjsip-apps/src/pjsua/pjsua_app.c index c53b04c0a9..b6eeda3483 100644 --- a/pjsip-apps/src/pjsua/pjsua_app.c +++ b/pjsip-apps/src/pjsua/pjsua_app.c @@ -1060,6 +1060,11 @@ void on_ip_change_progress(pjsua_ip_change_op op, if (status == PJ_SUCCESS) { switch (op) { + case PJSUA_IP_CHANGE_OP_SHUTDOWN_TP: + pj_ansi_snprintf(info_str, sizeof(info_str), + "TCP/TLS transports shutdown"); + break; + case PJSUA_IP_CHANGE_OP_RESTART_LIS: pjsua_transport_get_info(info->lis_restart.transport_id, &tp_info); pj_ansi_snprintf(info_str, sizeof(info_str), @@ -1107,6 +1112,7 @@ void on_ip_change_progress(pjsua_ip_change_op op, pj_ansi_snprintf(info_str, sizeof(info_str), "done"); default: + info_str[0] = '\0'; break; } PJ_LOG(3,(THIS_FILE, "IP change progress report : %s", info_str)); diff --git a/pjsip-apps/src/pjsua/pjsua_app_legacy.c b/pjsip-apps/src/pjsua/pjsua_app_legacy.c index 0559827007..14f3e95c8f 100644 --- a/pjsip-apps/src/pjsua/pjsua_app_legacy.c +++ b/pjsip-apps/src/pjsua/pjsua_app_legacy.c @@ -1786,8 +1786,6 @@ static void ui_handle_ip_change() status = pjsua_handle_ip_change(¶m); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "IP change failed", status); - } else { - PJ_LOG(3,(THIS_FILE, "IP change succeeded")); } } diff --git a/pjsip-apps/src/swig/symbols.i b/pjsip-apps/src/swig/symbols.i index 85bd7c1066..bf0965b0d7 100644 --- a/pjsip-apps/src/swig/symbols.i +++ b/pjsip-apps/src/swig/symbols.i @@ -911,6 +911,7 @@ typedef enum pjsua_snd_dev_mode typedef enum pjsua_ip_change_op { PJSUA_IP_CHANGE_OP_NULL, + PJSUA_IP_CHANGE_OP_SHUTDOWN_TP, PJSUA_IP_CHANGE_OP_RESTART_LIS, PJSUA_IP_CHANGE_OP_ACC_SHUTDOWN_TP, PJSUA_IP_CHANGE_OP_ACC_UPDATE_CONTACT, diff --git a/pjsip/include/pjsip/sip_transport.h b/pjsip/include/pjsip/sip_transport.h index 0127433d40..878186a331 100644 --- a/pjsip/include/pjsip/sip_transport.h +++ b/pjsip/include/pjsip/sip_transport.h @@ -1322,6 +1322,53 @@ PJ_DECL(pj_status_t) pjsip_tpmgr_destroy(pjsip_tpmgr *mgr); PJ_DECL(void) pjsip_tpmgr_dump_transports(pjsip_tpmgr *mgr); +/** + * Parameter for pjsip_tpmgr_shutdown_all() function. + */ +typedef struct pjsip_tpmgr_shutdown_param +{ + /** + * Specify whether disconnection state notification should be sent + * immediately, see pjsip_transport_shutdown2() for more info. + * + * Default: PJ_TRUE. + */ + pj_bool_t force; + + /** + * Specify whether UDP transports should also be shutdown. + * + * Default: PJ_TRUE. + */ + pj_bool_t include_udp; + +} pjsip_tpmgr_shutdown_param; + + +/** + * Initialize transports shutdown parameter with default values. + * + * @param prm The parameter to be initialized. + */ +PJ_DECL(void) pjsip_tpmgr_shutdown_param_default( + pjsip_tpmgr_shutdown_param *prm); + + +/** + * Shutdown all transports. This basically invokes pjsip_transport_shutdown2() + * on all transports. + * + * @param mgr The transport manager. + * @param param The function parameters. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjsip_tpmgr_shutdown_all( + pjsip_tpmgr *mgr, + const pjsip_tpmgr_shutdown_param *param); + + + /***************************************************************************** * * PUBLIC API diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h index 737421e97e..e39572f267 100644 --- a/pjsip/include/pjsua-lib/pjsua.h +++ b/pjsip/include/pjsua-lib/pjsua.h @@ -849,6 +849,11 @@ typedef enum pjsua_ip_change_op { */ PJSUA_IP_CHANGE_OP_NULL, + /** + * The restart listener process. + */ + PJSUA_IP_CHANGE_OP_SHUTDOWN_TP, + /** * The restart listener process. */ @@ -2787,6 +2792,15 @@ typedef struct pjsua_ip_change_param */ unsigned restart_lis_delay; + /** + * If set to PJ_TRUE, this will forcefully shutdown all transports. + * Note that this will shutdown TCP/TLS transports only, UDP transport + * should be restarted via restart_listener. + * + * Default : PJ_TRUE + */ + pj_bool_t shutdown_transport; + } pjsua_ip_change_param; @@ -4528,6 +4542,18 @@ typedef struct pjsua_acc_config */ pj_bool_t register_on_acc_add; + /** + * Specify whether account modification with pjsua_acc_modify() should + * automatically update registration if necessary, for example if + * account credentials change. + * + * Disable this when immediate registration is not desirable, such as + * during IP address change. + * + * Default: PJ_FALSE. + */ + pj_bool_t disable_reg_on_modify; + /** * Specify account configuration specific to IP address change used when * calling #pjsua_handle_ip_change(). @@ -7505,7 +7531,7 @@ typedef struct pjsua_snd_dev_param */ unsigned mode; - /* + /** * The library will maintain the global sound device settings set when * opening the sound device for the first time and later can be modified * using #pjsua_snd_set_setting(). These setings are then applied to any diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h index d7ee2c68aa..08fe11fc64 100644 --- a/pjsip/include/pjsua-lib/pjsua_internal.h +++ b/pjsip/include/pjsua-lib/pjsua_internal.h @@ -772,6 +772,7 @@ void pjsua_ice_check_start_trickling(pjsua_call *call, pj_bool_t pjsua_call_media_is_changing(pjsua_call *call); pj_status_t pjsua_call_media_init(pjsua_call_media *call_med, pjmedia_type type, + const pjmedia_sdp_session *rem_sdp, const pjsua_transport_config *tcfg, int security_level, int *sip_err_code, diff --git a/pjsip/include/pjsua2/account.hpp b/pjsip/include/pjsua2/account.hpp index f6d2c8cdb2..237d6b8f69 100644 --- a/pjsip/include/pjsua2/account.hpp +++ b/pjsip/include/pjsua2/account.hpp @@ -62,6 +62,18 @@ struct AccountRegConfig : public PersistentObject */ bool registerOnAdd; + /** + * Specify whether account modification with Account::modify() should + * automatically update registration if necessary, for example if + * account credentials change. + * + * Disable this when immediate registration is not desirable, such as + * during IP address change. + * + * Default: false. + */ + bool disableRegOnModify; + /** * The optional custom SIP headers to be put in the registration * request. diff --git a/pjsip/include/pjsua2/endpoint.hpp b/pjsip/include/pjsua2/endpoint.hpp index 5392ec1cee..bfd7e4de16 100644 --- a/pjsip/include/pjsua2/endpoint.hpp +++ b/pjsip/include/pjsua2/endpoint.hpp @@ -347,6 +347,15 @@ struct IpChangeParam { */ unsigned restartLisDelay; + /** + * If set to PJ_TRUE, this will forcefully shutdown all transports. + * Note that this will shutdown TCP/TLS transports only, UDP transport + * should be restarted via restart_listener. + * + * Default : PJ_TRUE + */ + bool shutdownTransport; + public: /** * Constructor. diff --git a/pjsip/src/pjsip/sip_dialog.c b/pjsip/src/pjsip/sip_dialog.c index 147397ec4a..2c40106a66 100644 --- a/pjsip/src/pjsip/sip_dialog.c +++ b/pjsip/src/pjsip/sip_dialog.c @@ -474,6 +474,8 @@ pj_status_t create_uas_dialog( pjsip_user_agent *ua, if (rdata->tp_info.transport->dir == PJSIP_TP_DIR_OUTGOING) { pj_strdup(dlg->pool, &dlg->initial_dest, &rdata->tp_info.transport->remote_name.host); + PJ_LOG(5, (THIS_FILE, "Saving initial dest %.*s", + (int)dlg->initial_dest.slen, dlg->initial_dest.ptr)); } /* Init remote's contact from Contact header. @@ -1222,8 +1224,11 @@ static pj_status_t dlg_create_request_throw( pjsip_dialog *dlg, /* Copy the initial destination host to tdata. This information can be * used later by transport for transport selection. */ - if (dlg->initial_dest.slen) + if (dlg->initial_dest.slen) { pj_strdup(tdata->pool, &tdata->dest_info.name, &dlg->initial_dest); + PJ_LOG(5, (THIS_FILE, "Setting initial dest %.*s", + (int)dlg->initial_dest.slen, dlg->initial_dest.ptr)); + } /* Done. */ *p_tdata = tdata; @@ -1878,6 +1883,13 @@ static void dlg_update_routeset(pjsip_dialog *dlg, const pjsip_rx_data *rdata) { pj_strdup(dlg->pool, &dlg->initial_dest, &rdata->tp_info.transport->remote_name.host); + PJ_LOG(5, (THIS_FILE, "Saving initial dest %.*s", + (int)dlg->initial_dest.slen, dlg->initial_dest.ptr)); + } else { + /* Reset the stored remote name if the transport is a server + * transport. + */ + dlg->initial_dest.slen = 0; } /* Ignore subsequent request from remote */ diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c index 7687d17baa..1f7483152b 100644 --- a/pjsip/src/pjsip/sip_transaction.c +++ b/pjsip/src/pjsip/sip_transaction.c @@ -2144,11 +2144,15 @@ static void send_msg_callback( pjsip_send_state *send_state, else sc = PJSIP_SC_TSX_TRANSPORT_ERROR; - /* Terminate transaction, if it's not already terminated. */ - tsx_set_status_code(tsx, sc, &err); - if (tsx->state != PJSIP_TSX_STATE_TERMINATED && + /* We terminate the transaction for 502 error. For 503, + * we will retry it. + * See https://github.com/pjsip/pjproject/pull/3805 + */ + if (sc == PJSIP_SC_BAD_GATEWAY && + tsx->state != PJSIP_TSX_STATE_TERMINATED && tsx->state != PJSIP_TSX_STATE_DESTROYED) { + tsx_set_status_code(tsx, sc, &err); /* Set tsx state to TERMINATED, but release the lock * when invoking the callback, to avoid deadlock. */ @@ -2161,9 +2165,17 @@ static void send_msg_callback( pjsip_send_state *send_state, */ else if (tsx->transport_flag & TSX_HAS_PENDING_DESTROY) { + tsx_set_status_code(tsx, sc, &err); tsx_set_state( tsx, PJSIP_TSX_STATE_DESTROYED, PJSIP_EVENT_TRANSPORT_ERROR, send_state->tdata, 0); + } else if (tsx->role == PJSIP_ROLE_UAS && + tsx->transport_flag & TSX_HAS_PENDING_RESCHED && + tsx->state != PJSIP_TSX_STATE_TERMINATED && + tsx->state != PJSIP_TSX_STATE_DESTROYED) + { + tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED); + tsx_resched_retransmission(tsx); } } else { diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c index c9a810b860..34cb0bbd7f 100644 --- a/pjsip/src/pjsip/sip_transport.c +++ b/pjsip/src/pjsip/sip_transport.c @@ -1282,8 +1282,10 @@ PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr, /* Allocate new entry for the freelist. */ for (; i < PJSIP_TRANSPORT_ENTRY_ALLOC_CNT; ++i) { tp_add = PJ_POOL_ZALLOC_T(mgr->pool, transport); - if (!tp_add) + if (!tp_add){ + pj_lock_release(mgr->lock); return PJ_ENOMEM; + } pj_list_init(tp_add); pj_list_push_back(&mgr->tp_entry_freelist, tp_add); } @@ -1985,6 +1987,60 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_destroy( pjsip_tpmgr *mgr ) } +/** + * Initialize transports shutdown parameter with default values. + * + * @param prm The parameter to be initialized. + */ +PJ_DEF(void) pjsip_tpmgr_shutdown_param_default( + pjsip_tpmgr_shutdown_param *prm) +{ + pj_bzero(prm, sizeof(*prm)); + prm->force = PJ_TRUE; + prm->include_udp = PJ_TRUE; +} + +/* + * Shutdown all transports. + */ +PJ_DEF(pj_status_t) pjsip_tpmgr_shutdown_all( + pjsip_tpmgr *mgr, + const pjsip_tpmgr_shutdown_param *prm) +{ + pj_hash_iterator_t itr_val; + pj_hash_iterator_t *itr; + + PJ_ASSERT_RETURN(mgr, PJ_EINVAL); + + PJ_LOG(3, (THIS_FILE, "Shutting down all transports")); + + pj_lock_acquire(mgr->lock); + + itr = pj_hash_first(mgr->table, &itr_val); + while (itr) { + transport *tp_entry = (transport*)pj_hash_this(mgr->table, itr); + if (tp_entry) { + transport *tp_iter = tp_entry; + do { + pjsip_transport *tp = tp_iter->tp; + if (prm->include_udp || + ((tp->key.type & ~PJSIP_TRANSPORT_IPV6) != + PJSIP_TRANSPORT_UDP)) + { + pjsip_transport_shutdown2(tp, prm->force); + } + tp_iter = tp_iter->next; + } while (tp_iter != tp_entry); + } + itr = pj_hash_next(mgr->table, itr); + } + + pj_lock_release(mgr->lock); + + return PJ_SUCCESS; +} + + /* * pjsip_tpmgr_receive_packet() * @@ -2398,6 +2454,7 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr, (sel->u.ip_ver == PJSIP_TPSELECTOR_USE_IPV6_ONLY && pjsip_transport_type_get_af(type) != pj_AF_INET6())) { + pj_lock_release(mgr->lock); TRACE_((THIS_FILE, "Address type in tpsel not matched")); return PJSIP_ETPNOTSUITABLE; } diff --git a/pjsip/src/pjsip/sip_util.c b/pjsip/src/pjsip/sip_util.c index 4c5b3265c7..1167093166 100644 --- a/pjsip/src/pjsip/sip_util.c +++ b/pjsip/src/pjsip/sip_util.c @@ -1409,7 +1409,7 @@ stateless_send_resolver_callback( pj_status_t status, if (tdata->tp_sel.type == PJSIP_TPSELECTOR_IP_VER) { PJ_LOG(5, (THIS_FILE, "Resorting target addresses based on " "%s preference", - tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_PREFER_IPV4? + tdata->tp_sel.u.ip_ver <= PJSIP_TPSELECTOR_PREFER_IPV4? "IPv4": "IPv6")); if (tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_PREFER_IPV4) resort_address(&tdata->dest_info.addr, pj_AF_INET()); @@ -1463,6 +1463,28 @@ PJ_DEF(pj_status_t) pjsip_endpt_send_request_stateless(pjsip_endpoint *endpt, if (!tdata->dest_info.name.slen) { pj_strdup(tdata->pool, &tdata->dest_info.name, &dest_info.addr.host); + } else { + /* Check if: + * - User configures transport to use a specific IP version + * - The IP version doesn't match with destination info + */ + if (tdata->tp_sel.type == PJSIP_TPSELECTOR_IP_VER && + ((tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_USE_IPV4_ONLY && + (dest_info.type & PJSIP_TRANSPORT_IPV6) != 0) || + (tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_USE_IPV6_ONLY && + (dest_info.type & PJSIP_TRANSPORT_IPV6) == 0))) + { + PJ_LOG(5, (THIS_FILE, "Using initial dest %.*s", + (int)tdata->dest_info.name.slen, + tdata->dest_info.name.ptr)); + pj_strdup(tdata->pool, &dest_info.addr.host, + &tdata->dest_info.name); + if (tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_USE_IPV4_ONLY) { + dest_info.type &= ~PJSIP_TRANSPORT_IPV6; + } else { + dest_info.type |= PJSIP_TRANSPORT_IPV6; + } + } } pjsip_endpt_resolve( endpt, tdata->pool, &dest_info, stateless_data, diff --git a/pjsip/src/pjsua-lib/pjsua_acc.c b/pjsip/src/pjsua-lib/pjsua_acc.c index ba4bc97cca..fd04e5d83f 100644 --- a/pjsip/src/pjsua-lib/pjsua_acc.c +++ b/pjsip/src/pjsua-lib/pjsua_acc.c @@ -462,6 +462,12 @@ PJ_DEF(pj_status_t) pjsua_acc_add( const pjsua_acc_config *cfg, PJ_ASSERT_RETURN(pjsua_var.acc_cnt < PJ_ARRAY_SIZE(pjsua_var.acc), PJ_ETOOMANY); +#if !PJ_HAS_IPV6 + PJ_ASSERT_RETURN(cfg->ipv6_sip_use == PJSUA_IPV6_DISABLED, PJ_EINVAL); + PJ_ASSERT_RETURN(cfg->ipv6_media_use == PJSUA_IPV6_DISABLED, PJ_EINVAL); + PJ_ASSERT_RETURN(cfg->nat64_opt == PJSUA_IPV6_DISABLED, PJ_EINVAL); +#endif + /* Must have a transport */ PJ_ASSERT_RETURN(pjsua_var.tpdata[0].data.ptr != NULL, PJ_EINVALIDOP); @@ -834,8 +840,7 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, pjsip_name_addr *id_name_addr = NULL; pjsip_sip_uri *id_sip_uri = NULL; pjsip_sip_uri *reg_sip_uri = NULL; - pj_uint32_t local_route_crc, global_route_crc; - pjsip_route_hdr global_route; + pj_uint32_t local_route_crc; pjsip_route_hdr local_route; pj_str_t acc_proxy[PJSUA_ACC_MAX_PROXIES]; pj_bool_t update_reg = PJ_FALSE; @@ -846,6 +851,12 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, PJ_ASSERT_RETURN(acc_id>=0 && acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc), PJ_EINVAL); +#if !PJ_HAS_IPV6 + PJ_ASSERT_RETURN(cfg->ipv6_sip_use == PJSUA_IPV6_DISABLED, PJ_EINVAL); + PJ_ASSERT_RETURN(cfg->ipv6_media_use == PJSUA_IPV6_DISABLED, PJ_EINVAL); + PJ_ASSERT_RETURN(cfg->nat64_opt == PJSUA_IPV6_DISABLED, PJ_EINVAL); +#endif + PJ_LOG(4,(THIS_FILE, "Modifying account %d", acc_id)); pj_log_push_indent(); @@ -887,6 +898,7 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, /* Registrar URI */ if (pj_strcmp(&acc->cfg.reg_uri, &cfg->reg_uri) && cfg->reg_uri.slen) { pjsip_uri *reg_uri; + unsigned rcnt; /* Need to parse reg_uri to get the elements: */ reg_uri = pjsip_parse_uri(acc->pool, cfg->reg_uri.ptr, @@ -907,6 +919,23 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, } reg_sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(reg_uri); + + /* Clear route headers from the previous registrar. */ + rcnt = (unsigned)pj_list_size(&acc->route_set); + if (rcnt != pjsua_var.ua_cfg.outbound_proxy_cnt + acc->cfg.proxy_cnt) { + pjsip_route_hdr *hr; + unsigned i; + + for (i=pjsua_var.ua_cfg.outbound_proxy_cnt + acc->cfg.proxy_cnt, + hr=acc->route_set.prev; + iprev; + pj_list_erase(hr); + hr = prev; + } + } } /* REGISTER header list */ @@ -918,22 +947,6 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, /* SUBSCRIBE header list */ update_hdr_list(acc->pool, &acc->cfg.sub_hdr_list, &cfg->sub_hdr_list); - /* Global outbound proxy */ - global_route_crc = calc_proxy_crc(pjsua_var.ua_cfg.outbound_proxy, - pjsua_var.ua_cfg.outbound_proxy_cnt); - if (global_route_crc != acc->global_route_crc) { - pjsip_route_hdr *r; - - /* Copy from global outbound proxies */ - pj_list_init(&global_route); - r = pjsua_var.outbound_proxy.next; - while (r != &pjsua_var.outbound_proxy) { - pj_list_push_back(&global_route, - pjsip_hdr_shallow_clone(acc->pool, r)); - r = r->next; - } - } - /* Account proxy */ local_route_crc = calc_proxy_crc(cfg->proxy, cfg->proxy_cnt); if (local_route_crc != acc->local_route_crc) { @@ -966,6 +979,33 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, local_route_crc = calc_proxy_crc(acc_proxy, cfg->proxy_cnt); } + if (local_route_crc != acc->local_route_crc) { + unsigned i; + pjsip_route_hdr *r = &acc->route_set; + + /* Remove the current account proxies from the route set */ + for (i = 0; i < pjsua_var.ua_cfg.outbound_proxy_cnt; i++) + r = r->next; + for (i = 0; i < acc->cfg.proxy_cnt; ++i) { + pjsip_route_hdr *r_ = r->next; + pj_list_erase(r_); + } + + /* Insert new proxy setting to the route set */ + pj_list_insert_list_after(r, &local_route); + + /* Update the proxy setting */ + acc->cfg.proxy_cnt = cfg->proxy_cnt; + for (i = 0; i < cfg->proxy_cnt; ++i) + acc->cfg.proxy[i] = acc_proxy[i]; + + /* Update local route CRC */ + acc->local_route_crc = local_route_crc; + + update_reg = PJ_TRUE; + unreg_first = PJ_TRUE; + } + /* == Apply the new config == */ @@ -981,6 +1021,21 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, unreg_first = PJ_TRUE; } + /* SIP IP version preference */ + if (acc->cfg.ipv6_sip_use != cfg->ipv6_sip_use) { + acc->cfg.ipv6_sip_use = cfg->ipv6_sip_use; + update_reg = PJ_TRUE; + unreg_first = PJ_TRUE; + + /* Set client registration's transport based on acc's config. */ + if (acc->regc) { + pjsip_tpselector tp_sel; + + pjsua_init_tpselector(acc->index, &tp_sel); + pjsip_regc_set_transport(acc->regc, &tp_sel); + } + } + /* User data */ acc->cfg.user_data = cfg->user_data; @@ -1160,53 +1215,6 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, unreg_first = PJ_TRUE; } - /* Global outbound proxy */ - if (global_route_crc != acc->global_route_crc) { - unsigned i; - pj_size_t rcnt; - - /* Remove the outbound proxies from the route set */ - rcnt = pj_list_size(&acc->route_set); - for (i=0; i < rcnt - acc->cfg.proxy_cnt; ++i) { - pjsip_route_hdr *r = acc->route_set.next; - pj_list_erase(r); - } - - /* Insert the outbound proxies to the beginning of route set */ - pj_list_merge_first(&acc->route_set, &global_route); - - /* Update global route CRC */ - acc->global_route_crc = global_route_crc; - - update_reg = PJ_TRUE; - unreg_first = PJ_TRUE; - } - - /* Account proxy */ - if (local_route_crc != acc->local_route_crc) { - unsigned i; - - /* Remove the current account proxies from the route set */ - for (i=0; i < acc->cfg.proxy_cnt; ++i) { - pjsip_route_hdr *r = acc->route_set.prev; - pj_list_erase(r); - } - - /* Insert new proxy setting to the route set */ - pj_list_merge_last(&acc->route_set, &local_route); - - /* Update the proxy setting */ - acc->cfg.proxy_cnt = cfg->proxy_cnt; - for (i = 0; i < cfg->proxy_cnt; ++i) - acc->cfg.proxy[i] = acc_proxy[i]; - - /* Update local route CRC */ - acc->local_route_crc = local_route_crc; - - update_reg = PJ_TRUE; - unreg_first = PJ_TRUE; - } - /* Credential info */ { unsigned i; @@ -1394,8 +1402,10 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, acc->cfg.rtp_cfg.bound_addr = b_addr; } - acc->cfg.nat64_opt = cfg->nat64_opt; - acc->cfg.ipv6_media_use = cfg->ipv6_media_use; + acc->cfg.nat64_opt = PJ_HAS_IPV6? cfg->nat64_opt : + PJSUA_NAT64_DISABLED; + acc->cfg.ipv6_media_use = PJ_HAS_IPV6? cfg->ipv6_media_use : + PJSUA_IPV6_DISABLED; acc->cfg.enable_rtcp_mux = cfg->enable_rtcp_mux; acc->cfg.lock_codec = cfg->lock_codec; acc->cfg.enable_rtcp_xr = cfg->enable_rtcp_xr; @@ -1444,7 +1454,7 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, acc->cfg.call_hold_type = cfg->call_hold_type; /* Unregister first */ - if (unreg_first) { + if (unreg_first && !cfg->disable_reg_on_modify) { if (acc->regc) { status = pjsua_acc_set_registration(acc->index, PJ_FALSE); if (status != PJ_SUCCESS) { @@ -1464,7 +1474,7 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id, } /* Update registration */ - if (update_reg) { + if (update_reg && !cfg->disable_reg_on_modify) { /* If accounts has registration enabled, start registration */ if (acc->cfg.reg_uri.slen) { status = pjsua_acc_set_registration(acc->index, PJ_TRUE); @@ -2751,15 +2761,21 @@ static pj_status_t pjsua_regc_init(int acc_id) pj_bool_t pjsua_sip_acc_is_using_ipv6(pjsua_acc_id acc_id) { +#if PJ_HAS_IPV6 pjsua_acc *acc = &pjsua_var.acc[acc_id]; return ((acc->tp_type & PJSIP_TRANSPORT_IPV6) == PJSIP_TRANSPORT_IPV6 || pjsua_var.acc[acc_id].cfg.ipv6_sip_use == PJSUA_IPV6_ENABLED_USE_IPV6_ONLY); +#else + PJ_UNUSED_ARG(acc_id); + return PJ_FALSE; +#endif } static int sip_acc_get_pref_ip_ver(pjsua_acc_id acc_id) { +#if PJ_HAS_IPV6 pjsua_acc *acc = &pjsua_var.acc[acc_id]; if ((acc->tp_type & PJSIP_TRANSPORT_IPV6) == PJSIP_TRANSPORT_IPV6 || @@ -2784,6 +2800,10 @@ static int sip_acc_get_pref_ip_ver(pjsua_acc_id acc_id) */ return 0; } +#else + PJ_UNUSED_ARG(acc_id); + return 4; +#endif } pj_bool_t pjsua_sip_acc_is_using_stun(pjsua_acc_id acc_id) @@ -3641,10 +3661,10 @@ pj_status_t pjsua_acc_get_uac_addr(pjsua_acc_id acc_id, goto on_return; } - if (ip_addr_ver == 6 || sip_pref_ip == 6) { + if (PJ_HAS_IPV6 && (ip_addr_ver == 6 || sip_pref_ip == 6)) { /* Get IPv6 address if dest host is IPv6 or we prefer IPv6. */ af = pj_AF_INET6(); - } else if (ip_addr_ver == 4 || sip_pref_ip == 4) { + } else if (!PJ_HAS_IPV6 || ip_addr_ver == 4 || sip_pref_ip == 4) { /* Get IPv4 address if dest host is IPv4 or we prefer IPv4. */ af = pj_AF_INET(); } else { @@ -3664,7 +3684,9 @@ pj_status_t pjsua_acc_get_uac_addr(pjsua_acc_id acc_id, /* Get fallback address, only if the host is not IP address and * account is not bound to a certain transport. */ - if (ip_addr_ver == 0 && acc->tp_type == PJSIP_TRANSPORT_UNSPECIFIED) { + if (PJ_HAS_IPV6 && ip_addr_ver == 0 && + acc->tp_type == PJSIP_TRANSPORT_UNSPECIFIED) + { unsigned cnt = 1; /* If first address is IPv4, fallback to IPv6, and vice versa. */ @@ -3960,7 +3982,7 @@ PJ_DEF(pj_status_t) pjsua_acc_create_uas_contact( pj_pool_t *pool, pjsua_sip_acc_is_using_ipv6(acc_id) || (rdata->tp_info.transport->key.type & PJSIP_TRANSPORT_IPV6)) { - if (acc->cfg.ipv6_sip_use == PJSUA_IPV6_DISABLED) + if (!PJ_HAS_IPV6 || acc->cfg.ipv6_sip_use == PJSUA_IPV6_DISABLED) return PJSIP_EUNSUPTRANSPORT; tp_type = (pjsip_transport_type_e) (((int)tp_type) | PJSIP_TRANSPORT_IPV6); @@ -4392,6 +4414,8 @@ pj_status_t pjsua_acc_handle_call_on_ip_change(pjsua_acc *acc) { for (i = 0; i < pjsua_var.ua_cfg.max_calls; ++i) { pjsua_call_info call_info; + pjsua_call *call; + pjsip_dialog *dlg = NULL; if (!pjsua_call_is_active(i) || pjsua_var.calls[i].acc_id != acc->index || @@ -4400,6 +4424,21 @@ pj_status_t pjsua_acc_handle_call_on_ip_change(pjsua_acc *acc) continue; } + status = acquire_call("call_tpsel_on_ip_change()", + i, &call, &dlg); + if (status == PJ_SUCCESS) { + pjsip_tpselector tp_sel; + + /* Set dialog's transport based on acc's config. */ + pjsua_init_tpselector(call->acc_id, &tp_sel); + pjsip_dlg_set_transport(dlg, &tp_sel); + + pjsip_dlg_dec_lock(dlg); + } else { + PJ_LOG(4, (THIS_FILE, "Failed to update call %d's transport " + "selector", i)); + } + if ((acc->cfg.ip_change_cfg.hangup_calls) && (call_info.state >= PJSIP_INV_STATE_EARLY)) { @@ -4455,9 +4494,6 @@ pj_status_t pjsua_acc_handle_call_on_ip_change(pjsua_acc *acc) /* Check if remote support SIP UPDATE method */ if (use_update) { - pjsua_call *call; - pjsip_dialog *dlg = NULL; - PJ_LOG(5, (THIS_FILE, "Call #%d: IP change is configured " "to using UPDATE", i)); diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index 84ebf093c6..687ebd41f1 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -374,8 +374,10 @@ PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg) cfg->register_on_acc_add = PJ_TRUE; cfg->mwi_expires = PJSIP_MWI_DEFAULT_EXPIRES; - cfg->ipv6_sip_use = PJSUA_IPV6_ENABLED_NO_PREFERENCE; - cfg->ipv6_media_use = PJSUA_IPV6_ENABLED_PREFER_IPV4; + cfg->ipv6_sip_use = PJ_HAS_IPV6? PJSUA_IPV6_ENABLED_NO_PREFERENCE : + PJSUA_IPV6_DISABLED; + cfg->ipv6_media_use = PJ_HAS_IPV6? PJSUA_IPV6_ENABLED_PREFER_IPV4 : + PJSUA_IPV6_DISABLED; cfg->media_stun_use = PJSUA_STUN_RETRY_ON_FAILURE; cfg->ip_change_cfg.shutdown_tp = PJ_TRUE; @@ -1216,6 +1218,10 @@ PJ_DEF(pj_status_t) pjsua_init( const pjsua_config *ua_cfg, } } +#if !PJ_HAS_IPV6 + pjsua_var.ua_cfg.stun_try_ipv6 = PJ_FALSE; +#endif + /* Start resolving STUN server */ status = resolve_stun_server(PJ_FALSE, PJ_FALSE, 0); if (status != PJ_SUCCESS && status != PJ_EPENDING) { @@ -1930,14 +1936,14 @@ PJ_DEF(pj_status_t) pjsua_destroy2(unsigned flags) /* Terminate all calls. */ if ((flags & PJSUA_DESTROY_NO_TX_MSG) == 0) { pjsua_call_hangup_all(); - } - - /* Deinit media channel of all calls (see #1717) */ - for (i=0; i<(int)pjsua_var.ua_cfg.max_calls; ++i) { - /* TODO: check if we're not allowed to send to network in the - * "flags", and if so do not do TURN allocation... - */ - pjsua_media_channel_deinit(i); + } else { + /* Deinit media channel of all calls (see #1717) */ + for (i=0; i<(int)pjsua_var.ua_cfg.max_calls; ++i) { + /* TODO: check if we're not allowed to send to network in the + * "flags", and if so do not do TURN allocation... + */ + pjsua_media_channel_deinit(i); + } } /* Set all accounts to offline */ @@ -3255,6 +3261,7 @@ PJ_DEF(void) pjsua_ip_change_param_default(pjsua_ip_change_param *param) pj_bzero(param, sizeof(*param)); param->restart_listener = PJ_TRUE; param->restart_lis_delay = PJSUA_TRANSPORT_RESTART_DELAY_TIME; + param->shutdown_transport = PJ_TRUE; } @@ -3985,6 +3992,31 @@ PJ_DEF(pj_status_t) pjsua_handle_ip_change(const pjsua_ip_change_param *param) PJ_LOG(4,(THIS_FILE,"IP change temporarily ignores request timeout")); } + /* Shutdown all TCP/TLS transports */ + if (param->shutdown_transport) { + pjsip_tpmgr_shutdown_param param; + + pjsip_tpmgr_shutdown_param_default(¶m); + param.include_udp = PJ_FALSE; + + PJ_LOG(4,(THIS_FILE, "IP change shutting down transports..")); + status = pjsip_tpmgr_shutdown_all( + pjsip_endpt_get_tpmgr(pjsua_var.endpt), + ¶m); + + /* Provide dummy info instead of NULL info to avoid possible crash + * (if app does not check). + */ + if (pjsua_var.ua_cfg.cb.on_ip_change_progress) { + pjsua_ip_change_op_info info; + + pj_bzero(&info, sizeof(info)); + pjsua_var.ua_cfg.cb.on_ip_change_progress( + PJSUA_IP_CHANGE_OP_SHUTDOWN_TP, + status, &info); + } + } + if (param->restart_listener) { PJSUA_LOCK(); /* Restart listener/transport, handle_ip_change_on_acc() will diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index b7dde8bdd3..6e3317b197 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -246,9 +246,11 @@ pj_status_t pjsua_media_subsys_destroy(unsigned flags) return PJ_SUCCESS; } -static int get_media_ip_version(pjsua_call_media *call_med) +static int get_media_ip_version(pjsua_call_media *call_med, + const pjmedia_sdp_session *rem_sdp) { - pjmedia_sdp_session *rem_sdp = call_med->call->async_call.rem_sdp; +#if PJ_HAS_IPV6 + pjsua_ipv6_use ipv6_use; ipv6_use = pjsua_var.acc[call_med->call->acc_id].cfg.ipv6_media_use; @@ -276,6 +278,10 @@ static int get_media_ip_version(pjsua_call_media *call_med) return 6; } } +#else + PJ_UNUSED_ARG(call_med); + PJ_UNUSED_ARG(rem_sdp); +#endif /* Use IPv4. */ return 4; @@ -287,7 +293,8 @@ static int get_media_ip_version(pjsua_call_media *call_med) */ static pj_status_t create_rtp_rtcp_sock(pjsua_call_media *call_med, const pjsua_transport_config *cfg, - pjmedia_sock_info *skinfo) + pjmedia_sock_info *skinfo, + const pjmedia_sdp_session *rem_sdp) { enum { RTP_RETRY = 100 @@ -302,8 +309,8 @@ static pj_status_t create_rtp_rtcp_sock(pjsua_call_media *call_med, pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id]; pj_sock_t sock[2]; - use_ipv6 = (get_media_ip_version(call_med) == 6); - use_nat64 = (acc->cfg.nat64_opt != PJSUA_NAT64_DISABLED); + use_ipv6 = (get_media_ip_version(call_med, rem_sdp) == 6); + use_nat64 = PJ_HAS_IPV6 && (acc->cfg.nat64_opt != PJSUA_NAT64_DISABLED); af = (use_ipv6 || use_nat64) ? pj_AF_INET6() : pj_AF_INET(); /* Make sure STUN server resolution has completed */ @@ -705,12 +712,13 @@ static pj_status_t create_rtp_rtcp_sock(pjsua_call_media *call_med, /* Create normal UDP media transports */ static pj_status_t create_udp_media_transport(const pjsua_transport_config *cfg, - pjsua_call_media *call_med) + pjsua_call_media *call_med, + const pjmedia_sdp_session *rem_sdp) { pjmedia_sock_info skinfo; pj_status_t status; - status = create_rtp_rtcp_sock(call_med, cfg, &skinfo); + status = create_rtp_rtcp_sock(call_med, cfg, &skinfo, rem_sdp); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Unable to create RTP/RTCP socket", status); @@ -745,7 +753,8 @@ static pj_status_t create_udp_media_transport(const pjsua_transport_config *cfg, /* Create loop media transport */ static pj_status_t create_loop_media_transport( const pjsua_transport_config *cfg, - pjsua_call_media *call_med) + pjsua_call_media *call_med, + const pjmedia_sdp_session *rem_sdp) { pj_status_t status; pjmedia_loop_tp_setting opt; @@ -753,8 +762,8 @@ static pj_status_t create_loop_media_transport( int af; pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id]; - use_ipv6 = (get_media_ip_version(call_med) == 6); - use_nat64 = (acc->cfg.nat64_opt != PJSUA_NAT64_DISABLED); + use_ipv6 = (get_media_ip_version(call_med, rem_sdp) == 6); + use_nat64 = PJ_HAS_IPV6 && (acc->cfg.nat64_opt != PJSUA_NAT64_DISABLED); af = (use_ipv6 || use_nat64) ? pj_AF_INET6() : pj_AF_INET(); pjmedia_loop_tp_setting_default(&opt); @@ -1022,6 +1031,7 @@ static pj_status_t parse_host_port(const pj_str_t *host_port, static pj_status_t create_ice_media_transport( const pjsua_transport_config *cfg, pjsua_call_media *call_med, + const pjmedia_sdp_session *remote_sdp, pj_bool_t async) { char stunip[PJ_INET6_ADDRSTRLEN]; @@ -1036,8 +1046,8 @@ static pj_status_t create_ice_media_transport( pjmedia_sdp_session *rem_sdp; acc_cfg = &pjsua_var.acc[call_med->call->acc_id].cfg; - use_ipv6 = (get_media_ip_version(call_med) == 6); - use_nat64 = (acc_cfg->nat64_opt != PJSUA_NAT64_DISABLED); + use_ipv6 = (get_media_ip_version(call_med, remote_sdp) == 6); + use_nat64 = PJ_HAS_IPV6 && (acc_cfg->nat64_opt != PJSUA_NAT64_DISABLED); /* Make sure STUN server resolution has completed */ if (pjsua_media_acc_is_using_stun(call_med->call->acc_id)) { @@ -2006,6 +2016,7 @@ pj_bool_t pjsua_call_media_is_changing(pjsua_call *call) /* Initialize the media line */ pj_status_t pjsua_call_media_init(pjsua_call_media *call_med, pjmedia_type type, + const pjmedia_sdp_session *rem_sdp, const pjsua_transport_config *tcfg, int security_level, int *sip_err_code, @@ -2049,9 +2060,10 @@ pj_status_t pjsua_call_media_init(pjsua_call_media *call_med, pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_CREATING); if (acc->cfg.use_loop_med_tp) { - status = create_loop_media_transport(tcfg, call_med); + status = create_loop_media_transport(tcfg, call_med, rem_sdp); } else if (acc->cfg.ice_cfg.enable_ice) { - status = create_ice_media_transport(tcfg, call_med, async); + status = create_ice_media_transport(tcfg, call_med, rem_sdp, + async); if (async && status == PJ_EPENDING) { /* We will resume call media initialization in the * on_ice_complete() callback. @@ -2062,7 +2074,7 @@ pj_status_t pjsua_call_media_init(pjsua_call_media *call_med, return PJ_EPENDING; } } else { - status = create_udp_media_transport(tcfg, call_med); + status = create_udp_media_transport(tcfg, call_med, rem_sdp); } if (status != PJ_SUCCESS) { @@ -2538,15 +2550,17 @@ pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, PJ_LOG(4,(THIS_FILE, "Call %d: setting media direction " "#%d to %d.", call_id, mi, call_med->def_dir)); - } else if (!reinit) { - /* Initialize default initial media direction as bidirectional */ + } else if (!reinit || mi >= call->med_cnt) { + /* Initialize default media direction as bidirectional, + * for initial media or newly added media. + */ call_med->def_dir = PJMEDIA_DIR_ENCODING_DECODING; } if (enabled) { call_med->enable_rtcp_mux = acc->cfg.enable_rtcp_mux; - status = pjsua_call_media_init(call_med, media_type, + status = pjsua_call_media_init(call_med, media_type, rem_sdp, &acc->cfg.rtp_cfg, security_level, sip_err_code, async, @@ -2825,9 +2839,11 @@ pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id, pj_bool_t use_ipv6; pj_bool_t use_nat64; - use_ipv6 = (pjsua_var.acc[call->acc_id].cfg.ipv6_media_use != + use_ipv6 = PJ_HAS_IPV6 && + (pjsua_var.acc[call->acc_id].cfg.ipv6_media_use != PJSUA_IPV6_DISABLED); - use_nat64 = (pjsua_var.acc[call->acc_id].cfg.nat64_opt != + use_nat64 = PJ_HAS_IPV6 && + (pjsua_var.acc[call->acc_id].cfg.nat64_opt != PJSUA_NAT64_DISABLED); m->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn); diff --git a/pjsip/src/pjsua-lib/pjsua_vid.c b/pjsip/src/pjsua-lib/pjsua_vid.c index d7f701d492..066bd52f71 100644 --- a/pjsip/src/pjsua-lib/pjsua_vid.c +++ b/pjsip/src/pjsua-lib/pjsua_vid.c @@ -2092,7 +2092,7 @@ static pj_status_t call_add_video(pjsua_call *call, /* Initialize call media */ call_med = &call->media_prov[call->med_prov_cnt++]; - status = pjsua_call_media_init(call_med, PJMEDIA_TYPE_VIDEO, + status = pjsua_call_media_init(call_med, PJMEDIA_TYPE_VIDEO, NULL, &acc_cfg->rtp_cfg, call->secure_level, NULL, PJ_FALSE, NULL); if (status != PJ_SUCCESS) @@ -2138,6 +2138,7 @@ static pj_status_t call_add_video(pjsua_call *call, pjmedia_sdp_media_add_attr(sdp_m, a); } + call_med->def_dir = dir; /* Update SDP media line by media transport */ status = pjmedia_transport_encode_sdp(call_med->tp, pool, @@ -2241,7 +2242,7 @@ static pj_status_t call_modify_video(pjsua_call *call, call->opt.vid_cnt++; } - status = pjsua_call_media_init(call_med, PJMEDIA_TYPE_VIDEO, + status = pjsua_call_media_init(call_med, PJMEDIA_TYPE_VIDEO, NULL, &acc_cfg->rtp_cfg, call->secure_level, NULL, PJ_FALSE, NULL); if (status != PJ_SUCCESS) diff --git a/pjsip/src/pjsua2/account.cpp b/pjsip/src/pjsua2/account.cpp index 025ca3acc7..5f00dbdbde 100644 --- a/pjsip/src/pjsua2/account.cpp +++ b/pjsip/src/pjsua2/account.cpp @@ -575,6 +575,7 @@ void AccountConfig::toPj(pjsua_acc_config &ret) const // AccountRegConfig ret.reg_uri = str2Pj(regConfig.registrarUri); ret.register_on_acc_add = regConfig.registerOnAdd; + ret.disable_reg_on_modify = regConfig.disableRegOnModify; ret.reg_timeout = regConfig.timeoutSec; ret.reg_retry_interval = regConfig.retryIntervalSec; ret.reg_first_retry_interval= regConfig.firstRetryIntervalSec; @@ -734,6 +735,7 @@ void AccountConfig::fromPj(const pjsua_acc_config &prm, // AccountRegConfig regConfig.registrarUri = pj2Str(prm.reg_uri); regConfig.registerOnAdd = (prm.register_on_acc_add != 0); + regConfig.disableRegOnModify= (prm.disable_reg_on_modify != 0); regConfig.timeoutSec = prm.reg_timeout; regConfig.retryIntervalSec = prm.reg_retry_interval; regConfig.firstRetryIntervalSec = prm.reg_first_retry_interval; diff --git a/pjsip/src/pjsua2/endpoint.cpp b/pjsip/src/pjsua2/endpoint.cpp index 5cea0c3d7d..451b583986 100644 --- a/pjsip/src/pjsua2/endpoint.cpp +++ b/pjsip/src/pjsua2/endpoint.cpp @@ -230,6 +230,7 @@ pjsua_ip_change_param IpChangeParam::toPj() const param.restart_listener = restartListener; param.restart_lis_delay = restartLisDelay; + param.shutdown_transport = shutdownTransport; return param; } @@ -239,6 +240,7 @@ void IpChangeParam::fromPj(const pjsua_ip_change_param ¶m) { restartListener = PJ2BOOL(param.restart_listener); restartLisDelay = param.restart_lis_delay; + shutdownTransport = PJ2BOOL(param.shutdown_transport); } ///////////////////////////////////////////////////////////////////////////////