From 017f7a2f9743ff93541e7d8f9b7411efa566952e Mon Sep 17 00:00:00 2001
From: Edric Milaret <edric.ladent-milaret@savoirfairelinux.com>
Date: Mon, 4 May 2015 16:50:37 -0400
Subject: [PATCH] windows: add upnp support

Refs #71910

Change-Id: Iab724e6c9b9f6e412623a125a5bb076d3c78a57e
---
 configure.ac                             |  3 +
 contrib/src/upnp/libupnp-configure.patch | 82 ------------------------
 contrib/src/upnp/rules.mak               | 11 ++--
 contrib/src/upnp/threadpool.patch        | 29 +++++++++
 src/Makefile.am                          |  1 -
 src/ip_utils.cpp                         |  3 +
 src/ip_utils.h                           |  9 ++-
 src/upnp/upnp_context.cpp                |  8 ++-
 src/upnp/upnp_context.h                  |  5 ++
 9 files changed, 55 insertions(+), 96 deletions(-)
 delete mode 100644 contrib/src/upnp/libupnp-configure.patch
 create mode 100644 contrib/src/upnp/threadpool.patch

diff --git a/configure.ac b/configure.ac
index 6da792887a..3bac0eae2d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -73,6 +73,9 @@ case "${host_os}" in
     AC_DEFINE([_XOPEN_SOURCE_EXTENDED], [1], [XPG things and X/Open Unix extensions.])
     AC_DEFINE([_BSD_SOURCE], [1], [ISO C, POSIX, and 4.3BSD things.])
     AC_DEFINE([_SVID_SOURCE], [1], [ISO C, POSIX, and SVID things.])
+
+    AC_DEFINE([WIN32_LEAN_AND_MEAN],, [Define to limit the scope of <windows.h>.])
+
     CPPFLAGS+="-D_WIN32_WINNT=0x0601 -DWINVER=0x0601"
     LDFLAGS+="-no-undefined -avoid-version -Wl,--nxcompat -Wl,--dynamicbase"
     ac_default_prefix="`pwd`/_win32"
diff --git a/contrib/src/upnp/libupnp-configure.patch b/contrib/src/upnp/libupnp-configure.patch
deleted file mode 100644
index dbc14cca5e..0000000000
--- a/contrib/src/upnp/libupnp-configure.patch
+++ /dev/null
@@ -1,82 +0,0 @@
---- libupnp/configure.ac.orig	2011-02-09 00:55:44.000000000 +0100
-+++ libupnp/configure.ac	2011-02-10 23:39:44.154929678 +0100
-@@ -397,7 +397,6 @@
- AC_PROG_MAKE_SET
- AC_PROG_EGREP
- 
--#
- # Default compilation flags
- #
- echo "--------------------- Default compilation flags -------------------------------"
-@@ -531,39 +530,46 @@
- # Checks for POSIX Threads
- #
- echo "--------------------------- pthread stuff -------------------------------------"
--ACX_PTHREAD(
--	[],
--	[AC_MSG_ERROR([POSIX threads are required to build this program])])
-+#ACX_PTHREAD(
-+#	[],
-+#	[AC_MSG_ERROR([POSIX threads are required to build this program])])
- #
-+PTHREAD_LIBS=" -lpthreadGC2 -lws2_32"
-+PTHREAD_CFLAGS=" -DPTW32_STATIC_LIB -DUPNP_STATIC_LIB"
- # Update environment variables for pthreads
- #
--CC="$PTHREAD_CC"
-+#CC="$PTHREAD_CC"
- CFLAGS="$PTHREAD_CFLAGS $CFLAGS"
- LIBS="$PTHREAD_LIBS $LIBS"
-+
-+AC_SUBST(PTHREAD_LIBS)
-+AC_SUBST(PTHREAD_CFLAGS)
-+AC_SUBST(PTHREAD_CC)
-+
- #
- # Determine if pthread_rwlock_t is available
- #
--echo "----------------------- pthread_rwlock_t stuff --------------------------------"
--AC_MSG_CHECKING([if pthread_rwlock_t is available])
--AC_LANG([C])
--AC_COMPILE_IFELSE(
--	[AC_LANG_PROGRAM(
--		[#include <pthread.h>],
--		[pthread_rwlock_t *x;])],
--	[AC_DEFINE([UPNP_USE_RWLOCK], [1], [Use pthread_rwlock_t])
--		AC_MSG_RESULT([yes, supported without any options])],
--	[AC_COMPILE_IFELSE(
--		[AC_LANG_PROGRAM(
--			[#define _GNU_SOURCE
--			#include <pthread.h>],
--			[pthread_rwlock_t *x;])],
--		[AC_DEFINE([UPNP_USE_RWLOCK], [1], [Use pthread_rwlock_t])
--			CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
--			AC_MSG_RESULT([yes, definition of _GNU_SOURCE required])],
--		[AC_DEFINE([UPNP_USE_RWLOCK], [0], [Do not use pthread_rwlock_t])
--			AC_MSG_RESULT([no, needs to fallback to pthread_mutex])
--			AC_MSG_ERROR([pthread_rwlock_t not available])])])
--echo "-------------------------------------------------------------------------------"
-+#echo "----------------------- pthread_rwlock_t stuff --------------------------------"
-+#AC_MSG_CHECKING([if pthread_rwlock_t is available])
-+#AC_LANG([C])
-+#AC_COMPILE_IFELSE(
-+#	[AC_LANG_PROGRAM(
-+#		[#include <pthread.h>],
-+#		[pthread_rwlock_t *x;])],
-+#	[AC_DEFINE([UPNP_USE_RWLOCK], [1], [Use pthread_rwlock_t])
-+#		AC_MSG_RESULT([yes, supported without any options])],
-+#	[AC_COMPILE_IFELSE(
-+#		[AC_LANG_PROGRAM(
-+#			[#define _GNU_SOURCE
-+#			#include <pthread.h>],
-+#			[pthread_rwlock_t *x;])],
-+#		[AC_DEFINE([UPNP_USE_RWLOCK], [1], [Use pthread_rwlock_t])
-+#			CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
-+#			AC_MSG_RESULT([yes, definition of _GNU_SOURCE required])],
-+#		[AC_DEFINE([UPNP_USE_RWLOCK], [0], [Do not use pthread_rwlock_t])
-+#			AC_MSG_RESULT([no, needs to fallback to pthread_mutex])
-+#			AC_MSG_ERROR([pthread_rwlock_t not available])])])
-+#echo "-------------------------------------------------------------------------------"
- 
- 
- AC_CONFIG_FILES([
diff --git a/contrib/src/upnp/rules.mak b/contrib/src/upnp/rules.mak
index b17bb73755..28d75371ed 100644
--- a/contrib/src/upnp/rules.mak
+++ b/contrib/src/upnp/rules.mak
@@ -12,17 +12,12 @@ $(TARBALLS)/libupnp-$(UPNP_VERSION).tar.bz2:
 
 .sum-upnp: libupnp-$(UPNP_VERSION).tar.bz2
 
-ifdef HAVE_WIN32
-DEPS_upnp += pthreads $(DEPS_pthreads)
-LIBUPNP_ECFLAGS = -DPTW32_STATIC_LIB
-endif
-
 upnp: libupnp-$(UPNP_VERSION).tar.bz2 .sum-upnp
 	$(UNPACK)
 ifdef HAVE_WIN32
-	$(APPLY) $(SRC)/upnp/libupnp-configure.patch
 	$(APPLY) $(SRC)/upnp/libupnp-win32.patch
 	$(APPLY) $(SRC)/upnp/libupnp-win64.patch
+	$(APPLY) $(SRC)/upnp/threadpool.patch
 endif
 	$(APPLY) $(SRC)/upnp/libupnp-ipv6.patch
 	$(APPLY) $(SRC)/upnp/miniserver.patch
@@ -33,7 +28,9 @@ endif
 .upnp: upnp
 ifdef HAVE_WIN32
 	$(RECONF)
+	cd $< && $(HOSTVARS) CFLAGS="-DUPNP_STATIC_LIB" ./configure --disable-samples --without-documentation --disable-blocking_tcp_connections $(HOSTCONF)
+else
+	cd $< && $(HOSTVARS) CFLAGS="$(CFLAGS) -DUPNP_STATIC_LIB" ./configure --disable-samples --without-documentation --disable-blocking_tcp_connections $(HOSTCONF)
 endif
-	cd $< && $(HOSTVARS) CFLAGS="$(CFLAGS) -DUPNP_STATIC_LIB $(LIBUPNP_ECFLAGS)" ./configure --disable-samples --without-documentation --disable-blocking_tcp_connections $(HOSTCONF)
 	cd $< && $(MAKE) install
 	touch $@
diff --git a/contrib/src/upnp/threadpool.patch b/contrib/src/upnp/threadpool.patch
new file mode 100644
index 0000000000..b0a5a6335e
--- /dev/null
+++ b/contrib/src/upnp/threadpool.patch
@@ -0,0 +1,29 @@
+--- a/threadutil/src/ThreadPool.c	2012-04-03 09:01:15.000000000 -0400
++++ b/threadutil/src/ThreadPool.c	2015-05-07 14:37:13.168494069 -0400
+@@ -264,7 +264,7 @@
+	setpriority(PRIO_PROCESS, 0, 0);
+	retVal = 0;
+ #elif defined(WIN32)
+-	retVal = sched_setscheduler(0, in);
++	retVal = 0;
+ #elif defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING > 0
+	struct sched_param current;
+	int sched_result;
+@@ -416,7 +416,7 @@
+
+	gettimeofday(&t, NULL);
+ #if defined(WIN32)
+-	srand((unsigned int)t.tv_usec + (unsigned int)ithread_get_current_thread_id().p);
++	srand((unsigned int)t.tv_usec + (unsigned int)ithread_get_current_thread_id());
+ #elif defined(BSD) || defined(__OSX__) || defined(__APPLE__) || defined(__FreeBSD_kernel__)
+	srand((unsigned int)t.tv_usec + (unsigned int)ithread_get_current_thread_id());
+ #elif defined(__linux__) || defined(__sun) || defined(__CYGWIN__) || defined(__GLIBC__)
+@@ -654,7 +654,7 @@
+		rc = ithread_detach(temp);
+		/* ithread_detach will return EINVAL if thread has been
+		 successfully detached by ithread_create */
+-		if (rc == EINVAL)
++		if (rc == EINVAL || rc == ESRCH)
+			rc = 0;
+		tp->pendingWorkerThreadStart = 1;
+		/* wait until the new worker thread starts */
diff --git a/src/Makefile.am b/src/Makefile.am
index 06c4d9b3b2..9270739d67 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -93,7 +93,6 @@ libring_la_CFLAGS = \
 		@SAMPLERATE_CFLAGS@ \
 		@LIBUPNP_CFLAGS@ \
 		@SPEEXDSP_CFLAGS@ \
-		@LIBUPNP_CFLAGS@ \
 		@PORTAUDIO_CFLAGS@ \
 		$(TLS_CFLAGS)
 
diff --git a/src/ip_utils.cpp b/src/ip_utils.cpp
index dfd6ad600d..dfbc63ba3b 100644
--- a/src/ip_utils.cpp
+++ b/src/ip_utils.cpp
@@ -30,6 +30,9 @@
  */
 
 #include "ip_utils.h"
+#ifdef s_addr
+    #undef s_addr
+#endif
 #include "logger.h"
 
 #include "sip/sip_utils.h"
diff --git a/src/ip_utils.h b/src/ip_utils.h
index 4adaba22f1..fe0c96f10f 100644
--- a/src/ip_utils.h
+++ b/src/ip_utils.h
@@ -34,18 +34,17 @@
 
 #include <pjlib.h>
 
+#ifdef HAVE_CONFIG
+ #include <config.h>
+#endif
+
 #ifdef _WIN32
     #include <ws2tcpip.h>
-    #include <config.h>
-    #include <winsock2.h>
 
     //define in mingw
     #ifdef interface
     #undef interface
     #endif
-    #ifdef s_addr
-    #undef s_addr
-    #endif
 #else
     #include <arpa/inet.h>
     #include <netinet/in.h>
diff --git a/src/upnp/upnp_context.cpp b/src/upnp/upnp_context.cpp
index 68c6314442..c53ec81932 100644
--- a/src/upnp/upnp_context.cpp
+++ b/src/upnp/upnp_context.cpp
@@ -178,8 +178,10 @@ UPnPContext::~UPnPContext()
 
     if (deviceRegistered_)
         UpnpUnRegisterRootDevice( deviceHandle_ );
-
+// FIXME : on windows thread have already been destroyed at this point resulting in a deadlock
+#ifndef _WIN32
     UpnpFinish();
+#endif
 }
 
 void
@@ -283,7 +285,11 @@ static uint16_t
 generateRandomPort()
 {
     /* obtain a random number from hardware */
+#ifndef _WIN32
     static std::random_device rd;
+#else
+    static std::default_random_engine rd(std::chrono::system_clock::now().time_since_epoch().count());
+#endif
     /* seed the generator */
     static std::mt19937 gen(rd());
     /* define the range */
diff --git a/src/upnp/upnp_context.h b/src/upnp/upnp_context.h
index 13578945ca..a4d090c22b 100644
--- a/src/upnp/upnp_context.h
+++ b/src/upnp/upnp_context.h
@@ -44,6 +44,11 @@
 #include <atomic>
 
 #if HAVE_LIBUPNP
+#ifdef _WIN32
+#define UPNP_STATIC_LIB
+#include <windows.h>
+#include <wincrypt.h>
+#endif
 #include <upnp/upnp.h>
 #include <upnp/upnptools.h>
 #endif
-- 
GitLab