Try to ensure we build correctly against various libminiupnpc versions.
authorEtienne Dechamps <etienne@edechamps.fr>
Sun, 15 Nov 2015 17:42:14 +0000 (17:42 +0000)
committerEtienne Dechamps <etienne@edechamps.fr>
Sat, 21 Nov 2015 16:18:01 +0000 (16:18 +0000)
Unfortunately, libminiupnpc has a somewhat... "peculiar" approach to
backwards compatibility for their API, where they reserve the right to
make breaking changes when they feel like it, forcing users to resort
to #ifdefs to ensure they use the correct API. Sigh.

Previously, tinc would only build against API versions <= 13, because I
was doing my initial development using miniupnpc-1.9.20140610 which is
the version that ships with Debian. The changes in this commit are
required for tinc to build against more recent versions, from
1.9.20150730 to the latest one at the time of this commit, 1.9.20151026.

src/upnp.c

index a03143a..abd2f92 100644 (file)
@@ -37,6 +37,39 @@ static bool upnp_udp;
 static int upnp_discover_wait = 5;
 static int upnp_refresh_period = 60;
 
+// Unfortunately, libminiupnpc devs don't seem to care about API compatibility,
+// and there are slight changes to function signatures between library versions.
+// Well, at least they publish a "MINIUPNPC_API_VERSION" constant, so we got that going for us, which is nice.
+// Differences between API versions are documented in "apiversions.txt" in the libminiupnpc distribution.
+
+#ifndef MINIUPNPC_API_VERSION
+#define MINIUPNPC_API_VERSION 0
+#endif
+
+static struct UPNPDev *upnp_discover(int delay, int *error) {
+#if MINIUPNPC_API_VERSION <= 13
+
+#if MINIUPNPC_API_VERSION < 8
+#warning "The version of libminiupnpc you're building against seems to be too old. Expect trouble."
+#endif
+
+       return upnpDiscover(delay, NULL, NULL, false, false, error);
+
+#elif MINIUPNPC_API_VERSION <= 14
+
+       return upnpDiscover(delay, NULL NULL, false, false, 2, error);
+
+#else
+
+#if MINIUPNPC_API_VERSION > 15
+#warning "The version of libminiupnpc you're building against seems to be too recent. Expect trouble."
+#endif
+
+       return upnpDiscover(delay, NULL, NULL, UPNP_LOCAL_PORT_ANY, false, 2, error);
+
+#endif
+}
+
 static void upnp_add_mapping(struct UPNPUrls *urls, struct IGDdatas *data, const char *myaddr, int socket, const char *proto) {
        // Extract the port from the listening socket.
        // Note that we can't simply use listen_socket[].sa because this won't have the port
@@ -72,7 +105,7 @@ static void upnp_refresh() {
        logger(DEBUG_PROTOCOL, LOG_INFO, "[upnp] Discovering IGD devices");
 
        int error;
-       struct UPNPDev *devices = upnpDiscover(upnp_discover_wait * 1000, NULL, NULL, false, false, &error);
+       struct UPNPDev *devices = upnp_discover(upnp_discover_wait * 1000, &error);
        if (!devices) {
                logger(DEBUG_PROTOCOL, LOG_WARNING, "[upnp] Unable to find IGD devices: [%d] %s", error, strupnperror(error));
                freeUPNPDevlist(devices);