mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-12 19:12:28 -04:00
Created V0.3.x branch and moved the head into the trunk directory.
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@246 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
commit
935745a08e
1318 changed files with 348809 additions and 0 deletions
356
libretroshare/src/upnp/upnphandler.cc
Normal file
356
libretroshare/src/upnp/upnphandler.cc
Normal file
|
@ -0,0 +1,356 @@
|
|||
|
||||
#include "dht/dhthandler.h"
|
||||
|
||||
|
||||
/* This stuff is actually C */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
/* This stuff is actually C */
|
||||
|
||||
|
||||
|
||||
|
||||
/* HACK TO SWITCH THIS OFF during testing */
|
||||
/*define NO_UPNP_RUNNING 1*/
|
||||
|
||||
#include "upnp/upnputil.h"
|
||||
#include "upnp/upnphandler.h"
|
||||
|
||||
class uPnPConfigData
|
||||
{
|
||||
public:
|
||||
struct UPNPDev * devlist;
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
char lanaddr[16]; /* my ip address on the LAN */
|
||||
};
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
void upnphandler::run()
|
||||
{
|
||||
|
||||
/* infinite loop */
|
||||
while(1)
|
||||
{
|
||||
std::cerr << "UPnPHandler::Run()" << std::endl;
|
||||
int allowedSleep = 30; /* check every 30 seconds */
|
||||
|
||||
/* lock it up */
|
||||
dataMtx.lock(); /* LOCK MUTEX */
|
||||
|
||||
bool shutdown = toShutdown;
|
||||
int state = upnpState;
|
||||
|
||||
dataMtx.unlock(); /* UNLOCK MUTEX */
|
||||
|
||||
if (shutdown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* do the work! */
|
||||
checkUPnPState();
|
||||
|
||||
/* check new state for sleep period */
|
||||
|
||||
dataMtx.lock(); /* LOCK MUTEX */
|
||||
|
||||
state = upnpState;
|
||||
|
||||
dataMtx.unlock(); /* UNLOCK MUTEX */
|
||||
|
||||
|
||||
/* state machine */
|
||||
switch(state)
|
||||
{
|
||||
case RS_UPNP_S_UNINITIALISED:
|
||||
case RS_UPNP_S_UNAVAILABLE:
|
||||
/* failed ... try again in 30 min. */
|
||||
allowedSleep = 1800;
|
||||
break;
|
||||
|
||||
case RS_UPNP_S_READY:
|
||||
case RS_UPNP_S_TCP_FAILED:
|
||||
case RS_UPNP_S_UDP_FAILED:
|
||||
case RS_UPNP_S_ACTIVE:
|
||||
/* working ... normal 15 seconds */
|
||||
allowedSleep = 15;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* default??? how did it get here? */
|
||||
break;
|
||||
}
|
||||
|
||||
std::cerr << "UPnPHandler::Run() sleeping for:" << allowedSleep << std::endl;
|
||||
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||
#ifndef WINDOWS_SYS
|
||||
sleep(allowedSleep);
|
||||
#else
|
||||
Sleep(1000 * allowedSleep);
|
||||
#endif
|
||||
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void upnphandler::checkUPnPState()
|
||||
{
|
||||
dataMtx.lock(); /* LOCK MUTEX */
|
||||
|
||||
int state = upnpState;
|
||||
|
||||
dataMtx.unlock(); /* UNLOCK MUTEX */
|
||||
|
||||
/* state machine */
|
||||
switch(state)
|
||||
{
|
||||
case RS_UPNP_S_UNINITIALISED:
|
||||
case RS_UPNP_S_UNAVAILABLE:
|
||||
initUPnPState();
|
||||
break;
|
||||
|
||||
case RS_UPNP_S_READY:
|
||||
case RS_UPNP_S_TCP_FAILED:
|
||||
case RS_UPNP_S_UDP_FAILED:
|
||||
case RS_UPNP_S_ACTIVE:
|
||||
printUPnPState();
|
||||
updateUPnP();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool upnphandler::initUPnPState()
|
||||
{
|
||||
/* allocate memory */
|
||||
uPnPConfigData *upcd = new uPnPConfigData;
|
||||
|
||||
upcd->devlist = upnpDiscover(2000);
|
||||
if(upcd->devlist)
|
||||
{
|
||||
struct UPNPDev * device;
|
||||
printf("List of UPNP devices found on the network :\n");
|
||||
for(device=upcd->devlist;device;device=device->pNext)
|
||||
{
|
||||
printf("\n desc: %s\n st: %s\n",
|
||||
device->descURL, device->st);
|
||||
}
|
||||
putchar('\n');
|
||||
if(UPNP_GetValidIGD(upcd->devlist, &(upcd->urls),
|
||||
&(upcd->data), upcd->lanaddr,
|
||||
sizeof(upcd->lanaddr)))
|
||||
{
|
||||
printf("Found valid IGD : %s\n",
|
||||
upcd->urls.controlURL);
|
||||
printf("Local LAN ip address : %s\n",
|
||||
upcd->lanaddr);
|
||||
|
||||
/* MODIFY STATE */
|
||||
dataMtx.lock(); /* LOCK MUTEX */
|
||||
|
||||
/* convert to ipaddress. */
|
||||
inet_aton(upcd->lanaddr, &(upnp_iaddr.sin_addr));
|
||||
upnp_iaddr.sin_port = iaddr.sin_port;
|
||||
|
||||
upnpState = RS_UPNP_S_READY;
|
||||
upnpConfig = upcd; /* */
|
||||
|
||||
dataMtx.unlock(); /* UNLOCK MUTEX */
|
||||
|
||||
|
||||
|
||||
|
||||
/* done -> READY */
|
||||
return 1;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
|
||||
}
|
||||
|
||||
|
||||
freeUPNPDevlist(upcd->devlist);
|
||||
upcd->devlist = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "No IGD UPnP Device found on the network !\n");
|
||||
}
|
||||
|
||||
upnpState = RS_UPNP_S_UNAVAILABLE;
|
||||
delete upcd;
|
||||
upnpConfig = NULL;
|
||||
|
||||
/* done, FAILED -> NOT AVAILABLE */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool upnphandler::printUPnPState()
|
||||
{
|
||||
std::cerr << "upnphandler::printUPnPState() ... locking";
|
||||
std::cerr << std::endl;
|
||||
|
||||
dataMtx.lock(); /* LOCK MUTEX */
|
||||
|
||||
std::cerr << "upnphandler::printUPnPState() ... locked";
|
||||
std::cerr << std::endl;
|
||||
|
||||
uPnPConfigData *config = upnpConfig;
|
||||
if ((upnpState >= RS_UPNP_S_READY) && (config))
|
||||
{
|
||||
DisplayInfos(&(config -> urls), &(config->data));
|
||||
GetConnectionStatus(&(config -> urls), &(config->data));
|
||||
ListRedirections(&(config -> urls), &(config->data));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "UPNP not Ready" << std::endl;
|
||||
}
|
||||
|
||||
dataMtx.unlock(); /* UNLOCK MUTEX */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool upnphandler::updateUPnP()
|
||||
{
|
||||
dataMtx.lock(); /* LOCK MUTEX */
|
||||
|
||||
|
||||
uPnPConfigData *config = upnpConfig;
|
||||
if (!((upnpState >= RS_UPNP_S_READY) && (config)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char eprot1[] = "TCP";
|
||||
char eprot2[] = "UDP";
|
||||
|
||||
/* if we're to unload -> unload */
|
||||
if ((toStop) && (eport_curr > 0))
|
||||
{
|
||||
toStop = false;
|
||||
|
||||
char eport1[256];
|
||||
char eport2[256];
|
||||
|
||||
snprintf(eport1, 256, "%d", eport_curr);
|
||||
snprintf(eport2, 256, "%d", eport_curr + 1);
|
||||
|
||||
std::cerr << "Attempting To Remove Redirection: port: " << eport1;
|
||||
std::cerr << " Prot: " << eprot1;
|
||||
std::cerr << std::endl;
|
||||
|
||||
RemoveRedirect(&(config -> urls), &(config->data),
|
||||
eport1, eprot1);
|
||||
|
||||
|
||||
std::cerr << "Attempting To Remove Redirection: port: " << eport2;
|
||||
std::cerr << " Prot: " << eprot2;
|
||||
std::cerr << std::endl;
|
||||
|
||||
RemoveRedirect(&(config -> urls), &(config->data),
|
||||
eport2, eprot2);
|
||||
|
||||
upnpState = RS_UPNP_S_READY;
|
||||
}
|
||||
|
||||
|
||||
/* if we're to load -> load */
|
||||
if (toStart)
|
||||
{
|
||||
/* select external ports */
|
||||
eport_curr = eport;
|
||||
if (!eport_curr)
|
||||
{
|
||||
/* use local port if eport is zero */
|
||||
eport_curr = ntohs(iaddr.sin_port);
|
||||
std::cerr << "Using LocalPort for extPort!";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
if (!eport_curr)
|
||||
{
|
||||
std::cerr << "Invalid eport ... ";
|
||||
std::cerr << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
toStart = false;
|
||||
|
||||
/* our port */
|
||||
char in_addr[256];
|
||||
char in_port1[256];
|
||||
char in_port2[256];
|
||||
char eport1[256];
|
||||
char eport2[256];
|
||||
|
||||
//struct sockaddr_in localAddr = iaddr;
|
||||
if (iaddr.sin_addr.s_addr != upnp_iaddr.sin_addr.s_addr)
|
||||
{
|
||||
std::cerr << "Warning ... Address Mismatch!";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
upnp_iaddr.sin_port = iaddr.sin_port;
|
||||
struct sockaddr_in localAddr = upnp_iaddr;
|
||||
|
||||
snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port));
|
||||
snprintf(in_port2, 256, "%d", ntohs(localAddr.sin_port) + 1);
|
||||
snprintf(in_addr, 256, "%d.%d.%d.%d",
|
||||
((localAddr.sin_addr.s_addr >> 0) & 0xff),
|
||||
((localAddr.sin_addr.s_addr >> 8) & 0xff),
|
||||
((localAddr.sin_addr.s_addr >> 16) & 0xff),
|
||||
((localAddr.sin_addr.s_addr >> 24) & 0xff));
|
||||
|
||||
snprintf(eport1, 256, "%d", eport_curr);
|
||||
snprintf(eport2, 256, "%d", eport_curr + 1);
|
||||
|
||||
std::cerr << "Attempting Redirection: InAddr: " << in_addr;
|
||||
std::cerr << " InPort: " << in_port1;
|
||||
std::cerr << " ePort: " << eport1;
|
||||
std::cerr << " eProt: " << eprot1;
|
||||
std::cerr << std::endl;
|
||||
|
||||
if (!SetRedirectAndTest(&(config -> urls), &(config->data),
|
||||
in_addr, in_port1, eport1, eprot1))
|
||||
{
|
||||
upnpState = RS_UPNP_S_TCP_FAILED;
|
||||
}
|
||||
else if (!SetRedirectAndTest(&(config -> urls), &(config->data),
|
||||
in_addr, in_port2, eport2, eprot2))
|
||||
{
|
||||
upnpState = RS_UPNP_S_UDP_FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
upnpState = RS_UPNP_S_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
dataMtx.unlock(); /* UNLOCK MUTEX */
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue