Improve IP address change IPv4 <-> IPv6 (#3910)

This commit is contained in:
sauwming 2024-04-03 18:04:51 +08:00 committed by GitHub
parent 86b7dd48b5
commit e7e7f28f16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 84 additions and 9 deletions

View File

@ -1848,8 +1848,6 @@ static void ui_handle_ip_change()
status = pjsua_handle_ip_change(&param);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "IP change failed", status);
} else {
PJ_LOG(3,(THIS_FILE, "IP change succeeded"));
}
}

View File

@ -4552,6 +4552,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().

View File

@ -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.

View File

@ -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,8 @@ 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.

View File

@ -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,

View File

@ -1026,6 +1026,14 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id,
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 */
@ -1446,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) {
@ -1466,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);
@ -4335,6 +4343,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 ||
@ -4343,6 +4353,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))
{
@ -4398,9 +4423,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));

View File

@ -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;