mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 04:04:16 +00:00
Fix UPnP for Win32
* find_package for headers * Swap includes order to pass compilation with MSVC 2013 * Enforce SO address resolution checks * Change SO/DLL name on Windows * Portable sleep from C++11 This closes #186
This commit is contained in:
parent
d7e7823606
commit
046ffd8648
142
UPnP.cpp
142
UPnP.cpp
@ -2,15 +2,19 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/thread/thread.hpp>
|
#include <boost/thread/thread.hpp>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#define dlsym GetProcAddress
|
||||||
|
#else
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
#include "UPnP.h"
|
#include "UPnP.h"
|
||||||
#include "NetDb.h"
|
#include "NetDb.h"
|
||||||
@ -18,24 +22,36 @@
|
|||||||
|
|
||||||
#include <miniupnpc/miniupnpc.h>
|
#include <miniupnpc/miniupnpc.h>
|
||||||
#include <miniupnpc/upnpcommands.h>
|
#include <miniupnpc/upnpcommands.h>
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
|
// These are per-process and are safe to reuse for all threads
|
||||||
#ifndef UPNPDISCOVER_SUCCESS
|
#ifndef UPNPDISCOVER_SUCCESS
|
||||||
/* miniupnpc 1.5 */
|
/* miniupnpc 1.5 */
|
||||||
typedef UPNPDev* (*upnp_upnpDiscoverFunc) (int, const char *, const char *, int);
|
UPNPDev* (*upnpDiscoverFunc) (int, const char *, const char *, int);
|
||||||
typedef int (*upnp_UPNP_AddPortMappingFunc) (const char *, const char *, const char *, const char *,
|
int (*UPNP_AddPortMappingFunc) (const char *, const char *, const char *, const char *,
|
||||||
const char *, const char *, const char *, const char *);
|
const char *, const char *, const char *, const char *);
|
||||||
#else
|
#else
|
||||||
/* miniupnpc 1.6 */
|
/* miniupnpc 1.6 */
|
||||||
typedef UPNPDev* (*upnp_upnpDiscoverFunc) (int, const char *, const char *, int, int, int *);
|
UPNPDev* (*upnpDiscoverFunc) (int, const char *, const char *, int, int, int *);
|
||||||
typedef int (*upnp_UPNP_AddPortMappingFunc) (const char *, const char *, const char *, const char *,
|
int (*UPNP_AddPortMappingFunc) (const char *, const char *, const char *, const char *,
|
||||||
const char *, const char *, const char *, const char *, const char *);
|
const char *, const char *, const char *, const char *, const char *);
|
||||||
#endif
|
#endif
|
||||||
typedef int (*upnp_UPNP_GetValidIGDFunc) (struct UPNPDev *, struct UPNPUrls *, struct IGDdatas *, char *, int);
|
int (*UPNP_GetValidIGDFunc) (struct UPNPDev *, struct UPNPUrls *, struct IGDdatas *, char *, int);
|
||||||
typedef int (*upnp_UPNP_GetExternalIPAddressFunc) (const char *, const char *, char *);
|
int (*UPNP_GetExternalIPAddressFunc) (const char *, const char *, char *);
|
||||||
typedef int (*upnp_UPNP_DeletePortMappingFunc) (const char *, const char *, const char *, const char *, const char *);
|
int (*UPNP_DeletePortMappingFunc) (const char *, const char *, const char *, const char *, const char *);
|
||||||
typedef void (*upnp_freeUPNPDevlistFunc) (struct UPNPDev *);
|
void (*freeUPNPDevlistFunc) (struct UPNPDev *);
|
||||||
typedef void (*upnp_FreeUPNPUrlsFunc) (struct UPNPUrls *);
|
void (*FreeUPNPUrlsFunc) (struct UPNPUrls *);
|
||||||
|
|
||||||
|
// Nice approach http://stackoverflow.com/a/21517513/673826
|
||||||
|
template<typename F>
|
||||||
|
F GetKnownProcAddressImpl(HMODULE hmod, const char *name, F) {
|
||||||
|
auto proc = reinterpret_cast<F>(dlsym(hmod, name));
|
||||||
|
if (!proc) {
|
||||||
|
LogPrint("Error resolving ", name, " from UPNP library. This often happens if there is version mismatch!");
|
||||||
|
}
|
||||||
|
return proc;
|
||||||
|
}
|
||||||
|
#define GetKnownProcAddress(hmod, func) GetKnownProcAddressImpl(hmod, #func, func##Func);
|
||||||
|
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@ -57,6 +73,33 @@ namespace transport
|
|||||||
|
|
||||||
void UPnP::Start()
|
void UPnP::Start()
|
||||||
{
|
{
|
||||||
|
if (!m_IsModuleLoaded) {
|
||||||
|
#ifdef MAC_OSX
|
||||||
|
m_Module = dlopen ("libminiupnpc.dylib", RTLD_LAZY);
|
||||||
|
#elif _WIN32
|
||||||
|
m_Module = LoadLibrary ("miniupnpc.dll"); // official prebuilt binary, e.g., in upnpc-exe-win32-20140422.zip
|
||||||
|
#else
|
||||||
|
m_Module = dlopen ("libminiupnpc.so", RTLD_LAZY);
|
||||||
|
#endif
|
||||||
|
if (m_Module == NULL)
|
||||||
|
{
|
||||||
|
LogPrint ("Error loading UPNP library. This often happens if there is version mismatch!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
upnpDiscoverFunc = GetKnownProcAddress (m_Module, upnpDiscover);
|
||||||
|
UPNP_GetValidIGDFunc = GetKnownProcAddress (m_Module, UPNP_GetValidIGD);
|
||||||
|
UPNP_GetExternalIPAddressFunc = GetKnownProcAddress (m_Module, UPNP_GetExternalIPAddress);
|
||||||
|
UPNP_AddPortMappingFunc = GetKnownProcAddress (m_Module, UPNP_AddPortMapping);
|
||||||
|
UPNP_DeletePortMappingFunc = GetKnownProcAddress (m_Module, UPNP_DeletePortMapping);
|
||||||
|
freeUPNPDevlistFunc = GetKnownProcAddress (m_Module, freeUPNPDevlist);
|
||||||
|
FreeUPNPUrlsFunc = GetKnownProcAddress (m_Module, FreeUPNPUrls);
|
||||||
|
if (upnpDiscoverFunc && UPNP_GetValidIGDFunc && UPNP_GetExternalIPAddressFunc && UPNP_AddPortMappingFunc &&
|
||||||
|
UPNP_DeletePortMappingFunc && freeUPNPDevlistFunc && FreeUPNPUrlsFunc)
|
||||||
|
m_IsModuleLoaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
m_Thread = new std::thread (std::bind (&UPnP::Run, this));
|
m_Thread = new std::thread (std::bind (&UPnP::Run, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,33 +109,6 @@ namespace transport
|
|||||||
|
|
||||||
void UPnP::Run ()
|
void UPnP::Run ()
|
||||||
{
|
{
|
||||||
#ifdef MAC_OSX
|
|
||||||
m_Module = dlopen ("libminiupnpc.dylib", RTLD_LAZY);
|
|
||||||
#elif _WIN32
|
|
||||||
m_Module = LoadLibrary ("libminiupnpc.dll");
|
|
||||||
if (m_Module == NULL)
|
|
||||||
{
|
|
||||||
LogPrint ("Error loading UPNP library. This often happens if there is version mismatch!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_IsModuleLoaded = true;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
m_Module = dlopen ("libminiupnpc.so", RTLD_LAZY);
|
|
||||||
#endif
|
|
||||||
#ifndef _WIN32
|
|
||||||
if (!m_Module)
|
|
||||||
{
|
|
||||||
LogPrint ("no UPnP module available (", dlerror (), ")");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_IsModuleLoaded = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
for (auto& address : context.GetRouterInfo ().GetAddresses ())
|
for (auto& address : context.GetRouterInfo ().GetAddresses ())
|
||||||
{
|
{
|
||||||
if (!address.host.is_v6 ())
|
if (!address.host.is_v6 ())
|
||||||
@ -112,18 +128,6 @@ namespace transport
|
|||||||
|
|
||||||
void UPnP::Discover ()
|
void UPnP::Discover ()
|
||||||
{
|
{
|
||||||
const char *error;
|
|
||||||
#ifdef _WIN32
|
|
||||||
upnp_upnpDiscoverFunc upnpDiscoverFunc = (upnp_upnpDiscoverFunc) GetProcAddress (m_Module, "upnpDiscover");
|
|
||||||
#else
|
|
||||||
upnp_upnpDiscoverFunc upnpDiscoverFunc = (upnp_upnpDiscoverFunc) dlsym (m_Module, "upnpDiscover");
|
|
||||||
// reinterpret_cast<upnp_upnpDiscoverFunc> (dlsym(...));
|
|
||||||
if ( (error = dlerror ()))
|
|
||||||
{
|
|
||||||
LogPrint ("Error loading UPNP library. This often happens if there is version mismatch!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif // _WIN32
|
|
||||||
#ifndef UPNPDISCOVER_SUCCESS
|
#ifndef UPNPDISCOVER_SUCCESS
|
||||||
/* miniupnpc 1.5 */
|
/* miniupnpc 1.5 */
|
||||||
m_Devlist = upnpDiscoverFunc (2000, m_MulticastIf, m_Minissdpdpath, 0);
|
m_Devlist = upnpDiscoverFunc (2000, m_MulticastIf, m_Minissdpdpath, 0);
|
||||||
@ -134,15 +138,9 @@ namespace transport
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
#ifdef _WIN32
|
r = UPNP_GetValidIGDFunc (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
||||||
upnp_UPNP_GetValidIGDFunc UPNP_GetValidIGDFunc = (upnp_UPNP_GetValidIGDFunc) GetProcAddress (m_Module, "UPNP_GetValidIGD");
|
|
||||||
#else
|
|
||||||
upnp_UPNP_GetValidIGDFunc UPNP_GetValidIGDFunc = (upnp_UPNP_GetValidIGDFunc) dlsym (m_Module, "UPNP_GetValidIGD");
|
|
||||||
#endif
|
|
||||||
r = (*UPNP_GetValidIGDFunc) (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
|
||||||
if (r == 1)
|
if (r == 1)
|
||||||
{
|
{
|
||||||
upnp_UPNP_GetExternalIPAddressFunc UPNP_GetExternalIPAddressFunc = (upnp_UPNP_GetExternalIPAddressFunc) dlsym (m_Module, "UPNP_GetExternalIPAddress");
|
|
||||||
r = UPNP_GetExternalIPAddressFunc (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
r = UPNP_GetExternalIPAddressFunc (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
||||||
if(r != UPNPCOMMAND_SUCCESS)
|
if(r != UPNPCOMMAND_SUCCESS)
|
||||||
{
|
{
|
||||||
@ -182,11 +180,6 @@ namespace transport
|
|||||||
std::string strDesc = "I2Pd";
|
std::string strDesc = "I2Pd";
|
||||||
try {
|
try {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
#ifdef _WIN32
|
|
||||||
upnp_UPNP_AddPortMappingFunc UPNP_AddPortMappingFunc = (upnp_UPNP_AddPortMappingFunc) GetProcAddress (m_Module, "UPNP_AddPortMapping");
|
|
||||||
#else
|
|
||||||
upnp_UPNP_AddPortMappingFunc UPNP_AddPortMappingFunc = (upnp_UPNP_AddPortMappingFunc) dlsym (m_Module, "UPNP_AddPortMapping");
|
|
||||||
#endif
|
|
||||||
#ifndef UPNPDISCOVER_SUCCESS
|
#ifndef UPNPDISCOVER_SUCCESS
|
||||||
/* miniupnpc 1.5 */
|
/* miniupnpc 1.5 */
|
||||||
r = UPNP_AddPortMappingFunc (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0);
|
r = UPNP_AddPortMappingFunc (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0);
|
||||||
@ -204,7 +197,9 @@ namespace transport
|
|||||||
LogPrint ("UPnP Port Mapping successful. (", m_NetworkAddr ,":", strPort.c_str(), " type ", strType.c_str () ," -> ", m_externalIPAddress ,":", strPort.c_str() ,")");
|
LogPrint ("UPnP Port Mapping successful. (", m_NetworkAddr ,":", strPort.c_str(), " type ", strType.c_str () ," -> ", m_externalIPAddress ,":", strPort.c_str() ,")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sleep(20*60);
|
std::this_thread::sleep_for(std::chrono::minutes(20)); // c++11
|
||||||
|
//boost::this_thread::sleep_for(); // pre c++11
|
||||||
|
//sleep(20*60); // non-portable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (boost::thread_interrupted)
|
catch (boost::thread_interrupted)
|
||||||
@ -228,29 +223,14 @@ namespace transport
|
|||||||
strType = "UDP";
|
strType = "UDP";
|
||||||
}
|
}
|
||||||
int r = 0;
|
int r = 0;
|
||||||
#ifdef _WIN32
|
|
||||||
upnp_UPNP_DeletePortMappingFunc UPNP_DeletePortMappingFunc = (upnp_UPNP_DeletePortMappingFunc) GetProcAddress (m_Module, "UPNP_DeletePortMapping");
|
|
||||||
#else
|
|
||||||
upnp_UPNP_DeletePortMappingFunc UPNP_DeletePortMappingFunc = (upnp_UPNP_DeletePortMappingFunc) dlsym (m_Module, "UPNP_DeletePortMapping");
|
|
||||||
#endif
|
|
||||||
r = UPNP_DeletePortMappingFunc (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), 0);
|
r = UPNP_DeletePortMappingFunc (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), 0);
|
||||||
LogPrint ("UPNP_DeletePortMapping() returned : ", r, "\n");
|
LogPrint ("UPNP_DeletePortMapping() returned : ", r, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void UPnP::Close ()
|
void UPnP::Close ()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
upnp_freeUPNPDevlistFunc freeUPNPDevlistFunc = (upnp_freeUPNPDevlistFunc) GetProcAddress (m_Module, "freeUPNPDevlist");
|
|
||||||
#else
|
|
||||||
upnp_freeUPNPDevlistFunc freeUPNPDevlistFunc = (upnp_freeUPNPDevlistFunc) dlsym (m_Module, "freeUPNPDevlist");
|
|
||||||
#endif
|
|
||||||
freeUPNPDevlistFunc (m_Devlist);
|
freeUPNPDevlistFunc (m_Devlist);
|
||||||
m_Devlist = 0;
|
m_Devlist = 0;
|
||||||
#ifdef _WIN32
|
|
||||||
upnp_FreeUPNPUrlsFunc FreeUPNPUrlsFunc = (upnp_FreeUPNPUrlsFunc) GetProcAddress (m_Module, "FreeUPNPUrlsFunc");
|
|
||||||
#else
|
|
||||||
upnp_FreeUPNPUrlsFunc FreeUPNPUrlsFunc = (upnp_FreeUPNPUrlsFunc) dlsym (m_Module, "FreeUPNPUrlsFunc");
|
|
||||||
#endif
|
|
||||||
FreeUPNPUrlsFunc (&m_upnpUrls);
|
FreeUPNPUrlsFunc (&m_upnpUrls);
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
dlclose (m_Module);
|
dlclose (m_Module);
|
||||||
|
2
UPnP.h
2
UPnP.h
@ -52,7 +52,7 @@ namespace transport
|
|||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
void *m_Module;
|
void *m_Module;
|
||||||
#else
|
#else
|
||||||
HINSTANCE *m_Module;
|
HINSTANCE m_Module;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ option(WITH_HARDENING "Use hardening compiler flags" OFF)
|
|||||||
option(WITH_LIBRARY "Build library" ON)
|
option(WITH_LIBRARY "Build library" ON)
|
||||||
option(WITH_BINARY "Build binary" ON)
|
option(WITH_BINARY "Build binary" ON)
|
||||||
option(WITH_STATIC "Static build" OFF)
|
option(WITH_STATIC "Static build" OFF)
|
||||||
|
option(WITH_UPNP "Include support for UPnP client" OFF)
|
||||||
|
|
||||||
# paths
|
# paths
|
||||||
set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" )
|
set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" )
|
||||||
@ -43,6 +44,7 @@ set (COMMON_SRC
|
|||||||
"${CMAKE_SOURCE_DIR}/util.cpp"
|
"${CMAKE_SOURCE_DIR}/util.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/Datagram.cpp"
|
"${CMAKE_SOURCE_DIR}/Datagram.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/Signature.cpp"
|
"${CMAKE_SOURCE_DIR}/Signature.cpp"
|
||||||
|
"${CMAKE_SOURCE_DIR}/UPnP.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
@ -62,10 +64,13 @@ set (DAEMON_SRC
|
|||||||
"${CMAKE_SOURCE_DIR}/I2PTunnel.cpp"
|
"${CMAKE_SOURCE_DIR}/I2PTunnel.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/SAM.cpp"
|
"${CMAKE_SOURCE_DIR}/SAM.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/SOCKS.cpp"
|
"${CMAKE_SOURCE_DIR}/SOCKS.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/UPnP.cpp"
|
|
||||||
"${CMAKE_SOURCE_DIR}/i2p.cpp"
|
"${CMAKE_SOURCE_DIR}/i2p.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (WITH_UPNP)
|
||||||
|
add_definitions(-DUSE_UPNP)
|
||||||
|
endif ()
|
||||||
|
|
||||||
set (LIBRARY_SRC
|
set (LIBRARY_SRC
|
||||||
"${CMAKE_SOURCE_DIR}/api.cpp"
|
"${CMAKE_SOURCE_DIR}/api.cpp"
|
||||||
)
|
)
|
||||||
@ -137,7 +142,7 @@ if (WITH_STATIC)
|
|||||||
set(Boost_USE_STATIC_LIBS ON)
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
find_package ( Boost COMPONENTS system filesystem regex program_options date_time REQUIRED )
|
find_package ( Boost COMPONENTS system filesystem regex program_options date_time thread chrono REQUIRED )
|
||||||
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
||||||
message(SEND_ERROR "Boost is not found, or your boost version was bellow 1.46. Please download Boost!")
|
message(SEND_ERROR "Boost is not found, or your boost version was bellow 1.46. Please download Boost!")
|
||||||
endif()
|
endif()
|
||||||
@ -147,6 +152,11 @@ if(NOT DEFINED CRYPTO++_INCLUDE_DIR)
|
|||||||
message(SEND_ERROR "Could not find Crypto++. Please download and install it first!")
|
message(SEND_ERROR "Could not find Crypto++. Please download and install it first!")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package ( MiniUPnPc )
|
||||||
|
if (NOT ${MINIUPNPC_FOUND})
|
||||||
|
set(WITH_UPNP OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
# load includes
|
# load includes
|
||||||
include_directories( ${Boost_INCLUDE_DIRS} ${CRYPTO++_INCLUDE_DIR} "${CMAKE_SOURCE_DIR}/..")
|
include_directories( ${Boost_INCLUDE_DIRS} ${CRYPTO++_INCLUDE_DIR} "${CMAKE_SOURCE_DIR}/..")
|
||||||
|
|
||||||
@ -163,6 +173,7 @@ message(STATUS " HARDENING : ${WITH_HARDENING}")
|
|||||||
message(STATUS " LIBRARY : ${WITH_LIBRARY}")
|
message(STATUS " LIBRARY : ${WITH_LIBRARY}")
|
||||||
message(STATUS " BINARY : ${WITH_BINARY}")
|
message(STATUS " BINARY : ${WITH_BINARY}")
|
||||||
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
|
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
|
||||||
|
message(STATUS " UPnP : ${WITH_UPNP}")
|
||||||
message(STATUS "---------------------------------------")
|
message(STATUS "---------------------------------------")
|
||||||
|
|
||||||
#Handle paths nicely
|
#Handle paths nicely
|
||||||
|
25
build/cmake_modules/FindMiniUPnPc.cmake
Normal file
25
build/cmake_modules/FindMiniUPnPc.cmake
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# - Find MINIUPNPC
|
||||||
|
|
||||||
|
if(MINIUPNPC_INCLUDE_DIR)
|
||||||
|
set(MINIUPNPC_FOUND TRUE)
|
||||||
|
|
||||||
|
else()
|
||||||
|
find_path(MINIUPNPC_INCLUDE_DIR miniupnpc.h
|
||||||
|
/usr/include/miniupnpc
|
||||||
|
/usr/local/include/miniupnpc
|
||||||
|
/opt/local/include/miniupnpc
|
||||||
|
$ENV{SystemDrive}/miniupnpc
|
||||||
|
${PROJECT_SOURCE_DIR}/../../miniupnpc
|
||||||
|
)
|
||||||
|
|
||||||
|
if(MINIUPNPC_INCLUDE_DIR)
|
||||||
|
set(MINIUPNPC_FOUND TRUE)
|
||||||
|
message(STATUS "Found MiniUPnP headers: ${MINIUPNPC_INCLUDE_DIR}")
|
||||||
|
else()
|
||||||
|
set(MINIUPNPC_FOUND FALSE)
|
||||||
|
message(STATUS "MiniUPnP not found.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced(MINIUPNPC_INCLUDE_DIR)
|
||||||
|
|
||||||
|
endif()
|
Loading…
x
Reference in New Issue
Block a user