From 4f82e697a033306f77f467f77c0e8b405844fcfb Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Thu, 27 Sep 2007 14:07:07 +0000 Subject: Ticket #381: auto-update the IP address in Contact according to the address/port received in REGISTER response git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1454 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/build/pjsua_lib.dsp | 2 + pjsip/include/pjsua-lib/pjsua.h | 13 ++++++ pjsip/src/pjsua-lib/pjsua_acc.c | 87 ++++++++++++++++++++++++++++++++++++++++ pjsip/src/pjsua-lib/pjsua_core.c | 1 + 4 files changed, 103 insertions(+) diff --git a/pjsip/build/pjsua_lib.dsp b/pjsip/build/pjsua_lib.dsp index da7c163f..3defda24 100644 --- a/pjsip/build/pjsua_lib.dsp +++ b/pjsip/build/pjsua_lib.dsp @@ -40,6 +40,7 @@ RSC=rc.exe # PROP Output_Dir ".\output\pjsua-lib-i386-win32-vc6-release" # PROP Intermediate_Dir ".\output\pjsua-lib-i386-win32-vc6-release" # PROP Target_Dir "" +F90=df.exe # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c # ADD CPP /nologo /MD /W4 /GX /Zi /O2 /I "../include" /I "../../pjmedia/include" /I "../../pjlib-util/include" /I "../../pjlib/include" /I "../../pjnath/include" /D "NDEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_MBCS" /D "_LIB" /FR /FD /c # SUBTRACT CPP /YX @@ -64,6 +65,7 @@ LIB32=link.exe -lib # PROP Output_Dir ".\output\pjsua-lib-i386-win32-vc6-debug" # PROP Intermediate_Dir ".\output\pjsua-lib-i386-win32-vc6-debug" # PROP Target_Dir "" +F90=df.exe # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjmedia/include" /I "../../pjlib-util/include" /I "../../pjlib/include" /I "../../pjnath/include" /D "_DEBUG" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "_MBCS" /D "_LIB" /FR /FD /GZ /c # SUBTRACT CPP /YX diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h index f493de5d..870ea8d5 100644 --- a/pjsip/include/pjsua-lib/pjsua.h +++ b/pjsip/include/pjsua-lib/pjsua.h @@ -1847,6 +1847,19 @@ 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. + * + * Default: 1 (yes) + */ + pj_bool_t auto_update_nat; + } pjsua_acc_config; diff --git a/pjsip/src/pjsua-lib/pjsua_acc.c b/pjsip/src/pjsua-lib/pjsua_acc.c index 854f8cb4..07cba74f 100644 --- a/pjsip/src/pjsua-lib/pjsua_acc.c +++ b/pjsip/src/pjsua-lib/pjsua_acc.c @@ -454,6 +454,83 @@ PJ_DEF(pj_status_t) pjsua_acc_set_online_status2( pjsua_acc_id acc_id, } +/* Update NAT address from the REGISTER response */ +static pj_bool_t acc_check_nat_addr(pjsua_acc *acc, + struct pjsip_regc_cbparam *param) +{ + pjsip_transport *tp; + const pj_str_t *via_addr; + int rport; + 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) + return PJ_FALSE; + + /* Only update if registration uses UDP transport */ + if (tp->key.type != PJSIP_TRANSPORT_UDP) + return PJ_FALSE; + + /* 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) + { + return PJ_FALSE; + } + + /* 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; + } else + rport = via->rport_param; + + if (via->recvd_param.slen != 0) + via_addr = &via->recvd_param; + 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) + { + /* Address doesn't change */ + return PJ_FALSE; + } + + /* At this point we've detected that the address as seen by registrar. + * has changed. + */ + 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)via_addr->slen, + via_addr->ptr, + rport)); + + /* Unregister current contact */ + pjsua_acc_set_registration(acc->index, PJ_FALSE); + if (acc->regc != NULL) { + pjsip_regc_destroy(acc->regc); + acc->regc = NULL; + } + + /* Update transport address */ + 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); + + return PJ_TRUE; +} + /* * This callback is called by pjsip_regc when outgoing register * request has completed. @@ -463,6 +540,9 @@ static void regc_cb(struct pjsip_regc_cbparam *param) pjsua_acc *acc = (pjsua_acc*) param->token; + if (param->regc != acc->regc) + return; + PJSUA_LOCK(); /* @@ -489,6 +569,13 @@ static void regc_cb(struct pjsip_regc_cbparam *param) PJ_LOG(3,(THIS_FILE, "%s: unregistration success", pjsua_var.acc[acc->index].cfg.id.ptr)); } else { + /* Check NAT bound address */ + if (acc_check_nat_addr(acc, param)) { + /* Update address, don't notify application yet */ + PJSUA_UNLOCK(); + return; + } + PJ_LOG(3, (THIS_FILE, "%s: registration success, status=%d (%.*s), " "will re-register in %d seconds", diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index fa55da60..3b512666 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -140,6 +140,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; } PJ_DEF(void) pjsua_buddy_config_default(pjsua_buddy_config *cfg) -- cgit v1.2.3