]> sjero.net Git - linphone/blobdiff - coreapi/upnp.c
Fix upnp forgotten retain
[linphone] / coreapi / upnp.c
index e8841c2d620951c158023238ac2dd6403e920370..0922dad59eb7aa7c66d8f7517da589715f2c1422 100644 (file)
@@ -29,9 +29,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define UPNP_REMOVE_MAX_RETRY 4
 #define UPNP_SECTION_NAME     "uPnP"
 #define UPNP_CORE_READY_CHECK 1 
-#define UPNP_CORE_RETRY_DELAY 4
-#define UPNP_CALL_RETRY_DELAY 1
-#define UPNP_UUID_LEN         32
+#define UPNP_CORE_RETRY_DELAY 10
+#define UPNP_CALL_RETRY_DELAY 3
+#define UPNP_UUID_LEN         128
 #define UPNP_UUID_LEN_STR     UPNP_TOSTRING(UPNP_UUID_LEN)
 /*
  * uPnP Definitions
@@ -114,19 +114,17 @@ int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBind
 static int linphone_upnp_strncmpi(const char *str1, const char *str2, int len) {
        int i = 0;
        char char1, char2;
-       while(true) {
-               if(i >= len) {
-                       return 0;
-               }
+       while(i < len) {
                char1 = toupper(*str1);
                char2 = toupper(*str2);
-               if(char1 == '\0' || char2 == '\0' || char1 != char2) {
+               if(char1 == '\0' || char1 != char2) {
                        return char1 - char2;
                }
                str1++;
                str2++;
                i++;
        }
+       return 0;
 }
 
 static int linphone_upnp_str_min(const char *str1, const char *str2) {
@@ -340,7 +338,7 @@ UpnpContext* linphone_upnp_context_new(LinphoneCore *lc) {
        linphone_core_add_iterate_hook(lc, linphone_core_upnp_hook, lupnp);
 
        lupnp->upnp_igd_ctxt = NULL;
-       lupnp->upnp_igd_ctxt = upnp_igd_create(linphone_upnp_igd_callback, linphone_upnp_igd_print, lupnp);
+       lupnp->upnp_igd_ctxt = upnp_igd_create(linphone_upnp_igd_callback, linphone_upnp_igd_print, NULL, lupnp);
        if(lupnp->upnp_igd_ctxt == NULL) {
                lupnp->state = LinphoneUpnpStateKo;
                ms_error("Can't create uPnP IGD context");
@@ -555,9 +553,8 @@ int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBind
                mapping.local_port = port->local_port;
                mapping.local_host = port->local_addr;
                if(port->external_port == -1)
-                       mapping.remote_port = rand()%(0xffff - 1024) + 1024;
-               else
-                       mapping.remote_port = port->external_port;
+                       port->external_port = rand()%(0xffff - 1024) + 1024;
+               mapping.remote_port = port->external_port;
                mapping.remote_host = "";
                snprintf(description, 128, "%s %s at %s:%d",
                                PACKAGE_NAME,
@@ -1056,11 +1053,17 @@ UpnpPortBinding *linphone_upnp_port_binding_new_with_parameters(upnp_igd_ip_prot
 UpnpPortBinding *linphone_upnp_port_binding_new_or_collect(MSList *list, upnp_igd_ip_protocol protocol, int local_port, int external_port) {
        UpnpPortBinding *tmp_binding;
        UpnpPortBinding *end_binding;
-       end_binding = linphone_upnp_port_binding_new_with_parameters(protocol, local_port, external_port);
+       
+       // Seek an binding with same protocol and local port
+       end_binding = linphone_upnp_port_binding_new_with_parameters(protocol, local_port, -1);
        tmp_binding = linphone_upnp_port_binding_equivalent_in_list(list, end_binding);
-       if(tmp_binding != NULL) {
+       
+       // Must be not attached to any struct 
+       if(tmp_binding != NULL && tmp_binding->ref == 1) {
                linphone_upnp_port_binding_release(end_binding);
-               end_binding = tmp_binding;
+               end_binding = linphone_upnp_port_binding_retain(tmp_binding);
+       } else {
+               end_binding->external_port = external_port;
        }
        return end_binding;     
 } 
@@ -1107,10 +1110,11 @@ void linphone_upnp_port_binding_log(int level, const char *msg, const UpnpPortBi
        }
 }
 
+// Return true if the binding are equivalent. (Note external_port == -1 means "don't care")
 bool_t linphone_upnp_port_binding_equal(const UpnpPortBinding *port1, const UpnpPortBinding *port2) {
        return port1->protocol == port2->protocol &&
-                       port1->local_port == port2->local_port &&
-                       port1->external_port == port2->external_port;
+              port1->local_port == port2->local_port &&
+              (port1->external_port == -1 || port2->external_port == -1 || port1->external_port == port2->external_port);
 }
 
 UpnpPortBinding *linphone_upnp_port_binding_equivalent_in_list(MSList *list, const UpnpPortBinding *port) {
@@ -1238,7 +1242,7 @@ static void linphone_upnp_config_list_port_bindings_cb(const char *entry, struct
        bool_t valid = TRUE;
        UpnpPortBinding *port;
        
-       ret = sscanf(entry, "%"UPNP_UUID_LEN_STR"s-%3s-%i-%i", device_id, protocol_str, &external_port, &local_port);
+       ret = sscanf(entry, "%"UPNP_UUID_LEN_STR"[^-]-%3s-%i-%i", device_id, protocol_str, &external_port, &local_port);
        if(ret == 4) {
                // Handle only wanted device bindings
                if(device_id != NULL && strcmp(cookie->device_id, device_id) != 0) {