Skip to content

Commit

Permalink
Enable Map port using UPnP
Browse files Browse the repository at this point in the history
  • Loading branch information
muddafudda committed May 19, 2015
1 parent 6fd8c4f commit 5dfdb3f
Show file tree
Hide file tree
Showing 9 changed files with 227 additions and 30 deletions.
14 changes: 13 additions & 1 deletion globalcoin-qt.pro
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,21 @@ contains(RELEASE, 1) {
}
}

# qmake "USE_UPNP=-" (not supported)
# use: qmake "USE_UPNP=1" ( enabled by default; default)
# or: qmake "USE_UPNP=0" (disabled by default)
# or: qmake "USE_UPNP=-" (not supported)
# miniupnpc (http://miniupnp.free.fr/files/) must be installed for support
contains(USE_UPNP, -) {
message(Building without UPNP support)
} else {
message(Building with UPNP support)
count(USE_UPNP, 0) {
USE_UPNP=1
}
DEFINES += USE_UPNP=$$USE_UPNP STATICLIB
INCLUDEPATH += $$MINIUPNPC_INCLUDE_PATH
LIBS += $$join(MINIUPNPC_LIB_PATH,,-L,) -lminiupnpc
win32:LIBS += -liphlpapi
}

# use: qmake "USE_QRCODE=1"
Expand Down
6 changes: 5 additions & 1 deletion src/bitcoinrpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2831,7 +2831,11 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol,
printf("Failed to create RPC server client thread\n");
delete conn;
}

// start HTTP client thread
else if (!NewThread(ThreadRPCServer3, conn)) {
printf("Failed to create RPC server client thread\n");
delete conn;
}
vnThreadsRunning[THREAD_RPCLISTENER]--;
}

Expand Down
19 changes: 14 additions & 5 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void StartShutdown()
uiInterface.QueueShutdown();
#else
// Without UI, Shutdown() can simply be started in a new thread
CreateThread(Shutdown, NULL);
NewThread(Shutdown, NULL);
#endif
}

Expand Down Expand Up @@ -79,7 +79,7 @@ void Shutdown(void* parg)
boost::filesystem::remove(GetPidFile());
UnregisterWallet(pwalletMain);
delete pwalletMain;
CreateThread(ExitTimeout, NULL);
NewThread(ExitTimeout, NULL);
Sleep(50);
printf("Globalcoin exited\n\n");
fExit = true;
Expand Down Expand Up @@ -249,6 +249,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" +
" -paytxfee=<amt> " + _("Fee per KB to add to transactions you send") + "\n" +
Expand Down Expand Up @@ -526,7 +533,9 @@ bool AppInit2()
fNoListen = !GetBoolArg("-listen", true);
fDiscover = GetBoolArg("-discover", true);
fNameLookup = GetBoolArg("-dns", true);

#ifdef USE_UPNP
fUseUPnP = GetBoolArg("-upnp", USE_UPNP);
#endif

bool fBound = false;
if (!fNoListen)
Expand Down Expand Up @@ -765,11 +774,11 @@ bool AppInit2()
printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size());

if (!CreateThread(StartNode, NULL))
if (!NewThread(StartNode, NULL))
InitError(_("Error: could not start node"));

if (fServer)
CreateThread(ThreadRPCServer, NULL);
NewThread(ThreadRPCServer, NULL);

// ********************************************************* Step 11: finished

Expand Down
190 changes: 171 additions & 19 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
#ifdef WIN32
#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 @@ -27,7 +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);
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);

Expand All @@ -42,7 +49,7 @@ struct LocalServiceInfo {
//
bool fClient = false;
bool fDiscover = true;

bool fUseUPnP = false;
uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
static CCriticalSection cs_mapLocalHost;
static map<CNetAddr, LocalServiceInfo> mapLocalHost;
Expand Down Expand Up @@ -978,6 +985,147 @@ void ThreadSocketHandler2(void* parg)
}


#ifdef USE_UPNP
void ThreadMapPort(void* parg)
{
// Make this thread recognisable as the UPnP thread
RenameThread("PayCon-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);
#else
/* miniupnpc 1.6 */
int error = 0;
devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &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 = "PayCon " + 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



Expand Down Expand Up @@ -1650,7 +1798,7 @@ void static Discover()
}
#endif

CreateThread(ThreadGetMyExternalIP, NULL);
NewThread(ThreadGetMyExternalIP, NULL);
}

void StartNode(void* parg)
Expand All @@ -1676,32 +1824,34 @@ void StartNode(void* parg)
if (!GetBoolArg("-dnsseed", true))
printf("DNS seeding disabled\n");
else
if (!CreateThread(ThreadDNSAddressSeed, NULL))
printf("Error: CreateThread(ThreadDNSAddressSeed) failed\n");

if (!NewThread(ThreadDNSAddressSeed, NULL))
printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
// Map ports with UPnP
if (fUseUPnP)
MapPort();

// Get addresses from IRC and advertise ours
if (!CreateThread(ThreadIRCSeed, NULL))
printf("Error: CreateThread(ThreadIRCSeed) failed\n");
if (!NewThread(ThreadIRCSeed, NULL))
printf("Error: NewThread(ThreadIRCSeed) failed\n");

// Send and receive from sockets, accept connections
if (!CreateThread(ThreadSocketHandler, NULL))
printf("Error: CreateThread(ThreadSocketHandler) failed\n");
if (!NewThread(ThreadSocketHandler, NULL))
printf("Error: NewThread(ThreadSocketHandler) failed\n");

// Initiate outbound connections from -addnode
if (!CreateThread(ThreadOpenAddedConnections, NULL))
printf("Error: CreateThread(ThreadOpenAddedConnections) failed\n");
if (!NewThread(ThreadOpenAddedConnections, NULL))
printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");

// Initiate outbound connections
if (!CreateThread(ThreadOpenConnections, NULL))
printf("Error: CreateThread(ThreadOpenConnections) failed\n");
if (!NewThread(ThreadOpenConnections, NULL))
printf("Error: NewThread(ThreadOpenConnections) failed\n");

// Process messages
if (!CreateThread(ThreadMessageHandler, NULL))
printf("Error: CreateThread(ThreadMessageHandler) failed\n");
if (!NewThread(ThreadMessageHandler, NULL))
printf("Error: NewThread(ThreadMessageHandler) failed\n");

// Dump network addresses
if (!CreateThread(ThreadDumpAddress, NULL))
if (!NewThread(ThreadDumpAddress, NULL))
printf("Error; CreateThread(ThreadDumpAddress) failed\n");

// Generate coins in the background
Expand Down Expand Up @@ -1734,7 +1884,9 @@ bool StopNode()
if (vnThreadsRunning[THREAD_MINER] > 0) printf("ThreadBitcoinMiner 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");
Expand Down
11 changes: 10 additions & 1 deletion src/qt/optionsmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ void OptionsModel::Init()

// These are shared with core Bitcoin; we want
// command-line options to override the GUI settings:
if (settings.contains("fUseUPnP"))
SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool());
if (settings.contains("addrProxy") && settings.value("fUseProxy").toBool())
SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString());
if (settings.contains("nSocksVersion") && settings.value("fUseProxy").toBool())
Expand Down Expand Up @@ -84,7 +86,7 @@ bool OptionsModel::Upgrade()
}
}
QList<QString> boolOptions;
boolOptions << "bDisplayAddresses" << "fMinimizeToTray" << "fMinimizeOnClose" << "fUseProxy" ;
boolOptions << "bDisplayAddresses" << "fMinimizeToTray" << "fMinimizeOnClose" << "fUseProxy" << "fUseUPnP";
foreach(QString key, boolOptions)
{
bool value = false;
Expand Down Expand Up @@ -136,6 +138,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
return QVariant(GUIUtil::GetStartOnSystemStartup());
case MinimizeToTray:
return QVariant(fMinimizeToTray);
case MapPortUPnP:
return settings.value("fUseUPnP", GetBoolArg("-upnp", true));
case MinimizeOnClose:
return QVariant(fMinimizeOnClose);
case ProxyUse:
Expand Down Expand Up @@ -187,6 +191,11 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
fMinimizeToTray = value.toBool();
settings.setValue("fMinimizeToTray", fMinimizeToTray);
break;
case MapPortUPnP:
fUseUPnP = value.toBool();
settings.setValue("fUseUPnP", fUseUPnP);
MapPort();
break;
case MinimizeOnClose:
fMinimizeOnClose = value.toBool();
settings.setValue("fMinimizeOnClose", fMinimizeOnClose);
Expand Down
2 changes: 1 addition & 1 deletion src/qt/qtipcserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ void ipcInit()
return;
}

if (!CreateThread(ipcThread, mq))
if (!NewThread(ipcThread, mq))
{
delete mq;
return;
Expand Down

0 comments on commit 5dfdb3f

Please sign in to comment.