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); status = pjsua_handle_ip_change(&param);
if (status != PJ_SUCCESS) { if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "IP change failed", status); 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; 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 * Specify account configuration specific to IP address change used when
* calling #pjsua_handle_ip_change(). * calling #pjsua_handle_ip_change().

View File

@ -62,6 +62,18 @@ struct AccountRegConfig : public PersistentObject
*/ */
bool registerOnAdd; 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 * The optional custom SIP headers to be put in the registration
* request. * 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) { if (rdata->tp_info.transport->dir == PJSIP_TP_DIR_OUTGOING) {
pj_strdup(dlg->pool, &dlg->initial_dest, pj_strdup(dlg->pool, &dlg->initial_dest,
&rdata->tp_info.transport->remote_name.host); &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. /* 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 /* Copy the initial destination host to tdata. This information can be
* used later by transport for transport selection. * 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_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. */ /* Done. */
*p_tdata = tdata; *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, pj_strdup(dlg->pool, &dlg->initial_dest,
&rdata->tp_info.transport->remote_name.host); &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 { } else {
/* Reset the stored remote name if the transport is a server /* Reset the stored remote name if the transport is a server
* transport. * transport.

View File

@ -1409,7 +1409,7 @@ stateless_send_resolver_callback( pj_status_t status,
if (tdata->tp_sel.type == PJSIP_TPSELECTOR_IP_VER) { if (tdata->tp_sel.type == PJSIP_TPSELECTOR_IP_VER) {
PJ_LOG(5, (THIS_FILE, "Resorting target addresses based on " PJ_LOG(5, (THIS_FILE, "Resorting target addresses based on "
"%s preference", "%s preference",
tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_PREFER_IPV4? tdata->tp_sel.u.ip_ver <= PJSIP_TPSELECTOR_PREFER_IPV4?
"IPv4": "IPv6")); "IPv4": "IPv6"));
if (tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_PREFER_IPV4) if (tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_PREFER_IPV4)
resort_address(&tdata->dest_info.addr, pj_AF_INET()); 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) { if (!tdata->dest_info.name.slen) {
pj_strdup(tdata->pool, &tdata->dest_info.name, pj_strdup(tdata->pool, &tdata->dest_info.name,
&dest_info.addr.host); &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, 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; acc->cfg.ipv6_sip_use = cfg->ipv6_sip_use;
update_reg = PJ_TRUE; update_reg = PJ_TRUE;
unreg_first = 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 */ /* 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; acc->cfg.call_hold_type = cfg->call_hold_type;
/* Unregister first */ /* Unregister first */
if (unreg_first) { if (unreg_first && !cfg->disable_reg_on_modify) {
if (acc->regc) { if (acc->regc) {
status = pjsua_acc_set_registration(acc->index, PJ_FALSE); status = pjsua_acc_set_registration(acc->index, PJ_FALSE);
if (status != PJ_SUCCESS) { if (status != PJ_SUCCESS) {
@ -1466,7 +1474,7 @@ PJ_DEF(pj_status_t) pjsua_acc_modify( pjsua_acc_id acc_id,
} }
/* Update registration */ /* Update registration */
if (update_reg) { if (update_reg && !cfg->disable_reg_on_modify) {
/* If accounts has registration enabled, start registration */ /* If accounts has registration enabled, start registration */
if (acc->cfg.reg_uri.slen) { if (acc->cfg.reg_uri.slen) {
status = pjsua_acc_set_registration(acc->index, PJ_TRUE); 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) { for (i = 0; i < pjsua_var.ua_cfg.max_calls; ++i) {
pjsua_call_info call_info; pjsua_call_info call_info;
pjsua_call *call;
pjsip_dialog *dlg = NULL;
if (!pjsua_call_is_active(i) || if (!pjsua_call_is_active(i) ||
pjsua_var.calls[i].acc_id != acc->index || 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; 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) && if ((acc->cfg.ip_change_cfg.hangup_calls) &&
(call_info.state >= PJSIP_INV_STATE_EARLY)) (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 */ /* Check if remote support SIP UPDATE method */
if (use_update) { if (use_update) {
pjsua_call *call;
pjsip_dialog *dlg = NULL;
PJ_LOG(5, (THIS_FILE, "Call #%d: IP change is configured " PJ_LOG(5, (THIS_FILE, "Call #%d: IP change is configured "
"to using UPDATE", i)); "to using UPDATE", i));

View File

@ -575,6 +575,7 @@ void AccountConfig::toPj(pjsua_acc_config &ret) const
// AccountRegConfig // AccountRegConfig
ret.reg_uri = str2Pj(regConfig.registrarUri); ret.reg_uri = str2Pj(regConfig.registrarUri);
ret.register_on_acc_add = regConfig.registerOnAdd; ret.register_on_acc_add = regConfig.registerOnAdd;
ret.disable_reg_on_modify = regConfig.disableRegOnModify;
ret.reg_timeout = regConfig.timeoutSec; ret.reg_timeout = regConfig.timeoutSec;
ret.reg_retry_interval = regConfig.retryIntervalSec; ret.reg_retry_interval = regConfig.retryIntervalSec;
ret.reg_first_retry_interval= regConfig.firstRetryIntervalSec; ret.reg_first_retry_interval= regConfig.firstRetryIntervalSec;
@ -734,6 +735,7 @@ void AccountConfig::fromPj(const pjsua_acc_config &prm,
// AccountRegConfig // AccountRegConfig
regConfig.registrarUri = pj2Str(prm.reg_uri); regConfig.registrarUri = pj2Str(prm.reg_uri);
regConfig.registerOnAdd = (prm.register_on_acc_add != 0); regConfig.registerOnAdd = (prm.register_on_acc_add != 0);
regConfig.disableRegOnModify= (prm.disable_reg_on_modify != 0);
regConfig.timeoutSec = prm.reg_timeout; regConfig.timeoutSec = prm.reg_timeout;
regConfig.retryIntervalSec = prm.reg_retry_interval; regConfig.retryIntervalSec = prm.reg_retry_interval;
regConfig.firstRetryIntervalSec = prm.reg_first_retry_interval; regConfig.firstRetryIntervalSec = prm.reg_first_retry_interval;