Skip to content

Commit

Permalink
Import UPnP code from novacoin(novacoin-project/novacoin@1c7ed42)
Browse files Browse the repository at this point in the history
Currently, supports only macOS XPd and XP-Qt.
  • Loading branch information
Naruto committed Mar 10, 2018
1 parent 4286f80 commit 7e1345a
Show file tree
Hide file tree
Showing 18 changed files with 372 additions and 11 deletions.
60 changes: 58 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ project(XPd CXX C)
# ----------------------------------------------------------------------------
option(USE_IPV6 "use IPV6" YES)
option(USE_LEVELDB "use leveldb" NO)
option(USE_UPNP "use UPNP" NO)
option(USE_ASM "use ASM" NO)
option(USE_SSE2 "use SSE2" NO)
if(MSVC)
Expand Down Expand Up @@ -97,6 +98,19 @@ else()
endif()
endif()

## upnp
if(USE_UPNP)
if (DEFINED $ENV{MINIUPNPC_INCLUDE_PATH})
include_directories($ENV{MINIUPNPC_INCLUDE_PATH})
else()
if(APPLE AND (${CMAKE_SYSTEM_NAME} MATCHES "Darwin"))
include_directories(${DEPSDIR}/miniupnpc/include)
elseif(MSVC)
# TODO:
endif()
endif()
endif()

# library directories
## openssl
if (DEFINED $ENV{OPENSSL_LIB_PATH})
Expand Down Expand Up @@ -177,6 +191,19 @@ else()
# TODO:
endif()

## upnp
if(USE_UPNP)
if (DEFINED $ENV{MINIUPNPC_LIB_PATH})
set(OPENSSL_LIB_PATH $ENV{MINIUPNPC_LIB_PATH})
else()
if(APPLE AND (${CMAKE_SYSTEM_NAME} MATCHES "Darwin"))
set(MINIUPNPC_LIB_PATH ${DEPSDIR}/miniupnpc/lib)
elseif(MSVC)
# TODO:
endif()
endif()
link_directories(${MINIUPNPC_LIB_PATH})
endif()

#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_STANDARD 11)
Expand Down Expand Up @@ -241,7 +268,26 @@ else()
endif()
endif()

add_definitions(-DUSE_IPV6=${USE_IPV6})
if(USE_UPNP)
if(MSVC)
add_definitions(/DUSE_UPNP=1)
else()
add_definitions(-DUSE_UPNP=1)
endif()
endif()

if(USE_IPV6)
set(USE_IPV6VAL 1)
else()
set(USE_IPV6VAL 0)
endif()

if(MSVC)
add_definitions(/DUSE_IPV6=${USE_IPV6VAL})
else()
add_definitions(-DUSE_IPV6=${USE_IPV6VAL})
endif()

if(APPLE AND (${CMAKE_SYSTEM_NAME} MATCHES "Darwin"))
add_definitions(-DMAC_OSX)
add_definitions(-DMSG_NOSIGNAL=0)
Expand Down Expand Up @@ -319,7 +365,11 @@ if(ENABLE_STATIC)
${OPENSSL_LIB_PATH}/libcrypto${CMAKE_FIND_LIBRARY_SUFFIXES}
z
)

endif()
if(USE_UPNP)
target_link_libraries(XPd
${MINIUPNPC_LIB_PATH}/libminiupnpc${CMAKE_FIND_LIBRARY_SUFFIXES}
)
endif()
else()
target_link_libraries(XPd
Expand All @@ -332,4 +382,10 @@ else()
crypto
z
)
if(USE_UPNP)
target_link_libraries(XPd
miniupnpc
)
endif()
endif()

13 changes: 12 additions & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,13 @@ std::string HelpMessage()
" -bantime=<n> " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" +
" -maxreceivebuffer=<n> " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)") + "\n" +
" -maxsendbuffer=<n> " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)") + "\n" +
#ifdef USE_UPNP
#if USE_UPNP
" -upnp " + _("Use UPnP to map the listening port (default: 1 when listening)") + "\n" +
#else
" -upnp " + _("Use UPnP to map the listening port (default: 0)") + "\n" +
#endif
#endif
" -detachdb " + _("Detach block and address databases. Increases shutdown time (default: 0)") + "\n" +

#ifdef DB_LOG_IN_MEMORY
Expand Down Expand Up @@ -421,6 +428,7 @@ bool AppInit2()

if (!GetBoolArg("-listen", true)) {
// do not map ports or try to retrieve public IP when not listening (pointless)
SoftSetBoolArg("-upnp", false);
SoftSetBoolArg("-discover", false);
}

Expand Down Expand Up @@ -667,10 +675,13 @@ bool AppInit2()
fNoListen = !GetBoolArg("-listen", true);
fDiscover = GetBoolArg("-discover", true);
fNameLookup = GetBoolArg("-dns", true);
#ifdef USE_UPNP
fUseUPnP = GetBoolArg("-upnp", USE_UPNP);
#endif
} else {
// Don't listen, discover addresses or search for nodes if IPv4 and IPv6 networking is disabled.
fNoListen = true;
fDiscover = fNameLookup = false;
fDiscover = fNameLookup = fUseUPnP = false;
SoftSetBoolArg("-irc", false);
SoftSetBoolArg("-dnsseed", false);
}
Expand Down
6 changes: 6 additions & 0 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20
// Maximum number of script-checking threads allowed
static const int MAX_SCRIPTCHECK_THREADS = 16;

#ifdef USE_UPNP
static const int fHaveUPnP = true;
#else
static const int fHaveUPnP = false;
#endif

static const uint256 hashGenesisBlock("0x0000065a10945931644cdda436d5ad0742d085e9dee3e7fdd51b822626727e78");
static const uint256 hashGenesisBlockTestNet("0x0000e097477b585e7289f4c23c4ff639a8775e8f4d2c715586f160fff8869278");

Expand Down
180 changes: 180 additions & 0 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
#include <string.h>
#endif

#ifdef USE_UPNP
#include <miniupnpc/miniwget.h>
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/upnpcommands.h>
#include <miniupnpc/upnperrors.h>
#endif

using namespace std;
using namespace boost;

Expand All @@ -25,6 +32,9 @@ void ThreadMessageHandler2(void* parg);
void ThreadSocketHandler2(void* parg);
void ThreadOpenConnections2(void* parg);
void ThreadOpenAddedConnections2(void* parg);
#ifdef USE_UPNP
void ThreadMapPort2(void* parg);
#endif
void ThreadDNSAddressSeed2(void* parg);

// Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
Expand All @@ -48,6 +58,7 @@ struct LocalServiceInfo {
//
bool fClient = false;
bool fDiscover = true;
bool fUseUPnP = false;
uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
static CCriticalSection cs_mapLocalHost;
static map<CNetAddr, LocalServiceInfo> mapLocalHost;
Expand Down Expand Up @@ -934,6 +945,167 @@ void ThreadSocketHandler2(void* parg)
}
}








#ifdef USE_UPNP
void ThreadMapPort(void* parg)
{
// Make this thread recognisable as the UPnP thread
RenameThread("xpcoin-UPnP");

try
{
vnThreadsRunning[THREAD_UPNP]++;
ThreadMapPort2(parg);
vnThreadsRunning[THREAD_UPNP]--;
}
catch (std::exception& e) {
vnThreadsRunning[THREAD_UPNP]--;
PrintException(&e, "ThreadMapPort()");
} catch (...) {
vnThreadsRunning[THREAD_UPNP]--;
PrintException(NULL, "ThreadMapPort()");
}
printf("ThreadMapPort exited\n");
}

void ThreadMapPort2(void* parg)
{
printf("ThreadMapPort started\n");

std::string port = strprintf("%u", GetListenPort());
const char * multicastif = 0;
const char * minissdpdpath = 0;
struct UPNPDev * devlist = 0;
char lanaddr[64];

#ifndef UPNPDISCOVER_SUCCESS
/* miniupnpc 1.5 */
devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
#elif MINIUPNPC_API_VERSION < 14
/* miniupnpc 1.6 */
int error = 0;
devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
#else
/* miniupnpc 1.9.20150730 */
int error = 0;
devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error);
#endif

struct UPNPUrls urls;
struct IGDdatas data;
int r;

r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
if (r == 1)
{
if (fDiscover) {
char externalIPAddress[40];
r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
if(r != UPNPCOMMAND_SUCCESS)
printf("UPnP: GetExternalIPAddress() returned %d\n", r);
else
{
if(externalIPAddress[0])
{
printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
}
else
printf("UPnP: GetExternalIPAddress failed.\n");
}
}

string strDesc = "XPCoin " + FormatFullVersion();
#ifndef UPNPDISCOVER_SUCCESS
/* miniupnpc 1.5 */
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
#else
/* miniupnpc 1.6 */
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
#endif

if(r!=UPNPCOMMAND_SUCCESS)
printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
else
printf("UPnP Port Mapping successful.\n");
int i = 1;
while (true)
{
if (fShutdown || !fUseUPnP)
{
r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
printf("UPNP_DeletePortMapping() returned : %d\n", r);
freeUPNPDevlist(devlist); devlist = 0;
FreeUPNPUrls(&urls);
return;
}
if (i % 600 == 0) // Refresh every 20 minutes
{
#ifndef UPNPDISCOVER_SUCCESS
/* miniupnpc 1.5 */
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
#else
/* miniupnpc 1.6 */
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
#endif

if(r!=UPNPCOMMAND_SUCCESS)
printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
else
printf("UPnP Port Mapping successful.\n");;
}
Sleep(2000);
i++;
}
} else {
printf("No valid UPnP IGDs found\n");
freeUPNPDevlist(devlist); devlist = 0;
if (r != 0)
FreeUPNPUrls(&urls);
while (true)
{
if (fShutdown || !fUseUPnP)
return;
Sleep(2000);
}
}
}

void MapPort()
{
if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
{
if (!NewThread(ThreadMapPort, NULL))
printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
}
}
#else
void MapPort()
{
// Intentionally left blank.
}
#endif









// DNS seeds
// Each pair gives a source name and a seed name.
// The first name is used as information source for addrman.
Expand Down Expand Up @@ -1699,6 +1871,11 @@ void StartNode(void* parg)
else
if (!NewThread(ThreadDNSAddressSeed, NULL))
printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
// Map ports with UPnP
if (!fUseUPnP)
printf("UPNP port mapping is disabled\n");
else
MapPort();

// Get addresses from IRC and advertise ours
if (!GetBoolArg("-irc", true))
Expand Down Expand Up @@ -1768,6 +1945,9 @@ bool StopNode()
if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
#ifdef USE_UPNP
if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
#endif
if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
Expand Down
3 changes: 3 additions & 0 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ enum
LOCAL_NONE, // unknown
LOCAL_IF, // address a local interface listens on
LOCAL_BIND, // address explicit bound to
LOCAL_UPNP, // address reported by UPnP
LOCAL_IRC, // address reported by IRC (deprecated)
LOCAL_HTTP, // address reported by whatismyip.com and similar
LOCAL_MANUAL, // address explicitly specified (-externalip=)
Expand Down Expand Up @@ -106,6 +107,7 @@ enum threadId
THREAD_OPENCONNECTIONS,
THREAD_MESSAGEHANDLER,
THREAD_RPCLISTENER,
THREAD_UPNP,
THREAD_DNSSEED,
THREAD_ADDEDCONNECTIONS,
THREAD_DUMPADDRESS,
Expand All @@ -119,6 +121,7 @@ enum threadId

extern bool fClient;
extern bool fDiscover;
extern bool fUseUPnP;
extern uint64_t nLocalServices;
extern uint64_t nLocalHostNonce;
extern CAddress addrSeenByPeer;
Expand Down
Loading

0 comments on commit 7e1345a

Please sign in to comment.