+}
+
+void linphone_upnp_update_config(UpnpContext* lupnp) {
+ char key[64];
+ const MSList *item;
+ UpnpPortBinding *port_mapping;
+
+ /* Add configs */
+ for(item = lupnp->adding_configs;item!=NULL;item=item->next) {
+ port_mapping = (UpnpPortBinding *)item->data;
+ snprintf(key, sizeof(key), "%s-%s-%d-%d",
+ port_mapping->device_id,
+ (port_mapping->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP",
+ port_mapping->external_port,
+ port_mapping->local_port);
+ lp_config_set_string(lupnp->lc->config, UPNP_SECTION_NAME, key, "uPnP");
+ linphone_upnp_port_binding_log(ORTP_DEBUG, "Configuration: Added port binding", port_mapping);
+ }
+ ms_list_for_each(lupnp->adding_configs,(void (*)(void*))linphone_upnp_port_binding_release);
+ lupnp->adding_configs = ms_list_free(lupnp->adding_configs);
+
+ /* Remove configs */
+ for(item = lupnp->removing_configs;item!=NULL;item=item->next) {
+ port_mapping = (UpnpPortBinding *)item->data;
+ snprintf(key, sizeof(key), "%s-%s-%d-%d",
+ port_mapping->device_id,
+ (port_mapping->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP",
+ port_mapping->external_port,
+ port_mapping->local_port);
+ lp_config_set_string(lupnp->lc->config, UPNP_SECTION_NAME, key, NULL);
+ linphone_upnp_port_binding_log(ORTP_DEBUG, "Configuration: Removed port binding", port_mapping);
+ }
+ ms_list_for_each(lupnp->removing_configs,(void (*)(void*))linphone_upnp_port_binding_release);
+ lupnp->removing_configs = ms_list_free(lupnp->removing_configs);
+}
+
+void linphone_upnp_update_proxy(UpnpContext* lupnp, bool_t force) {
+ LinphoneUpnpState ready_state;
+ const MSList *item;
+ time_t now = (force)? (lupnp->last_ready_check + UPNP_CORE_READY_CHECK) : time(NULL);
+
+ /* 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;
+ }
+ } else {
+ cfg->commit=TRUE;
+ }
+ }
+ }
+ lupnp->last_ready_state = ready_state;
+ }
+ }
+}
+
+bool_t linphone_core_upnp_hook(void *data) {
+ LCSipTransports transport;
+ UpnpContext *lupnp = (UpnpContext *)data;
+
+ ms_mutex_lock(&lupnp->mutex);
+
+ /* Update ports */
+ if(lupnp->state == LinphoneUpnpStateOk) {
+ linphone_core_get_sip_transports(lupnp->lc, &transport);
+ linphone_upnp_update_port_binding(lupnp, &lupnp->sip_udp, UPNP_IGD_IP_PROTOCOL_UDP, transport.udp_port, UPNP_CORE_RETRY_DELAY);
+ linphone_upnp_update_port_binding(lupnp, &lupnp->sip_tcp, UPNP_IGD_IP_PROTOCOL_TCP, transport.tcp_port, UPNP_CORE_RETRY_DELAY);
+ linphone_upnp_update_port_binding(lupnp, &lupnp->sip_tls, UPNP_IGD_IP_PROTOCOL_TCP, transport.tls_port, UPNP_CORE_RETRY_DELAY);
+ }
+
+ linphone_upnp_update_proxy(lupnp, FALSE);
+ linphone_upnp_update_config(lupnp);