From d208b59d33af656dd845c72d7e4750c656d91b6c Mon Sep 17 00:00:00 2001 From: drbob Date: Sun, 28 Oct 2012 16:51:00 +0000 Subject: [PATCH] Split the upnp files into libupnp and miniupnp implementations. modified libretroshare.pro to allow either to be used. git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-gxs-b1@5733 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/libretroshare.pro | 57 ++- libretroshare/src/rsserver/rsinit.cc | 6 +- libretroshare/src/upnp/upnphandler_linux.cc | 431 +++++++++++++++++ libretroshare/src/upnp/upnphandler_linux.h | 78 ++++ ...upnphandler.cc => upnphandler_miniupnp.cc} | 437 ------------------ .../{upnphandler.h => upnphandler_miniupnp.h} | 93 +--- 6 files changed, 547 insertions(+), 555 deletions(-) create mode 100644 libretroshare/src/upnp/upnphandler_linux.cc create mode 100644 libretroshare/src/upnp/upnphandler_linux.h rename libretroshare/src/upnp/{upnphandler.cc => upnphandler_miniupnp.cc} (53%) rename libretroshare/src/upnp/{upnphandler.h => upnphandler_miniupnp.h} (50%) diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index f7d08313e..7b0bf9a71 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -154,15 +154,11 @@ HEADERS += retroshare/rsgame.h \ OBJECTS_DIR = temp/obj MOC_DIR = temp/moc DESTDIR = lib - - # miniupnp implementation files - #HEADERS += upnp/upnputil.h - #SOURCES += upnp/upnputil.c + + # linux/bsd can use either - libupnp is more complete and packaged. + #CONFIG += upnp_miniupnpc + CONFIG += upnp_libupnp - # libupnp implementation files - HEADERS += upnp/UPnPBase.h - SOURCES += upnp/UPnPBase.cpp - # zeroconf disabled at the end of libretroshare.pro (but need the code) #CONFIG += zeroconf #CONFIG += zcnatassist @@ -192,9 +188,8 @@ HEADERS += retroshare/rsgame.h \ DEFINES *= STATICLIB \ WIN32 - # miniupnp implementation files - HEADERS += upnp/upnputil.h - SOURCES += upnp/upnputil.c + CONFIG += upnp_miniupnpc + SSL_DIR = ../../../../openssl UPNPC_DIR = ../../../../miniupnpc-1.3 GPG_ERROR_DIR = ../../../../libgpg-error-1.7 @@ -230,9 +225,8 @@ HEADERS += retroshare/rsgame.h \ # QMAKE_CFLAGS_DEBUG += -O2 DEFINES += USE_CMD_ARGS - # miniupnp implementation files - HEADERS += upnp/upnputil.h - SOURCES += upnp/upnputil.c + CONFIG += upnp_libupnp + UPNPC_DIR = ../../../lib/miniupnpc-1.3 PTHREADS_DIR = ../../../lib/pthreads-w32-2-8-0-release ZLIB_DIR = ../../../lib/zlib-1.2.3 @@ -261,10 +255,8 @@ HEADERS += retroshare/rsgame.h \ # DEFINES *= MINIUPNPC_VERSION=13 DESTDIR = lib - # miniupnp implementation files - HEADERS += upnp/upnputil.h - SOURCES += upnp/upnputil.c - + CONFIG += upnp_miniupnpc + # zeroconf disabled at the end of libretroshare.pro (but need the code) CONFIG += zeroconf CONFIG += zcnatassist @@ -296,9 +288,13 @@ HEADERS += retroshare/rsgame.h \ -Dstatvfs64=statvfs \ -Dfopen64=fopen + # linux/bsd can use either - libupnp is more complete and packaged. + #CONFIG += upnp_miniupnpc + CONFIG += upnp_libupnp + # libupnp implementation files - HEADERS += upnp/UPnPBase.h - SOURCES += upnp/UPnPBase.cpp + HEADERS += upnp/UPnPBase.h upnp/upnphandler_linux.h + SOURCES += upnp/UPnPBase.cpp upnp/upnphandler_linux.cc DESTDIR = lib } @@ -417,7 +413,7 @@ HEADERS += retroshare/rsgame.h \ HEADERS += turtle/p3turtle.h \ turtle/rsturtleitem.h \ turtle/turtletypes.h - HEADERS += upnp/upnphandler.h + HEADERS += util/folderiterator.h \ util/rsdebug.h \ util/smallobject.h \ @@ -434,6 +430,7 @@ HEADERS += retroshare/rsgame.h \ util/rsrandom.h \ util/radix64.h \ util/pugiconfig.h + SOURCES += dbase/cachestrapper.cc \ dbase/fimonitor.cc \ dbase/findex.cc \ @@ -549,7 +546,7 @@ HEADERS += retroshare/rsgame.h \ # turtle/turtlerouting.cc \ # turtle/turtlesearch.cc \ # turtle/turtletunnels.cc - SOURCES += upnp/upnphandler.cc + SOURCES += util/folderiterator.cc \ util/rsdebug.cc \ util/smallobject.cc \ @@ -564,6 +561,18 @@ HEADERS += retroshare/rsgame.h \ util/rsversion.cc \ util/rswin.cc \ util/rsrandom.cc + + upnp_miniupnpc { + HEADERS += upnp/upnputil.h upnp/upnphandler_miniupnp.h + SOURCES += upnp/upnputil.c upnp/upnphandler_miniupnp.cc + } + + upnp_libupnp { + HEADERS += upnp/UPnPBase.h upnp/upnphandler_linux.h + SOURCES += upnp/UPnPBase.cpp upnp/upnphandler_linux.cc + DEFINES *= RS_USE_LIBUPNP + } + zeroconf { HEADERS += zeroconf/p3zeroconf.h SOURCES += zeroconf/p3zeroconf.cc @@ -600,7 +609,6 @@ HEADERS += retroshare/rsgame.h \ util/contentvalue.h \ gxs/gxscoreserver.h \ gxs/gxssecurity.h \ - gxs/gxssecurity.h \ gxs/rsgxsifaceimpl.h \ services/p3posted.h \ retroshare/rsposted.h \ @@ -620,7 +628,6 @@ HEADERS += retroshare/rsgame.h \ util/contentvalue.cc \ gxs/gxscoreserver.cc \ gxs/gxssecurity.cc \ - gxs/gxssecurity.cc \ gxs/rsgxsifaceimpl.cc \ services/p3posted.cc \ serialiser/rsposteditems.cc @@ -631,7 +638,7 @@ HEADERS += retroshare/rsgame.h \ services/p3idservice.h \ serialiser/rsgxsiditems.h - SOURCES += services/p3idservice.cc + #SOURCES += services/p3idservice.cc # serialiser/rsgxsiditems.cc \ # Wiki Service diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index 7510041c1..09508e322 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -1795,7 +1795,11 @@ RsTurtle *rsTurtle = NULL ; #ifdef RS_ENABLE_ZCNATASSIST #include "zeroconf/p3zcnatassist.h" #else - #include "upnp/upnphandler.h" + #ifdef RS_USE_LIBUPNP + #include "upnp/upnphandler_linux.h" + #else + #include "upnp/upnphandler_miniupnp.h" + #endif #endif #include "services/p3disc.h" diff --git a/libretroshare/src/upnp/upnphandler_linux.cc b/libretroshare/src/upnp/upnphandler_linux.cc new file mode 100644 index 000000000..5d54b5581 --- /dev/null +++ b/libretroshare/src/upnp/upnphandler_linux.cc @@ -0,0 +1,431 @@ +//Linux only +/* This stuff is actually C */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern C */ +#endif +/* This stuff is actually C */ + +#include "upnp/upnphandler_linux.h" + +#include "util/rsnet.h" + +bool upnphandler::initUPnPState() +{ + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::initUPnPState" << std::endl; + #endif + cUPnPControlPoint = new CUPnPControlPoint(2000); + + bool IGWDetected = cUPnPControlPoint->GetIGWDeviceDetected(); + + if (IGWDetected) { + /* MODIFY STATE */ + dataMtx.lock(); /* LOCK MUTEX */ + upnpState = RS_UPNP_S_READY; + + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::initUPnPState cUPnPControlPoint internal ip adress : "; + std::cerr << cUPnPControlPoint->getInternalIpAddress() << std::endl; + #endif + + //const char ipaddr = cUPnPControlPoint->getInternalIpAddress().c_str(); + inet_aton(cUPnPControlPoint->getInternalIpAddress(), &(upnp_iaddr.sin_addr)); + upnp_iaddr.sin_port = htons(iport); + + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::initUPnPState READY" << std::endl; + #endif + dataMtx.unlock(); /* UNLOCK MUTEX */ + + } else { + upnpState = RS_UPNP_S_UNAVAILABLE; + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::initUPnPState UNAVAILABLE" << std::endl; + #endif + } + + return 0; +} + +class upnpThreadData +{ + public: + upnphandler *handler; + bool start; + bool stop; +}; + + /* Thread routines */ +extern "C" void* doSetupUPnP(void* p) +{ + #ifdef UPNP_DEBUG + std::cerr << "doSetupUPnP Creating upnp thread." << std::endl; + #endif + upnpThreadData *data = (upnpThreadData *) p; + if ((!data) || (!data->handler)) + { + pthread_exit(NULL); + } + + /* publish it! */ + if (data -> stop) + { + data->handler->shutdown_upnp(); + } + + if (data -> start) + { + data->handler->initUPnPState(); + data->handler->start_upnp(); + } + + delete data; + pthread_exit(NULL); + + return NULL; +} + +bool upnphandler::background_setup_upnp(bool start, bool stop) +{ + pthread_t tid; + + /* launch thread */ + #ifdef UPNP_DEBUG + std::cerr << "background_setup_upnp Creating upnp thread." << std::endl; + #endif + upnpThreadData *data = new upnpThreadData(); + data->handler = this; + data->start = start; + data->stop = stop; + + pthread_create(&tid, 0, &doSetupUPnP, (void *) data); + pthread_detach(tid); /* so memory is reclaimed in linux */ + + return true; +} + +bool upnphandler::start_upnp() +{ + if (!(upnpState >= RS_UPNP_S_READY)) + { + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::start_upnp() Not Ready" << std::endl; + #endif + return false; + } + + struct sockaddr_in localAddr; + { + RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ + + /* if we're to load -> load */ + /* select external ports */ + eport_curr = eport; + if (!eport_curr) + { + /* use local port if eport is zero */ + eport_curr = iport; + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::start_upnp() Using LocalPort for extPort." << std::endl; + #endif + } + + if (!eport_curr) + { + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::start_upnp() Invalid eport ... " << std::endl; + #endif + return false; + } + + /* our port */ + char in_addr[256]; + char in_port1[256]; + + upnp_iaddr.sin_port = htons(iport); + localAddr = upnp_iaddr; + uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr); + snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port)); + snprintf(in_addr, 256, "%d.%d.%d.%d", + ((linaddr >> 24) & 0xff), + ((linaddr >> 16) & 0xff), + ((linaddr >> 8) & 0xff), + ((linaddr >> 0) & 0xff)); + + #ifdef UPNP_DEBUG + std::cerr << "Attempting Redirection: InAddr: " << in_addr; + std::cerr << " InPort: " << in_port1; + std::cerr << " ePort: " << eport_curr; + std::cerr << " eProt: " << "TCP and UDP"; + std::cerr << std::endl; + #endif + } + + //first of all, build the mappings + std::vector upnpPortMapping1; + CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "TCP", true, "tcp retroshare redirection"); + upnpPortMapping1.push_back(cUPnPPortMapping1); + std::vector upnpPortMapping2; + CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "UDP", true, "udp retroshare redirection"); + upnpPortMapping2.push_back(cUPnPPortMapping2); + + //attempt to remove formal port redirection rules + cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); + cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); + + //add new rules + bool res = cUPnPControlPoint->AddPortMappings(upnpPortMapping1); + bool res2 = cUPnPControlPoint->AddPortMappings(upnpPortMapping2); + + struct sockaddr_in extAddr; + bool extAddrResult = getExternalAddress(extAddr); + + { + RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ + + if (extAddrResult && (res || res2)) { + upnpState = RS_UPNP_S_ACTIVE; + } else { + upnpState = RS_UPNP_S_TCP_AND_FAILED; + } + + toStart = false; + } + + return (upnpState == RS_UPNP_S_ACTIVE); + +} + +bool upnphandler::shutdown_upnp() +{ + RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ + + /* always attempt this (unless no port number) */ + if (eport_curr > 0 && eport > 0 && (upnpState >= RS_UPNP_S_ACTIVE)) + { + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; + std::cerr << " Prot: TCP"; + std::cerr << std::endl; + #endif + + std::vector upnpPortMapping1; + CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, 0, "TCP", true, "tcp redirection"); + upnpPortMapping1.push_back(cUPnPPortMapping1); + cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); + + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; + std::cerr << " Prot: UDP"; + std::cerr << std::endl; + #endif + + std::vector upnpPortMapping2; + CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, 0, "UDP", true, "udp redirection"); + upnpPortMapping2.push_back(cUPnPPortMapping2); + cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); + + //destroy the upnp object + cUPnPControlPoint->~CUPnPControlPoint(); + } else { + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::shutdown_upnp() : avoid upnp connection for shutdonws because probably a net flag went down." << std::endl; + #endif + } + + //stopping os ok, set starting to true for next net reset + toStop = false; + toStart = true; + upnpState = RS_UPNP_S_UNINITIALISED; + + return true; + +} + +/************************ External Interface ***************************** + * + * + * + */ + +upnphandler::upnphandler() + : + upnpState(RS_UPNP_S_UNINITIALISED), dataMtx("upupState"), + cUPnPControlPoint(NULL), + toEnable(false), toStart(false), toStop(false), + iport(0),eport(0), eport_curr(0) +{ +} + +upnphandler::~upnphandler() +{ + return; +} + + /* RsIface */ +void upnphandler::enable(bool active) +{ + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::enable called with argument active : " << active << std::endl; + std::cerr << "toEnable : " << toEnable << std::endl; + std::cerr << "toStart : " << toStart << std::endl; + #endif + + dataMtx.lock(); /*** LOCK MUTEX ***/ + if (active != toEnable) + { + if (active) + { + toStart = true; + } + else + { + toStop = true; + } + } + toEnable = active; + + bool start = toStart; + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + if (start) + { + /* make background thread to startup UPnP */ + background_setup_upnp(true, false); + } +} + + +void upnphandler::shutdown() +{ + /* blocking call to shutdown upnp */ + + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::shutdown() called." << std::endl; + #endif + shutdown_upnp(); +} + + +void upnphandler::restart() +{ + /* non-blocking call to shutdown upnp, and startup again. */ + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::restart() called." << std::endl; + #endif + background_setup_upnp(true, true); +} + + + +bool upnphandler::getEnabled() +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + + bool on = toEnable; + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + return on; +} + +bool upnphandler::getActive() +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + + #ifdef UPNP_DEBUG + std::cerr <<"upnphandler::getActive() result : " << (upnpState == RS_UPNP_S_ACTIVE) << std::endl; + #endif + + bool on = (upnpState == RS_UPNP_S_ACTIVE); + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + return on; +} + + /* the address that the listening port is on */ +void upnphandler::setInternalPort(unsigned short iport_in) +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + if (iport != iport_in) + { + iport = iport_in; + if ((toEnable) && + (upnpState == RS_UPNP_S_ACTIVE)) + { + toStop = true; + toStart = true; + } + } + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ +} + +void upnphandler::setExternalPort(unsigned short eport_in) +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + /* flag both shutdown/start -> for restart */ + if (eport != eport_in) + { + eport = eport_in; + if ((toEnable) && + (upnpState == RS_UPNP_S_ACTIVE)) + { + toStop = true; + toStart = true; + } + } + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ +} + + /* as determined by uPnP */ +bool upnphandler::getInternalAddress(struct sockaddr_in &addr) +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + addr = upnp_iaddr; + bool valid = (upnpState >= RS_UPNP_S_ACTIVE); + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + return valid; +} + +bool upnphandler::getExternalAddress(struct sockaddr_in &addr) +{ + std::string externalAdress = cUPnPControlPoint->getExternalAddress(); + + if(!externalAdress.empty() && externalAdress != "") + { + const char* externalIPAddress = externalAdress.c_str(); + + #ifdef UPNP_DEBUG + std::cerr << " upnphandler::getExternalAddress() : " << externalIPAddress; + std::cerr << ":" << eport_curr; + std::cerr << std::endl; + #endif + + dataMtx.lock(); /*** LOCK MUTEX ***/ + sockaddr_clear(&upnp_eaddr); + inet_aton(externalIPAddress, &(upnp_eaddr.sin_addr)); + upnp_eaddr.sin_family = AF_INET; + upnp_eaddr.sin_port = htons(eport_curr); + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + addr = upnp_eaddr; + return true; + } + else + { + return false; + } +} + + + diff --git a/libretroshare/src/upnp/upnphandler_linux.h b/libretroshare/src/upnp/upnphandler_linux.h new file mode 100644 index 000000000..44b6c073a --- /dev/null +++ b/libretroshare/src/upnp/upnphandler_linux.h @@ -0,0 +1,78 @@ +#ifndef _RS_UPNP_IFACE_H +#define _RS_UPNP_IFACE_H + +#include + +/* platform independent networking... */ +#include "pqi/pqinetwork.h" +#include "pqi/pqiassist.h" + +#include "util/rsthreads.h" + +#include +#include "upnp/UPnPBase.h" + +#define RS_UPNP_S_UNINITIALISED 0 +#define RS_UPNP_S_UNAVAILABLE 1 +#define RS_UPNP_S_READY 2 +#define RS_UPNP_S_TCP_AND_FAILED 3 +//#define RS_UPNP_S_UDP_FAILED 4 +#define RS_UPNP_S_ACTIVE 5 + +class upnphandler: public pqiNetAssistFirewall +{ + public: + + upnphandler(); + virtual ~upnphandler(); + + /* External Interface (pqiNetAssistFirewall) */ + virtual void enable(bool active); + virtual void shutdown(); + virtual void restart(); + + virtual bool getEnabled(); + virtual bool getActive(); + + virtual void setInternalPort(unsigned short iport_in); + virtual void setExternalPort(unsigned short eport_in); + virtual bool getInternalAddress(struct sockaddr_in &addr); + virtual bool getExternalAddress(struct sockaddr_in &addr); + + /* Public functions - for background thread operation, + * but effectively private from rest of RS, as in derived class + */ + unsigned int upnpState; + + bool start_upnp(); + bool shutdown_upnp(); + + bool initUPnPState(); + + /* Mutex for data below */ + RsMutex dataMtx; + + private: + + CUPnPControlPoint *cUPnPControlPoint; + + bool background_setup_upnp(bool, bool); + + + bool toEnable; /* overall on/off switch */ + bool toStart; /* if set start forwarding */ + bool toStop; /* if set stop forwarding */ + + unsigned short iport; + unsigned short eport; /* config */ + unsigned short eport_curr; /* current forwarded */ + + /* info from upnp */ + struct sockaddr_in upnp_iaddr; + struct sockaddr_in upnp_eaddr; +}; + +/* info from upnp */ +int CtrlPointCallbackEventHandler(Upnp_EventType ,void* , void*); + +#endif /* _RS_UPNP_IFACE_H */ diff --git a/libretroshare/src/upnp/upnphandler.cc b/libretroshare/src/upnp/upnphandler_miniupnp.cc similarity index 53% rename from libretroshare/src/upnp/upnphandler.cc rename to libretroshare/src/upnp/upnphandler_miniupnp.cc index d77aa90d1..5d3937ca1 100644 --- a/libretroshare/src/upnp/upnphandler.cc +++ b/libretroshare/src/upnp/upnphandler_miniupnp.cc @@ -1,440 +1,4 @@ -//Linux only -#if !defined(WINDOWS_SYS) && !defined(__APPLE__) - -/* This stuff is actually C */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} /* extern C */ -#endif -/* This stuff is actually C */ - -#include "upnp/upnphandler.h" - -#include "util/rsnet.h" - -bool upnphandler::initUPnPState() -{ - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState" << std::endl; - #endif - cUPnPControlPoint = new CUPnPControlPoint(2000); - - bool IGWDetected = cUPnPControlPoint->GetIGWDeviceDetected(); - - if (IGWDetected) { - /* MODIFY STATE */ - dataMtx.lock(); /* LOCK MUTEX */ - upnpState = RS_UPNP_S_READY; - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState cUPnPControlPoint internal ip adress : "; - std::cerr << cUPnPControlPoint->getInternalIpAddress() << std::endl; - #endif - - //const char ipaddr = cUPnPControlPoint->getInternalIpAddress().c_str(); - inet_aton(cUPnPControlPoint->getInternalIpAddress(), &(upnp_iaddr.sin_addr)); - upnp_iaddr.sin_port = htons(iport); - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState READY" << std::endl; - #endif - dataMtx.unlock(); /* UNLOCK MUTEX */ - - } else { - upnpState = RS_UPNP_S_UNAVAILABLE; - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState UNAVAILABLE" << std::endl; - #endif - } - - return 0; -} - -class upnpThreadData -{ - public: - upnphandler *handler; - bool start; - bool stop; -}; - - /* Thread routines */ -extern "C" void* doSetupUPnP(void* p) -{ - #ifdef UPNP_DEBUG - std::cerr << "doSetupUPnP Creating upnp thread." << std::endl; - #endif - upnpThreadData *data = (upnpThreadData *) p; - if ((!data) || (!data->handler)) - { - pthread_exit(NULL); - } - - /* publish it! */ - if (data -> stop) - { - data->handler->shutdown_upnp(); - } - - if (data -> start) - { - data->handler->initUPnPState(); - data->handler->start_upnp(); - } - - delete data; - pthread_exit(NULL); - - return NULL; -} - -bool upnphandler::background_setup_upnp(bool start, bool stop) -{ - pthread_t tid; - - /* launch thread */ - #ifdef UPNP_DEBUG - std::cerr << "background_setup_upnp Creating upnp thread." << std::endl; - #endif - upnpThreadData *data = new upnpThreadData(); - data->handler = this; - data->start = start; - data->stop = stop; - - pthread_create(&tid, 0, &doSetupUPnP, (void *) data); - pthread_detach(tid); /* so memory is reclaimed in linux */ - - return true; -} - -bool upnphandler::start_upnp() -{ - if (!(upnpState >= RS_UPNP_S_READY)) - { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::start_upnp() Not Ready" << std::endl; - #endif - return false; - } - - struct sockaddr_in localAddr; - { - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - /* if we're to load -> load */ - /* select external ports */ - eport_curr = eport; - if (!eport_curr) - { - /* use local port if eport is zero */ - eport_curr = iport; - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::start_upnp() Using LocalPort for extPort." << std::endl; - #endif - } - - if (!eport_curr) - { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::start_upnp() Invalid eport ... " << std::endl; - #endif - return false; - } - - /* our port */ - char in_addr[256]; - char in_port1[256]; - - upnp_iaddr.sin_port = htons(iport); - localAddr = upnp_iaddr; - uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr); - snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port)); - snprintf(in_addr, 256, "%d.%d.%d.%d", - ((linaddr >> 24) & 0xff), - ((linaddr >> 16) & 0xff), - ((linaddr >> 8) & 0xff), - ((linaddr >> 0) & 0xff)); - - #ifdef UPNP_DEBUG - std::cerr << "Attempting Redirection: InAddr: " << in_addr; - std::cerr << " InPort: " << in_port1; - std::cerr << " ePort: " << eport_curr; - std::cerr << " eProt: " << "TCP and UDP"; - std::cerr << std::endl; - #endif - } - - //first of all, build the mappings - std::vector upnpPortMapping1; - CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "TCP", true, "tcp retroshare redirection"); - upnpPortMapping1.push_back(cUPnPPortMapping1); - std::vector upnpPortMapping2; - CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "UDP", true, "udp retroshare redirection"); - upnpPortMapping2.push_back(cUPnPPortMapping2); - - //attempt to remove formal port redirection rules - cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); - cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); - - //add new rules - bool res = cUPnPControlPoint->AddPortMappings(upnpPortMapping1); - bool res2 = cUPnPControlPoint->AddPortMappings(upnpPortMapping2); - - struct sockaddr_in extAddr; - bool extAddrResult = getExternalAddress(extAddr); - - { - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - if (extAddrResult && (res || res2)) { - upnpState = RS_UPNP_S_ACTIVE; - } else { - upnpState = RS_UPNP_S_TCP_AND_FAILED; - } - - toStart = false; - } - - return (upnpState == RS_UPNP_S_ACTIVE); - -} - -bool upnphandler::shutdown_upnp() -{ - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - /* always attempt this (unless no port number) */ - if (eport_curr > 0 && eport > 0 && (upnpState >= RS_UPNP_S_ACTIVE)) - { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; - std::cerr << " Prot: TCP"; - std::cerr << std::endl; - #endif - - std::vector upnpPortMapping1; - CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, 0, "TCP", true, "tcp redirection"); - upnpPortMapping1.push_back(cUPnPPortMapping1); - cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; - std::cerr << " Prot: UDP"; - std::cerr << std::endl; - #endif - - std::vector upnpPortMapping2; - CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, 0, "UDP", true, "udp redirection"); - upnpPortMapping2.push_back(cUPnPPortMapping2); - cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); - - //destroy the upnp object - cUPnPControlPoint->~CUPnPControlPoint(); - } else { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown_upnp() : avoid upnp connection for shutdonws because probably a net flag went down." << std::endl; - #endif - } - - //stopping os ok, set starting to true for next net reset - toStop = false; - toStart = true; - upnpState = RS_UPNP_S_UNINITIALISED; - - return true; - -} - -/************************ External Interface ***************************** - * - * - * - */ - -upnphandler::upnphandler() - : - upnpState(RS_UPNP_S_UNINITIALISED), dataMtx("upupState"), - cUPnPControlPoint(NULL), - toEnable(false), toStart(false), toStop(false), - iport(0),eport(0), eport_curr(0) -{ -} - -upnphandler::~upnphandler() -{ - return; -} - - /* RsIface */ -void upnphandler::enable(bool active) -{ - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::enable called with argument active : " << active << std::endl; - std::cerr << "toEnable : " << toEnable << std::endl; - std::cerr << "toStart : " << toStart << std::endl; - #endif - - dataMtx.lock(); /*** LOCK MUTEX ***/ - if (active != toEnable) - { - if (active) - { - toStart = true; - } - else - { - toStop = true; - } - } - toEnable = active; - - bool start = toStart; - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - if (start) - { - /* make background thread to startup UPnP */ - background_setup_upnp(true, false); - } -} - - -void upnphandler::shutdown() -{ - /* blocking call to shutdown upnp */ - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown() called." << std::endl; - #endif - shutdown_upnp(); -} - - -void upnphandler::restart() -{ - /* non-blocking call to shutdown upnp, and startup again. */ - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::restart() called." << std::endl; - #endif - background_setup_upnp(true, true); -} - - - -bool upnphandler::getEnabled() -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - bool on = toEnable; - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return on; -} - -bool upnphandler::getActive() -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - #ifdef UPNP_DEBUG - std::cerr <<"upnphandler::getActive() result : " << (upnpState == RS_UPNP_S_ACTIVE) << std::endl; - #endif - - bool on = (upnpState == RS_UPNP_S_ACTIVE); - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return on; -} - - /* the address that the listening port is on */ -void upnphandler::setInternalPort(unsigned short iport_in) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - if (iport != iport_in) - { - iport = iport_in; - if ((toEnable) && - (upnpState == RS_UPNP_S_ACTIVE)) - { - toStop = true; - toStart = true; - } - } - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ -} - -void upnphandler::setExternalPort(unsigned short eport_in) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - /* flag both shutdown/start -> for restart */ - if (eport != eport_in) - { - eport = eport_in; - if ((toEnable) && - (upnpState == RS_UPNP_S_ACTIVE)) - { - toStop = true; - toStart = true; - } - } - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ -} - - /* as determined by uPnP */ -bool upnphandler::getInternalAddress(struct sockaddr_in &addr) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - addr = upnp_iaddr; - bool valid = (upnpState >= RS_UPNP_S_ACTIVE); - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return valid; -} - -bool upnphandler::getExternalAddress(struct sockaddr_in &addr) -{ - std::string externalAdress = cUPnPControlPoint->getExternalAddress(); - - if(!externalAdress.empty() && externalAdress != "") - { - const char* externalIPAddress = externalAdress.c_str(); - - #ifdef UPNP_DEBUG - std::cerr << " upnphandler::getExternalAddress() : " << externalIPAddress; - std::cerr << ":" << eport_curr; - std::cerr << std::endl; - #endif - - dataMtx.lock(); /*** LOCK MUTEX ***/ - sockaddr_clear(&upnp_eaddr); - inet_aton(externalIPAddress, &(upnp_eaddr.sin_addr)); - upnp_eaddr.sin_family = AF_INET; - upnp_eaddr.sin_port = htons(eport_curr); - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - addr = upnp_eaddr; - return true; - } - else - { - return false; - } -} -#endif - - - // Windows / Mac version. -#if defined(WINDOWS_SYS) || defined(__APPLE__) - /* This stuff is actually C */ #ifdef __cplusplus @@ -1001,4 +565,3 @@ bool upnphandler::getExternalAddress(struct sockaddr_in &addr) return valid; } -#endif diff --git a/libretroshare/src/upnp/upnphandler.h b/libretroshare/src/upnp/upnphandler_miniupnp.h similarity index 50% rename from libretroshare/src/upnp/upnphandler.h rename to libretroshare/src/upnp/upnphandler_miniupnp.h index 80b8560de..6708e68a0 100644 --- a/libretroshare/src/upnp/upnphandler.h +++ b/libretroshare/src/upnp/upnphandler_miniupnp.h @@ -1,94 +1,4 @@ -//Linux only... -#if !defined(WINDOWS_SYS) && !defined(__APPLE__) - -#ifndef _RS_UPNP_IFACE_H -#define _RS_UPNP_IFACE_H - -#include - -/* platform independent networking... */ -#include "pqi/pqinetwork.h" -#include "pqi/pqiassist.h" - -#include "util/rsthreads.h" - -#include -#include "upnp/UPnPBase.h" - -#define RS_UPNP_S_UNINITIALISED 0 -#define RS_UPNP_S_UNAVAILABLE 1 -#define RS_UPNP_S_READY 2 -#define RS_UPNP_S_TCP_AND_FAILED 3 -//#define RS_UPNP_S_UDP_FAILED 4 -#define RS_UPNP_S_ACTIVE 5 - -class upnphandler: public pqiNetAssistFirewall -{ - public: - - upnphandler(); - virtual ~upnphandler(); - - /* External Interface (pqiNetAssistFirewall) */ - virtual void enable(bool active); - virtual void shutdown(); - virtual void restart(); - - virtual bool getEnabled(); - virtual bool getActive(); - - virtual void setInternalPort(unsigned short iport_in); - virtual void setExternalPort(unsigned short eport_in); - virtual bool getInternalAddress(struct sockaddr_in &addr); - virtual bool getExternalAddress(struct sockaddr_in &addr); - - /* Public functions - for background thread operation, - * but effectively private from rest of RS, as in derived class - */ - unsigned int upnpState; - - bool start_upnp(); - bool shutdown_upnp(); - - bool initUPnPState(); - - /* Mutex for data below */ - RsMutex dataMtx; - - private: - - CUPnPControlPoint *cUPnPControlPoint; - - bool background_setup_upnp(bool, bool); - - - bool toEnable; /* overall on/off switch */ - bool toStart; /* if set start forwarding */ - bool toStop; /* if set stop forwarding */ - - unsigned short iport; - unsigned short eport; /* config */ - unsigned short eport_curr; /* current forwarded */ - - /* info from upnp */ - struct sockaddr_in upnp_iaddr; - struct sockaddr_in upnp_eaddr; -}; - -/* info from upnp */ -int CtrlPointCallbackEventHandler(Upnp_EventType ,void* , void*); - -#endif /* _RS_UPNP_IFACE_H */ - -#endif - - - - - -#if defined(WINDOWS_SYS) || defined(__APPLE__) - -//windows implementation +//windows/osx (miniupnpc) implementation #ifndef _RS_UPNP_IFACE_H #define _RS_UPNP_IFACE_H @@ -194,4 +104,3 @@ bool checkUPnPActive(); }; #endif /* _RS_UPNP_IFACE_H */ -#endif