diff --git a/pjsip-apps/src/pjsua/pjsua_app.c b/pjsip-apps/src/pjsua/pjsua_app.c index 1041fae03..e394d9160 100644 --- a/pjsip-apps/src/pjsua/pjsua_app.c +++ b/pjsip-apps/src/pjsua/pjsua_app.c @@ -694,7 +694,7 @@ static pj_status_t parse_args(int argc, char *argv[], break; case OPT_AUTO_UPDATE_NAT: /* OPT_AUTO_UPDATE_NAT */ - cur_acc->auto_update_nat = pj_strtoul(pj_cstr(&tmp, pj_optarg)); + cur_acc->allow_contact_rewrite = pj_strtoul(pj_cstr(&tmp, pj_optarg)); break; case OPT_USE_COMPACT_FORM: @@ -1148,10 +1148,10 @@ static void write_account_settings(int acc_index, pj_str_t *result) } /* */ - //if (acc_cfg->auto_update_nat) + if (acc_cfg->allow_contact_rewrite==0) { - pj_ansi_sprintf(line, "--auto-update-nat %i\n", - (int)acc_cfg->auto_update_nat); + pj_ansi_sprintf(line, "--contact-rewrite %i\n", + (int)acc_cfg->allow_contact_rewrite); pj_strcat2(result, line); } diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h index a095954a7..e6f6e2de7 100644 --- a/pjsip/include/pjsua-lib/pjsua.h +++ b/pjsip/include/pjsua-lib/pjsua.h @@ -2026,17 +2026,18 @@ typedef struct pjsua_acc_config pjsua_transport_id transport_id; /** - * This option is useful for keeping the UDP transport address up to - * date with the NAT public mapped address. When this option is - * enabled and STUN is configured, the library will keep track of - * the public IP address from the response of REGISTER request. Once - * it detects that the address has changed, it will unregister current - * Contact, update the UDP transport address, and register a new - * Contact to the registrar. + * This option is used to update the UDP transport address and the Contact + * header of REGISTER request. When this option is enabled, the library + * will keep track of the public IP address from the response of REGISTER + * request. Once it detects that the address has changed, it will + * unregister current Contact, update the Contact with transport address + * learned from Via header, and register a new Contact to the registrar. + * This will also update the public name of UDP transport if STUN is + * configured. * * Default: 1 (yes) */ - pj_bool_t auto_update_nat; + pj_bool_t allow_contact_rewrite; /** * Set the interval for periodic keep-alive transmission for this account. diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h index fb317e580..df981ed8e 100644 --- a/pjsip/include/pjsua-lib/pjsua_internal.h +++ b/pjsip/include/pjsua-lib/pjsua_internal.h @@ -84,6 +84,7 @@ typedef struct pjsua_acc int index; /**< Index in accounts array. */ pj_str_t display; /**< Display name, if any. */ pj_str_t user_part; /**< User part of local URI. */ + pj_str_t contact; /**< Our Contact URI for REGISTER */ pj_str_t srv_domain; /**< Host part of reg server. */ int srv_port; /**< Port number of reg server. */ diff --git a/pjsip/src/pjsua-lib/pjsua_acc.c b/pjsip/src/pjsua-lib/pjsua_acc.c index cd1b59310..e5b18ed11 100644 --- a/pjsip/src/pjsua-lib/pjsua_acc.c +++ b/pjsip/src/pjsua-lib/pjsua_acc.c @@ -484,31 +484,43 @@ static pj_bool_t acc_check_nat_addr(pjsua_acc *acc, { pjsip_transport *tp; const pj_str_t *via_addr; + pj_pool_t *pool; int rport; + pjsip_sip_uri *uri; pjsip_via_hdr *via; tp = param->rdata->tp_info.transport; /* Only update if account is configured to auto-update */ - if (acc->cfg.auto_update_nat == PJ_FALSE) + if (acc->cfg.allow_contact_rewrite == PJ_FALSE) return PJ_FALSE; - /* Only update if registration uses UDP transport */ - if (tp->key.type != PJSIP_TRANSPORT_UDP) - return PJ_FALSE; +#if 0 + // Always update + // See http://lists.pjsip.org/pipermail/pjsip_lists.pjsip.org/2008-March/002178.html - /* Only update if STUN is enabled (for now) */ - if (pjsua_var.ua_cfg.stun_domain.slen == 0 && - pjsua_var.ua_cfg.stun_host.slen == 0) + /* For UDP, only update if STUN is enabled (for now). + * For TCP/TLS, always check. + */ + if ((tp->key.type == PJSIP_TRANSPORT_UDP && + (pjsua_var.ua_cfg.stun_domain.slen != 0 || + (pjsua_var.ua_cfg.stun_host.slen != 0)) || + (tp->key.type == PJSIP_TRANSPORT_TCP) || + (tp->key.type == PJSIP_TRANSPORT_TLS)) { + /* Yes we will check */ + } else { return PJ_FALSE; } +#endif /* Get the received and rport info */ via = param->rdata->msg_info.via; if (via->rport_param < 1) { /* Remote doesn't support rport */ rport = via->sent_by.port; + if (rport==0) + rport = pjsip_transport_get_default_port_for_type(tp->key.type); } else rport = via->rport_param; @@ -517,11 +529,21 @@ static pj_bool_t acc_check_nat_addr(pjsua_acc *acc, else via_addr = &via->sent_by.host; - /* Compare received and rport with transport published address */ - if (tp->local_name.port == rport && - pj_stricmp(&tp->local_name.host, via_addr)==0) + /* Compare received and rport with the URI in our registration */ + pool = pjsua_pool_create("tmp", 512, 512); + uri = (pjsip_sip_uri*) + pjsip_parse_uri(pool, acc->contact.ptr, acc->contact.slen, 0); + pj_assert(uri != NULL); + uri = pjsip_uri_get_uri(uri); + + if (uri->port == 0) + uri->port = pjsip_transport_get_default_port_for_type(tp->key.type); + + if (uri->port == rport && + pj_stricmp(&uri->host, via_addr)==0) { /* Address doesn't change */ + pj_pool_release(pool); return PJ_FALSE; } @@ -531,9 +553,9 @@ static pj_bool_t acc_check_nat_addr(pjsua_acc *acc, PJ_LOG(3,(THIS_FILE, "IP address change detected for account %d " "(%.*s:%d --> %.*s:%d). Updating registration..", acc->index, - (int)tp->local_name.host.slen, - tp->local_name.host.ptr, - tp->local_name.port, + (int)uri->host.slen, + uri->host.ptr, + uri->port, (int)via_addr->slen, via_addr->ptr, rport)); @@ -545,13 +567,44 @@ static pj_bool_t acc_check_nat_addr(pjsua_acc *acc, acc->regc = NULL; } - /* Update transport address */ - pj_strdup_with_null(tp->pool, &tp->local_name.host, via_addr); - tp->local_name.port = rport; + /* Update account's Contact header */ + { + char *tmp; + int len; + + tmp = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE); + len = pj_ansi_snprintf(tmp, PJSIP_MAX_URL_SIZE, + "", + (int)acc->user_part.slen, + acc->user_part.ptr, + (int)via_addr->slen, + via_addr->ptr, + rport, + tp->type_name); + if (len < 1) { + PJ_LOG(1,(THIS_FILE, "URI too long")); + pj_pool_release(pool); + return PJ_FALSE; + } + pj_strdup2(pjsua_var.pool, &acc->contact, tmp); + } + + /* For UDP transport, if STUN is enabled then update the transport's + * published name as well. + */ + if (tp->key.type==PJSIP_TRANSPORT_UDP && + (pjsua_var.ua_cfg.stun_domain.slen != 0 || + pjsua_var.ua_cfg.stun_host.slen != 0)) + { + pj_strdup_with_null(tp->pool, &tp->local_name.host, via_addr); + tp->local_name.port = rport; + } /* Perform new registration */ pjsua_acc_set_registration(acc->index, PJ_TRUE); + pj_pool_release(pool); + return PJ_TRUE; } @@ -863,7 +916,6 @@ static void regc_cb(struct pjsip_regc_cbparam *param) static pj_status_t pjsua_regc_init(int acc_id) { pjsua_acc *acc; - pj_str_t contact; pj_pool_t *pool; pj_status_t status; @@ -893,23 +945,30 @@ static pj_status_t pjsua_regc_init(int acc_id) } pool = pjsua_pool_create("tmpregc", 512, 512); - status = pjsua_acc_create_uac_contact( pool, &contact, - acc_id, &acc->cfg.reg_uri); - if (status != PJ_SUCCESS) { - pjsua_perror(THIS_FILE, "Unable to generate suitable Contact header" - " for registration", - status); - pjsip_regc_destroy(acc->regc); - pj_pool_release(pool); - acc->regc = NULL; - return status; + + if (acc->contact.slen == 0) { + pj_str_t tmp_contact; + + status = pjsua_acc_create_uac_contact( pool, &tmp_contact, + acc_id, &acc->cfg.reg_uri); + if (status != PJ_SUCCESS) { + pjsua_perror(THIS_FILE, "Unable to generate suitable Contact header" + " for registration", + status); + pjsip_regc_destroy(acc->regc); + pj_pool_release(pool); + acc->regc = NULL; + return status; + } + + pj_strdup_with_null(pjsua_var.pool, &acc->contact, &tmp_contact); } status = pjsip_regc_init( acc->regc, &acc->cfg.reg_uri, &acc->cfg.id, &acc->cfg.id, - 1, &contact, + 1, &acc->contact, acc->cfg.reg_timeout); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index 9bbbca7a5..83183dd5b 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -142,7 +142,7 @@ PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg) cfg->reg_timeout = PJSUA_REG_INTERVAL; cfg->transport_id = PJSUA_INVALID_ID; - cfg->auto_update_nat = PJ_TRUE; + cfg->allow_contact_rewrite = PJ_TRUE; cfg->require_100rel = pjsua_var.ua_cfg.require_100rel; cfg->ka_interval = 15; cfg->ka_data = pj_str("\r\n");