+void linphone_upnp_update_port_binding(UpnpContext *lupnp, UpnpPortBinding **port_mapping, upnp_igd_ip_protocol protocol, int port, int retry_delay) {
+ const char *local_addr, *external_addr;
+ time_t now = time(NULL);
+ if(port != 0) {
+ if(*port_mapping != NULL) {
+ if(port != (*port_mapping)->local_port) {
+ linphone_upnp_context_send_remove_port_binding(lupnp, *port_mapping, FALSE);
+ *port_mapping = NULL;
+ }
+ }
+ if(*port_mapping == NULL) {
+ *port_mapping = linphone_upnp_port_binding_new_or_collect(lupnp->pending_bindings, protocol, port, port);
+ }
+
+ // 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
+ if(now - (*port_mapping)->last_update >= retry_delay) {
+ (*port_mapping)->last_update = now;
+ linphone_upnp_context_send_add_port_binding(lupnp, *port_mapping, FALSE);
+ }
+ } else {
+ if(*port_mapping != NULL) {
+ linphone_upnp_context_send_remove_port_binding(lupnp, *port_mapping, FALSE);
+ *port_mapping = NULL;
+ }
+ }
+}
+