From: Yann Diorcet Date: Mon, 18 Feb 2013 13:59:48 +0000 (+0100) Subject: Fix uPnP issues. Correct registration and update with uPnP X-Git-Url: http://sjero.net/git/?p=linphone;a=commitdiff_plain;h=be6165d8615cf4176a98193931d1579830d7bd31 Fix uPnP issues. Correct registration and update with uPnP --- diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 55954772..75930adb 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -1100,10 +1100,11 @@ void linphone_proxy_config_update(LinphoneProxyConfig *cfg){ switch(linphone_core_get_firewall_policy(lc)) { case LinphonePolicyUseUpnp: #ifdef BUILD_UPNP - if(lc->upnp != NULL && !linphone_upnp_context_is_ready_for_register(lc->upnp)) { + if(!lc->sip_conf.register_only_when_upnp_is_ok || + (lc->upnp != NULL && !linphone_upnp_context_is_ready_for_register(lc->upnp))) { break; } -#endif +#endif //BUILD_UPNP default: if ((!lc->sip_conf.register_only_when_network_is_up || lc->network_reachable)) { linphone_proxy_config_register(cfg); diff --git a/coreapi/upnp.c b/coreapi/upnp.c index 0713a1d5..deb096b9 100644 --- a/coreapi/upnp.c +++ b/coreapi/upnp.c @@ -21,9 +21,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "private.h" #include "lpconfig.h" -#define UPNP_ADD_MAX_RETRY 4 +#define UPNP_ADD_MAX_RETRY 4 #define UPNP_REMOVE_MAX_RETRY 4 -#define UPNP_SECTION_NAME "uPnP" +#define UPNP_SECTION_NAME "uPnP" +#define UPNP_CORE_READY_CHECK 1 #define UPNP_CORE_RETRY_DELAY 4 #define UPNP_CALL_RETRY_DELAY 1 @@ -72,7 +73,9 @@ struct _UpnpContext { ms_mutex_t mutex; ms_cond_t empty_cond; - + + time_t last_ready_check; + LinphoneUpnpState last_ready_state; }; @@ -252,6 +255,9 @@ UpnpContext* linphone_upnp_context_new(LinphoneCore *lc) { ms_mutex_init(&lupnp->mutex, NULL); ms_cond_init(&lupnp->empty_cond, NULL); + lupnp->last_ready_check = 0; + lupnp->last_ready_state = LinphoneUpnpStateIdle; + lupnp->lc = lc; lupnp->pending_bindings = NULL; lupnp->adding_configs = NULL; @@ -347,16 +353,17 @@ LinphoneUpnpState linphone_upnp_context_get_state(UpnpContext *lupnp) { return state; } -bool_t linphone_upnp_context_is_ready_for_register(UpnpContext *lupnp) { +bool_t _linphone_upnp_context_is_ready_for_register(UpnpContext *lupnp) { bool_t ready = TRUE; - ms_mutex_lock(&lupnp->mutex); - + // 1 Check global uPnP state ready = (lupnp->state == LinphoneUpnpStateOk); // 2 Check external ip address - if(ready && upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt) == NULL) { - ready = FALSE; + if(ready) { + if (upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt) == NULL) { + ready = FALSE; + } } // 3 Check sip ports bindings @@ -377,7 +384,14 @@ bool_t linphone_upnp_context_is_ready_for_register(UpnpContext *lupnp) { ready = FALSE; } } + + return ready; +} +bool_t linphone_upnp_context_is_ready_for_register(UpnpContext *lupnp) { + bool_t ready; + ms_mutex_lock(&lupnp->mutex); + ready = _linphone_upnp_context_is_ready_for_register(lupnp); ms_mutex_unlock(&lupnp->mutex); return ready; } @@ -541,6 +555,7 @@ int linphone_core_update_upnp_audio_video(LinphoneCall *call, bool_t audio, bool } ms_mutex_lock(&lupnp->mutex); + // Don't handle when the call if(lupnp->state == LinphoneUpnpStateOk && call->upnp_session != NULL) { ret = 0; @@ -785,20 +800,16 @@ void linphone_upnp_update_port_binding(UpnpContext *lupnp, UpnpPortBinding **por // Get addresses local_addr = upnp_igd_get_local_ipaddress(lupnp->upnp_igd_ctxt); external_addr = upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt); - + // Force binding update on local address change if(local_addr != NULL) { if(strncmp((*port_mapping)->local_addr, local_addr, sizeof((*port_mapping)->local_addr))) { linphone_upnp_context_send_remove_port_binding(lupnp, *port_mapping, FALSE); strncpy((*port_mapping)->local_addr, local_addr, sizeof((*port_mapping)->local_addr)); } - } else { - ms_warning("uPnP IGD: can't get local address"); } if(external_addr != NULL) { strncpy((*port_mapping)->external_addr, external_addr, sizeof((*port_mapping)->external_addr)); - } else { - ms_warning("uPnP IGD: can't get external address"); } // Add (if not already done) the binding @@ -817,7 +828,9 @@ void linphone_upnp_update_port_binding(UpnpContext *lupnp, UpnpPortBinding **por bool_t linphone_core_upnp_hook(void *data) { char key[64]; LCSipTransports transport; - MSList *item; + const MSList *item; + LinphoneUpnpState ready_state; + time_t now = time(NULL); UpnpPortBinding *port_mapping; UpnpContext *lupnp = (UpnpContext *)data; @@ -831,6 +844,28 @@ bool_t linphone_core_upnp_hook(void *data) { linphone_upnp_update_port_binding(lupnp, &lupnp->sip_tls, UPNP_IGD_IP_PROTOCOL_TCP, transport.tls_port, UPNP_CORE_RETRY_DELAY); } + /* Refresh registers if we are ready */ + if(now - lupnp->last_ready_check >= UPNP_CORE_READY_CHECK) { + lupnp->last_ready_check = now; + ready_state = (_linphone_upnp_context_is_ready_for_register(lupnp))? LinphoneUpnpStateOk: LinphoneUpnpStateKo; + if(ready_state != lupnp->last_ready_state) { + for(item=linphone_core_get_proxy_config_list(lupnp->lc);item!=NULL;item=item->next) { + LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)item->data; + if (linphone_proxy_config_register_enabled(cfg)) { + if (ready_state != LinphoneUpnpStateOk) { + // Only reset ithe registration if we require that upnp should be ok + if(lupnp->lc->sip_conf.register_only_when_upnp_is_ok) { + linphone_proxy_config_set_state(cfg, LinphoneRegistrationNone, "Registration impossible (uPnP not ready)"); + } + } else { + cfg->commit=TRUE; + } + } + } + lupnp->last_ready_state = ready_state; + } + } + /* Add configs */ for(item = lupnp->adding_configs;item!=NULL;item=item->next) { port_mapping = (UpnpPortBinding *)item->data; diff --git a/mediastreamer2 b/mediastreamer2 index 44992c09..73a772ac 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 44992c096673ace578ba5248db7019ba1e0d78d5 +Subproject commit 73a772ac4754734c57ecbc1149cbe665acd2f376