mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-26 16:09:35 -05:00
2089 lines
55 KiB
C++
2089 lines
55 KiB
C++
/*******************************************************************************
|
|
* libretroshare/src/pqi: p3netmgr.cc *
|
|
* *
|
|
* libretroshare: retroshare core library *
|
|
* *
|
|
* Copyright (C) 2007-2011 Robert Fernie <retroshare@lunamutt.com> *
|
|
* Copyright (C) 2015-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
|
* *
|
|
* This program is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Lesser General Public License as *
|
|
* published by the Free Software Foundation, either version 3 of the *
|
|
* License, or (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Lesser General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Lesser General Public License *
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
|
* *
|
|
*******************************************************************************/
|
|
#include "util/rstime.h"
|
|
#include <vector>
|
|
|
|
#include "pqi/p3netmgr.h"
|
|
|
|
#include "pqi/p3peermgr.h"
|
|
#include "pqi/p3linkmgr.h"
|
|
|
|
#include "util/rsnet.h"
|
|
#include "util/rsrandom.h"
|
|
#include "util/rsdebug.h"
|
|
|
|
#include "util/extaddrfinder.h"
|
|
#include "util/dnsresolver.h"
|
|
|
|
|
|
struct RsLog::logInfo p3netmgrzoneInfo = {RsLog::Default, "p3netmgr"};
|
|
#define p3netmgrzone &p3netmgrzoneInfo
|
|
|
|
#include "rsitems/rsconfigitems.h"
|
|
|
|
#include "retroshare/rsiface.h"
|
|
#include "retroshare/rsconfig.h"
|
|
#include "retroshare/rsbanlist.h"
|
|
|
|
/* Network setup States */
|
|
|
|
constexpr uint32_t RS_NET_NEEDS_RESET = 0x0000;
|
|
constexpr uint32_t RS_NET_UNKNOWN = 0x0001;
|
|
constexpr uint32_t RS_NET_UPNP_INIT = 0x0002;
|
|
constexpr uint32_t RS_NET_UPNP_SETUP = 0x0003;
|
|
constexpr uint32_t RS_NET_EXT_SETUP = 0x0004;
|
|
constexpr uint32_t RS_NET_DONE = 0x0005;
|
|
constexpr uint32_t RS_NET_LOOPBACK = 0x0006;
|
|
//constexpr uint32_t RS_NET_DOWN = 0x0007;
|
|
constexpr uint32_t RS_NET_SHUTDOWN = 0x00FF; //Highest value to not restart UPnP nor ExtAddrFinder
|
|
|
|
/* Stun modes (TODO) */
|
|
//const uint32_t RS_STUN_DHT = 0x0001;
|
|
//const uint32_t RS_STUN_DONE = 0x0002;
|
|
//const uint32_t RS_STUN_LIST_MIN = 100;
|
|
//const uint32_t RS_STUN_FOUND_MIN = 10;
|
|
|
|
const uint32_t MAX_UPNP_INIT = 60; /* seconds UPnP timeout */
|
|
const uint32_t MAX_UPNP_COMPLETE = 600; /* 10 min... seems to take a while */
|
|
//const uint32_t MAX_NETWORK_INIT = 70; /* timeout before network reset */
|
|
|
|
//const uint32_t MIN_TIME_BETWEEN_NET_RESET = 5;
|
|
|
|
const uint32_t MIN_TIME_EXT_FINDER_UPDATE = 300; /* 5min to check if external IP is changed */
|
|
|
|
/****
|
|
* #define NETMGR_DEBUG 1
|
|
* #define NETMGR_DEBUG_RESET 1
|
|
* #define NETMGR_DEBUG_TICK 1
|
|
* #define NETMGR_DEBUG_STATEBOX 1
|
|
***/
|
|
// #define NETMGR_DEBUG 1
|
|
// #define NETMGR_DEBUG_RESET 1
|
|
// #define NETMGR_DEBUG_TICK 1
|
|
// #define NETMGR_DEBUG_STATEBOX 1
|
|
|
|
pqiNetStatus::pqiNetStatus() :
|
|
mExtAddrOk(false), mExtAddrStableOk(false), mUpnpOk(false), mDhtOk(false),
|
|
mDhtNetworkSize(0), mDhtRsNetworkSize(0), mResetReq(false)
|
|
{
|
|
sockaddr_storage_clear(mLocalAddr);
|
|
sockaddr_storage_clear(mExtAddr);
|
|
}
|
|
|
|
|
|
|
|
void pqiNetStatus::print(std::ostream &out)
|
|
{
|
|
out << "pqiNetStatus: ";
|
|
out << " mExtAddrOk: " << mExtAddrOk;
|
|
out << " mExtAddrStableOk: " << mExtAddrStableOk;
|
|
out << std::endl;
|
|
out << " mUpnpOk: " << mUpnpOk;
|
|
out << " mDhtOk: " << mDhtOk;
|
|
out << " mResetReq: " << mResetReq;
|
|
out << std::endl;
|
|
out << "mDhtNetworkSize: " << mDhtNetworkSize << " mDhtRsNetworkSize: " << mDhtRsNetworkSize;
|
|
out << std::endl;
|
|
out << "mLocalAddr: " << sockaddr_storage_tostring(mLocalAddr) << " ";
|
|
out << "mExtAddr: " << sockaddr_storage_tostring(mExtAddr) << " ";
|
|
out << std::endl;
|
|
}
|
|
|
|
|
|
p3NetMgrIMPL::p3NetMgrIMPL()
|
|
: mPeerMgr(nullptr), mLinkMgr(nullptr)
|
|
, mNetMtx("p3NetMgr"), mNetMode(RS_NET_MODE_UDP), mVsDisc(RS_VS_DISC_FULL), mVsDht(RS_VS_DHT_FULL)// default to full.
|
|
, mNetInitTS(0), mNetStatus(RS_NET_UNKNOWN), mStatusChanged(false)
|
|
, mUseExtAddrFinder(true), mNetExtAddrFinderTs(0), mDoNotNetCheckUntilTs(0)
|
|
{
|
|
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
mExtAddrFinder = new ExtAddrFinder();
|
|
|
|
mNetFlags = pqiNetStatus();
|
|
mOldNetFlags = pqiNetStatus();
|
|
|
|
mOldNatType = RsNatTypeMode::UNKNOWN;
|
|
mOldNatHole = RsNatHoleMode::UNKNOWN;
|
|
sockaddr_storage_clear(mLocalAddr);
|
|
sockaddr_storage_clear(mExtAddr);
|
|
|
|
// force to IPv4 for the moment.
|
|
mLocalAddr.ss_family = AF_INET;
|
|
mExtAddr.ss_family = AF_INET;
|
|
|
|
}
|
|
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgr() Startup" << std::endl;
|
|
#endif
|
|
|
|
rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr() Startup, resetting network");
|
|
netReset();
|
|
|
|
return;
|
|
}
|
|
|
|
void p3NetMgrIMPL::setManagers(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr)
|
|
{
|
|
mPeerMgr = peerMgr;
|
|
mLinkMgr = linkMgr;
|
|
}
|
|
|
|
#ifdef RS_USE_DHT_STUNNER
|
|
void p3NetMgrIMPL::setAddrAssist(pqiAddrAssist *dhtStun, pqiAddrAssist *proxyStun)
|
|
{
|
|
mDhtStunner = dhtStun;
|
|
mProxyStunner = proxyStun;
|
|
}
|
|
#endif // RS_USE_DHT_STUNNER
|
|
|
|
|
|
/***** Framework / initial implementation for a connection manager.
|
|
*
|
|
* This needs a state machine for Initialisation.
|
|
*
|
|
* Network state:
|
|
* RS_NET_UNKNOWN
|
|
* RS_NET_EXT_UNKNOWN * forwarded port (but Unknown Ext IP) *
|
|
* RS_NET_EXT_KNOWN * forwarded port with known IP/Port. *
|
|
*
|
|
* RS_NET_UPNP_CHECK * checking for UPnP *
|
|
* RS_NET_UPNP_KNOWN * confirmed UPnP ext Ip/port *
|
|
*
|
|
* RS_NET_UDP_UNKNOWN * not Ext/UPnP - to determine Ext IP/Port *
|
|
* RS_NET_UDP_KNOWN * have Stunned for Ext Addr *
|
|
*
|
|
* Transitions:
|
|
*
|
|
* RS_NET_UNKNOWN -(config)-> RS_NET_EXT_UNKNOWN
|
|
* RS_NET_UNKNOWN -(config)-> RS_NET_UPNP_UNKNOWN
|
|
* RS_NET_UNKNOWN -(config)-> RS_NET_UDP_UNKNOWN
|
|
*
|
|
* RS_NET_EXT_UNKNOWN -(DHT(ip)/Stun)-> RS_NET_EXT_KNOWN
|
|
*
|
|
* RS_NET_UPNP_UNKNOWN -(Upnp)-> RS_NET_UPNP_KNOWN
|
|
* RS_NET_UPNP_UNKNOWN -(timout/Upnp)-> RS_NET_UDP_UNKNOWN
|
|
*
|
|
* RS_NET_UDP_UNKNOWN -(stun)-> RS_NET_UDP_KNOWN
|
|
*
|
|
*
|
|
* STUN state:
|
|
* RS_STUN_INIT * done nothing *
|
|
* RS_STUN_DHT * looking up peers *
|
|
* RS_STUN_DONE * found active peer and stunned *
|
|
*
|
|
*
|
|
* Steps.
|
|
*******************************************************************
|
|
* (1) Startup.
|
|
* - UDP port setup.
|
|
* - DHT setup.
|
|
* - Get Stun Keys -> add to DHT.
|
|
* - Feedback from DHT -> ask UDP to stun.
|
|
*
|
|
* (1) determine Network mode.
|
|
* If external Port.... Done:
|
|
* (2)
|
|
*******************************************************************
|
|
* Stable operation:
|
|
* (1) tick and check peers.
|
|
* (2) handle callback.
|
|
* (3) notify of new/failed connections.
|
|
*
|
|
*
|
|
*/
|
|
|
|
/* Called to reseet the whole network stack. this call is
|
|
* triggered by udp stun address tracking.
|
|
*
|
|
* must:
|
|
* - reset UPnP and DHT.
|
|
* -
|
|
*/
|
|
|
|
void p3NetMgrIMPL::netReset()
|
|
{
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netReset() Called" << std::endl;
|
|
#endif
|
|
rslog(RSL_ALERT, p3netmgrzone, "p3NetMgr::netReset() Called");
|
|
|
|
shutdown(); /* blocking shutdown call */
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
mNetStatus = RS_NET_UNKNOWN;
|
|
}
|
|
|
|
// Will initiate a new call for determining the external ip.
|
|
if (mUseExtAddrFinder)
|
|
{
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netReset() restarting AddrFinder" << std::endl;
|
|
#endif
|
|
mExtAddrFinder->reset(true) ;
|
|
}
|
|
else
|
|
{
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netReset() ExtAddrFinder Disabled" << std::endl;
|
|
#endif
|
|
}
|
|
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netReset() resetting NetStatus" << std::endl;
|
|
#endif
|
|
|
|
/* reset tcp network - if necessary */
|
|
{
|
|
/* NOTE: nNetListeners should be protected via the Mutex.
|
|
* HOWEVER, as we NEVER change this list - once its setup
|
|
* we can get away without it - and assume its constant.
|
|
*
|
|
* NB: (*it)->reset_listener must be out of the mutex,
|
|
* as it calls back to p3ConnMgr.
|
|
*/
|
|
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
struct sockaddr_storage iaddr = mLocalAddr;
|
|
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netReset() resetting listeners" << std::endl;
|
|
#endif
|
|
std::list<pqiNetListener *>::const_iterator it;
|
|
for(it = mNetListeners.begin(); it != mNetListeners.end(); ++it)
|
|
{
|
|
(*it)->resetListener(iaddr);
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netReset() reset listener" << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
netStatusReset_locked();
|
|
}
|
|
|
|
updateNetStateBox_reset();
|
|
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netReset() done" << std::endl;
|
|
#endif
|
|
}
|
|
|
|
|
|
void p3NetMgrIMPL::netStatusReset_locked()
|
|
{
|
|
//std::cerr << "p3NetMgrIMPL::netStatusReset()" << std::endl;;
|
|
|
|
mNetFlags = pqiNetStatus();
|
|
}
|
|
|
|
|
|
bool p3NetMgrIMPL::shutdown() /* blocking shutdown call */
|
|
{
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::shutdown()";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
mNetStatus = RS_NET_SHUTDOWN;
|
|
mNetInitTS = time(NULL);
|
|
netStatusReset_locked();
|
|
}
|
|
netAssistFirewallShutdown();
|
|
netAssistConnectShutdown();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void p3NetMgrIMPL::netStartup()
|
|
{
|
|
/* startup stuff */
|
|
|
|
/* StunInit gets a list of peers, and asks the DHT to find them...
|
|
* This is needed for all systems so startup straight away
|
|
*/
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netStartup()" << std::endl;
|
|
#endif
|
|
|
|
netDhtInit();
|
|
|
|
/* decide which net setup mode we're going into
|
|
*/
|
|
|
|
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
mNetInitTS = time(NULL);
|
|
netStatusReset_locked();
|
|
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netStartup() resetting mNetInitTS / Status" << std::endl;
|
|
#endif
|
|
mNetMode &= ~(RS_NET_MODE_ACTUAL);
|
|
|
|
switch(mNetMode & RS_NET_MODE_TRYMODE)
|
|
{
|
|
|
|
case RS_NET_MODE_TRY_EXT: /* v similar to UDP */
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netStartup() TRY_EXT mode";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mNetMode |= RS_NET_MODE_EXT;
|
|
mNetStatus = RS_NET_EXT_SETUP;
|
|
break;
|
|
|
|
case RS_NET_MODE_TRY_UDP:
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netStartup() TRY_UDP mode";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mNetMode |= RS_NET_MODE_UDP;
|
|
mNetStatus = RS_NET_EXT_SETUP;
|
|
break;
|
|
|
|
case RS_NET_MODE_TRY_LOOPBACK:
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netStartup() TRY_LOOPBACK mode";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mNetMode |= RS_NET_MODE_HIDDEN;
|
|
mNetStatus = RS_NET_LOOPBACK;
|
|
break;
|
|
|
|
default: // Fall through.
|
|
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netStartup() UNKNOWN mode";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
case RS_NET_MODE_TRY_UPNP:
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::netStartup() TRY_UPNP mode";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
/* Force it here (could be default!) */
|
|
mNetMode |= RS_NET_MODE_TRY_UPNP;
|
|
mNetMode |= RS_NET_MODE_UDP; /* set to UDP, upgraded is UPnP is Okay */
|
|
mNetStatus = RS_NET_UPNP_INIT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void p3NetMgrIMPL::tick()
|
|
{
|
|
rstime_t now = time(nullptr);
|
|
rstime_t dontCheckNetUntil;
|
|
{ RS_STACK_MUTEX(mNetMtx); dontCheckNetUntil = mDoNotNetCheckUntilTs; }
|
|
|
|
if(now >= dontCheckNetUntil) netStatusTick();
|
|
|
|
uint32_t netStatus; { RS_STACK_MUTEX(mNetMtx); netStatus = mNetStatus; }
|
|
switch (netStatus)
|
|
{
|
|
case RS_NET_LOOPBACK:
|
|
if(dontCheckNetUntil <= now)
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx);
|
|
mDoNotNetCheckUntilTs = now + 30;
|
|
}
|
|
break;
|
|
default:
|
|
netAssistTick();
|
|
updateNetStateBox_temporal();
|
|
#ifdef RS_USE_DHT_STUNNER
|
|
if (mDhtStunner) mDhtStunner->tick();
|
|
if (mProxyStunner) mProxyStunner->tick();
|
|
#endif // RS_USE_DHT_STUNNER
|
|
break;
|
|
}
|
|
}
|
|
|
|
#define STARTUP_DELAY 5
|
|
|
|
|
|
void p3NetMgrIMPL::netStatusTick()
|
|
{
|
|
|
|
#ifdef NETMGR_DEBUG_TICK
|
|
std::cerr << "p3NetMgrIMPL::netTick()" << std::endl;
|
|
|
|
std::cerr << "p3NetMgrIMPL::netTick() mNetMode: " << std::hex << mNetMode;
|
|
std::cerr << " ACTUALMODE: " << (mNetMode & RS_NET_MODE_ACTUAL);
|
|
std::cerr << " TRYMODE: " << (mNetMode & RS_NET_MODE_TRYMODE);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
// Check whether we are stuck on loopback. This happens if RS starts when
|
|
// the computer is not yet connected to the internet. In such a case we
|
|
// periodically check for a local net address.
|
|
//
|
|
checkNetAddress() ;
|
|
|
|
uint32_t netStatus = 0;
|
|
rstime_t age = 0;
|
|
bool needExtFinderUpdate = false;
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /************** LOCK MUTEX ***************/
|
|
|
|
netStatus = mNetStatus;
|
|
age = time(NULL) - mNetInitTS;
|
|
|
|
needExtFinderUpdate = netStatus == RS_NET_DONE;
|
|
needExtFinderUpdate &= mNetExtAddrFinderTs < time(nullptr);
|
|
if(needExtFinderUpdate)
|
|
mNetExtAddrFinderTs = time(nullptr) + MIN_TIME_EXT_FINDER_UPDATE;
|
|
}
|
|
|
|
if( mUseExtAddrFinder
|
|
&& ( netStatus <= RS_NET_UPNP_SETUP
|
|
|| needExtFinderUpdate) )
|
|
{
|
|
sockaddr_storage tmpip;
|
|
sockaddr_storage_copy( mLocalAddr, tmpip); // copies local port and correctly inits the IP family
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
RS_DBG("Asking ExtAddrFinder for IP. Initializing port with ", sockaddr_storage_port(tmpip));
|
|
#endif
|
|
|
|
if(mExtAddrFinder->hasValidIPV4(tmpip))
|
|
{
|
|
if(!sockaddr_storage_same(tmpip,mExtAddr))
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
RS_DBG("Ext supplied by ExtAddrFinder. ExtAddr: ", tmpip);
|
|
#endif
|
|
setExtAddress(tmpip);
|
|
}
|
|
}
|
|
else if(mExtAddrFinder->hasValidIPV6(tmpip))
|
|
{
|
|
if(!sockaddr_storage_same(tmpip,mExtAddr))
|
|
{
|
|
//Only if no IPv4 else, reset connections on setExtAddress()
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
RS_DBG("Ext supplied by ExtAddrFinder. ExtAddr: ", tmpip);
|
|
#endif
|
|
setExtAddress(tmpip);
|
|
}
|
|
}
|
|
}
|
|
|
|
switch(netStatus)
|
|
{
|
|
case RS_NET_NEEDS_RESET:
|
|
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netTick() STATUS: NEEDS_RESET" << std::endl;
|
|
#endif
|
|
rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::netTick() RS_NET_NEEDS_RESET, resetting network");
|
|
|
|
netReset();
|
|
break;
|
|
|
|
case RS_NET_UNKNOWN:
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netTick() STATUS: UNKNOWN" << std::endl;
|
|
#endif
|
|
|
|
/* add a small delay to stop restarting straight after a RESET
|
|
* This is so can we shutdown cleanly
|
|
*/
|
|
if (age < STARTUP_DELAY)
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netTick() Delaying Startup" << std::endl;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
netStartup();
|
|
}
|
|
|
|
break;
|
|
|
|
case RS_NET_UPNP_INIT:
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netTick() STATUS: UPNP_INIT" << std::endl;
|
|
#endif
|
|
netUpnpInit();
|
|
break;
|
|
|
|
case RS_NET_UPNP_SETUP:
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netTick() STATUS: UPNP_SETUP" << std::endl;
|
|
#endif
|
|
netUpnpCheck();
|
|
break;
|
|
|
|
|
|
case RS_NET_EXT_SETUP:
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netTick() STATUS: EXT_SETUP" << std::endl;
|
|
#endif
|
|
// This could take a lot of time on some systems to get there:
|
|
// (e.g. 10 mins to get passed upnp on windows), so it would be better to call it right away, so other external address finding
|
|
// systems still have a chance to run early.
|
|
|
|
netExtCheck();
|
|
break;
|
|
|
|
case RS_NET_DONE:
|
|
#ifdef NETMGR_DEBUG_TICK
|
|
std::cerr << "p3NetMgrIMPL::netTick() STATUS: DONE" << std::endl;
|
|
#endif
|
|
|
|
break;
|
|
|
|
case RS_NET_LOOPBACK:
|
|
//don't do a shutdown because a client in a computer without local network might be usefull for debug.
|
|
//shutdown();
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netTick() STATUS: RS_NET_LOOPBACK" << std::endl;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void p3NetMgrIMPL::netDhtInit()
|
|
{
|
|
#if defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netDhtInit()" << std::endl;
|
|
#endif
|
|
|
|
uint32_t vs = 0;
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /*********** LOCKED MUTEX ************/
|
|
vs = mVsDht;
|
|
}
|
|
|
|
enableNetAssistConnect(vs != RS_VS_DHT_OFF);
|
|
}
|
|
|
|
|
|
void p3NetMgrIMPL::netUpnpInit()
|
|
{
|
|
#if defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netUpnpInit()" << std::endl;
|
|
#endif
|
|
uint16_t eport, iport;
|
|
|
|
mNetMtx.lock(); /* LOCK MUTEX */
|
|
|
|
/* get the ports from the configuration */
|
|
|
|
mNetStatus = RS_NET_UPNP_SETUP;
|
|
iport = sockaddr_storage_port(mLocalAddr);
|
|
eport = sockaddr_storage_port(mExtAddr);
|
|
if ((eport < 1000) || (eport > 30000))
|
|
{
|
|
eport = iport;
|
|
}
|
|
|
|
mNetMtx.unlock(); /* UNLOCK MUTEX */
|
|
|
|
netAssistFirewallPorts(iport, eport);
|
|
enableNetAssistFirewall(true);
|
|
}
|
|
|
|
void p3NetMgrIMPL::netUpnpCheck()
|
|
{
|
|
/* grab timestamp */
|
|
mNetMtx.lock(); /* LOCK MUTEX */
|
|
|
|
rstime_t delta = time(NULL) - mNetInitTS;
|
|
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netUpnpCheck() age: " << delta << std::endl;
|
|
#endif
|
|
|
|
mNetMtx.unlock(); /* UNLOCK MUTEX */
|
|
|
|
struct sockaddr_storage extAddr;
|
|
int upnpState = netAssistFirewallActive();
|
|
|
|
if (((upnpState == 0) && (delta > (rstime_t)MAX_UPNP_INIT)) ||
|
|
((upnpState > 0) && (delta > (rstime_t)MAX_UPNP_COMPLETE)))
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netUpnpCheck() ";
|
|
std::cerr << "Upnp Check failed." << std::endl;
|
|
#endif
|
|
/* fallback to UDP startup */
|
|
mNetMtx.lock(); /* LOCK MUTEX */
|
|
|
|
/* UPnP Failed us! */
|
|
mNetStatus = RS_NET_EXT_SETUP;
|
|
mNetFlags.mUpnpOk = false;
|
|
|
|
mNetMtx.unlock(); /* UNLOCK MUTEX */
|
|
}
|
|
else if ((upnpState > 0) && netAssistExtAddress(extAddr))
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netUpnpCheck() ";
|
|
std::cerr << "Upnp Check success state: " << upnpState << std::endl;
|
|
#endif
|
|
/* switch to UDP startup */
|
|
mNetMtx.lock(); /* LOCK MUTEX */
|
|
|
|
/* Set Net Status flags ....
|
|
* we now have external upnp address. Golden!
|
|
* don't set netOk flag until have seen some traffic.
|
|
*/
|
|
if (sockaddr_storage_isValidNet(extAddr))
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netUpnpCheck() ";
|
|
std::cerr << "UpnpAddr: " << sockaddr_storage_tostring(extAddr);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mNetFlags.mUpnpOk = true;
|
|
mNetFlags.mExtAddr = extAddr;
|
|
mNetFlags.mExtAddrOk = true;
|
|
mNetFlags.mExtAddrStableOk = true;
|
|
|
|
mNetStatus = RS_NET_EXT_SETUP;
|
|
/* Fix netMode & Clear others! */
|
|
mNetMode = RS_NET_MODE_TRY_UPNP | RS_NET_MODE_UPNP;
|
|
}
|
|
mNetMtx.unlock(); /* UNLOCK MUTEX */
|
|
}
|
|
else
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netUpnpCheck() ";
|
|
std::cerr << "Upnp Check Continues: status: " << upnpState << std::endl;
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
class ZeroInt
|
|
{
|
|
public:
|
|
ZeroInt() { n=0; }
|
|
uint32_t n ;
|
|
};
|
|
|
|
void p3NetMgrIMPL::netExtCheck()
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netExtCheck()" << std::endl;
|
|
#endif
|
|
bool netSetupDone = false;
|
|
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx);
|
|
|
|
bool isStable = false;
|
|
sockaddr_storage tmpip;
|
|
|
|
std::map<sockaddr_storage,ZeroInt> address_votes;
|
|
|
|
/* check for External Address */
|
|
/* in order of importance */
|
|
/* (1) UPnP -> which handles itself */
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Not Ok" << std::endl;
|
|
#endif
|
|
/* net Assist */
|
|
if ( netAssistExtAddress(tmpip) &&
|
|
sockaddr_storage_isValidNet(tmpip) &&
|
|
sockaddr_storage_ipv6_to_ipv4(tmpip) )
|
|
{
|
|
if( !rsBanList ||
|
|
rsBanList->isAddressAccepted(
|
|
tmpip, RSBANLIST_CHECKING_FLAGS_BLACKLIST ) )
|
|
{
|
|
// must be stable???
|
|
isStable = true;
|
|
mNetFlags.mExtAddrOk = true;
|
|
mNetFlags.mExtAddrStableOk = isStable;
|
|
address_votes[tmpip].n++ ;
|
|
std::cerr << __PRETTY_FUNCTION__ << " NetAssistAddress "
|
|
<< " reported external address "
|
|
<< sockaddr_storage_iptostring(tmpip)
|
|
<< std::endl;
|
|
}
|
|
else
|
|
std::cerr << "(SS) netAssisExternalAddress returned banned "
|
|
<< "own IP " << sockaddr_storage_iptostring(tmpip)
|
|
<< " (banned). Rejecting." << std::endl;
|
|
}
|
|
}
|
|
|
|
/* ask ExtAddrFinder */
|
|
{
|
|
/* ExtAddrFinder */
|
|
if (mUseExtAddrFinder)
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
RS_DBG("checking ExtAddrFinder");
|
|
#endif
|
|
sockaddr_storage tmpip;
|
|
sockaddr_storage_copy( mLocalAddr, tmpip); // copies local port and correctly inits the IP family
|
|
|
|
// Test for IPv4 first to be compatible with older versions.
|
|
if (mExtAddrFinder->hasValidIPV4(tmpip))
|
|
{
|
|
sockaddr_storage_setport(tmpip, guessNewExtPort());
|
|
|
|
mNetFlags.mExtAddrOk = true;
|
|
|
|
address_votes[tmpip].n++ ;
|
|
|
|
/* XXX HACK TO FIX drbob: ALLOWING
|
|
* ExtAddrFinder -> ExtAddrStableOk = true
|
|
* (which it is not normally) */
|
|
mNetFlags.mExtAddrStableOk = true;
|
|
|
|
RS_DBG("Reported external IPv4 address ", sockaddr_storage_iptostring(tmpip));
|
|
}
|
|
else if (mExtAddrFinder->hasValidIPV6(tmpip))
|
|
{
|
|
sockaddr_storage_setport(tmpip, guessNewExtPort());
|
|
|
|
mNetFlags.mExtAddrOk = true;
|
|
|
|
address_votes[tmpip].n++ ;
|
|
|
|
/* XXX HACK TO FIX drbob: ALLOWING
|
|
* ExtAddrFinder -> ExtAddrStableOk = true
|
|
* (which it is not normally) */
|
|
mNetFlags.mExtAddrStableOk = true;
|
|
|
|
RS_DBG("Reported external IPv6 address ", sockaddr_storage_iptostring(tmpip));
|
|
}
|
|
}
|
|
}
|
|
|
|
/* also ask peer mgr. */
|
|
if (mPeerMgr)
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netExtCheck() checking mPeerMgr" << std::endl;
|
|
#endif
|
|
uint8_t isstable; // unused
|
|
sockaddr_storage tmpaddr;
|
|
|
|
if ( mPeerMgr->getExtAddressReportedByFriends(tmpaddr, isstable) && sockaddr_storage_ipv6_to_ipv4(tmpaddr) )
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netExtCheck() Ext supplied by friends" << std::endl;
|
|
#endif
|
|
sockaddr_storage_setport(tmpaddr, guessNewExtPort());
|
|
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netExtCheck() ";
|
|
std::cerr << "ExtAddr: " << sockaddr_storage_tostring(tmpip);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
mNetFlags.mExtAddrOk = true;
|
|
mNetFlags.mExtAddrStableOk = isstable;
|
|
|
|
address_votes[tmpaddr].n++;
|
|
|
|
std::cerr << __PRETTY_FUNCTION__ << " PeerMgr reported external"
|
|
<< " address "
|
|
<< sockaddr_storage_iptostring(tmpaddr) << std::endl;
|
|
}
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
else
|
|
std::cerr << " No reliable address returned." << std::endl;
|
|
#endif
|
|
}
|
|
|
|
#ifdef ALLOW_DHT_STUNNER
|
|
// (cyril) I disabled this because it's pretty dangerous. The DHT can report a wrong address quite easily
|
|
// if the other DHT peers are not collaborating.
|
|
// (sehraf) For the record: The udp stunner uses multiple (as for now: two) peers to ensure that the IP recieved is the correct one, see UdpStunner::locked_checkExternalAddress()
|
|
// Nevertheless this stays a more risky method to determine the external ip address.
|
|
|
|
/* lastly ask the DhtStunner as fallback */
|
|
if (address_votes.empty()) {
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Not Ok, Checking DhtStunner" << std::endl;
|
|
#endif
|
|
uint8_t isstable = 0;
|
|
struct sockaddr_storage tmpaddr;
|
|
sockaddr_storage_clear(tmpaddr);
|
|
|
|
if (mDhtStunner)
|
|
{
|
|
/* input network bits */
|
|
if (mDhtStunner->getExternalAddr(tmpaddr, isstable))
|
|
{
|
|
if((rsBanList == NULL) || rsBanList->isAddressAccepted(tmpaddr,RSBANLIST_CHECKING_FLAGS_BLACKLIST))
|
|
{
|
|
// must be stable???
|
|
isStable = (isstable == 1);
|
|
//mNetFlags.mExtAddr = tmpaddr;
|
|
mNetFlags.mExtAddrOk = true;
|
|
mNetFlags.mExtAddrStableOk = isStable;
|
|
|
|
address_votes[tmpaddr].n++ ;
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::netExtCheck() From DhtStunner: ";
|
|
std::cerr << sockaddr_storage_tostring(tmpaddr);
|
|
std::cerr << " Stable: " << (uint32_t) isstable;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
else
|
|
std::cerr << "(SS) DHTStunner returned wrong own IP " << sockaddr_storage_iptostring(tmpaddr) << " (banned). Rejecting." << std::endl;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* any other sources ??? */
|
|
|
|
/* finalise address */
|
|
if (mNetFlags.mExtAddrOk)
|
|
{
|
|
// look at votes.
|
|
|
|
std::cerr << "Figuring out ext addr from voting:" << std::endl;
|
|
uint32_t admax = 0 ;
|
|
|
|
for(std::map<sockaddr_storage,ZeroInt>::const_iterator it(address_votes.begin());it!=address_votes.end();++it)
|
|
{
|
|
std::cerr << " Vote: " << sockaddr_storage_iptostring(it->first) << " : " << it->second.n << " votes." ;
|
|
|
|
if(it->second.n > admax)
|
|
{
|
|
mNetFlags.mExtAddr = it->first ;
|
|
admax = it->second.n ;
|
|
|
|
std::cerr << " Kept!" << std::endl;
|
|
}
|
|
else
|
|
std::cerr << " Discarded." << std::endl;
|
|
}
|
|
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netExtCheck() ";
|
|
std::cerr << "ExtAddr: " << sockaddr_storage_tostring(mNetFlags.mExtAddr);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
//update ip address list
|
|
mExtAddr = mNetFlags.mExtAddr;
|
|
|
|
mNetStatus = RS_NET_DONE;
|
|
netSetupDone = true;
|
|
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Ok: RS_NET_DONE" << std::endl;
|
|
#endif
|
|
|
|
|
|
|
|
if (!mNetFlags.mExtAddrStableOk)
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netUdpCheck() UDP Unstable :( ";
|
|
std::cerr << std::endl;
|
|
std::cerr << "p3NetMgrIMPL::netUdpCheck() We are unreachable";
|
|
std::cerr << std::endl;
|
|
std::cerr << "netMode => RS_NET_MODE_UNREACHABLE";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
// Due to the new UDP connections - we can still connect some of the time!
|
|
// So limit warning!
|
|
|
|
//mNetMode &= ~(RS_NET_MODE_ACTUAL);
|
|
//mNetMode |= RS_NET_MODE_UNREACHABLE;
|
|
|
|
/* send a system warning message */
|
|
//pqiNotify *notify = getPqiNotify();
|
|
//if (notify)
|
|
{
|
|
//std::string title =
|
|
// "Warning: Bad Firewall Configuration";
|
|
|
|
std::string msg;
|
|
msg += " **** WARNING **** \n";
|
|
msg += "Retroshare has detected that you are behind";
|
|
msg += " a restrictive Firewall\n";
|
|
msg += "\n";
|
|
msg += "You will have limited connectivity to other firewalled peers\n";
|
|
msg += "\n";
|
|
msg += "You can fix this by:\n";
|
|
msg += " (1) opening an External Port\n";
|
|
msg += " (2) enabling UPnP, or\n";
|
|
msg += " (3) get a new (approved) Firewall/Router\n";
|
|
|
|
//notify->AddSysMessage(0, RS_SYS_WARNING, title, msg);
|
|
|
|
std::cerr << msg << std::endl;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mNetFlags.mExtAddrOk)
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netExtCheck() setting netAssistSetAddress()" << std::endl;
|
|
#endif
|
|
netAssistSetAddress(mNetFlags.mLocalAddr, mNetFlags.mExtAddr, mNetMode);
|
|
}
|
|
|
|
/* flag unreachables! */
|
|
if ((mNetFlags.mExtAddrOk) && (!mNetFlags.mExtAddrStableOk))
|
|
{
|
|
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
|
|
std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Unstable - Unreachable Check" << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (netSetupDone)
|
|
{
|
|
RS_DBG("netSetupDone");
|
|
|
|
/* Setup NetStateBox with this info */
|
|
updateNetStateBox_startup();
|
|
|
|
/* update PeerMgr with correct info */
|
|
if (mPeerMgr)
|
|
{
|
|
mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr);
|
|
}
|
|
|
|
/* inform DHT about our external IPV4 address, it doesn't support IPv6 for now.*/
|
|
if(sockaddr_storage_ipv6_to_ipv4(mExtAddr))
|
|
{
|
|
RsPeerId fakeId;
|
|
netAssistKnownPeer(fakeId, mExtAddr, NETASSIST_KNOWN_PEER_SELF | NETASSIST_KNOWN_PEER_ONLINE);
|
|
}
|
|
|
|
RS_INFO("Network Setup Complete");
|
|
}
|
|
}
|
|
|
|
/**********************************************************************************************
|
|
************************************** Interfaces *****************************************
|
|
**********************************************************************************************/
|
|
|
|
bool p3NetMgrIMPL::checkNetAddress()
|
|
{
|
|
bool addrChanged = false;
|
|
bool validAddr = false;
|
|
bool needOwnAddrUpdate = false;
|
|
|
|
sockaddr_storage prefAddr;
|
|
sockaddr_storage oldAddr;
|
|
|
|
if (mNetMode & RS_NET_MODE_TRY_LOOPBACK)
|
|
{
|
|
RsInfo() << __PRETTY_FUNCTION__ <<" network mode set to LOOPBACK,"
|
|
<< " forcing address to 127.0.0.1" << std::endl;
|
|
|
|
sockaddr_storage_ipv4_aton(prefAddr, "127.0.0.1");
|
|
validAddr = true;
|
|
}
|
|
else
|
|
{
|
|
/* TODO: Sat Oct 24 15:51:24 CEST 2015 The fact of having just one local
|
|
* address is a flawed assumption, this should be redesigned as soon as
|
|
* possible. It will require complete reenginering of the network layer
|
|
* code. */
|
|
|
|
/* For retro-compatibility strictly accept only IPv4 addresses here,
|
|
* IPv6 addresses are handled in a retro-compatible manner in
|
|
* p3PeerMgrIMPL::UpdateOwnAddress */
|
|
std::vector<sockaddr_storage> addrs;
|
|
if (getLocalAddresses(addrs))
|
|
{
|
|
for (auto it = addrs.begin(); it != addrs.end(); ++it)
|
|
{
|
|
sockaddr_storage& addr(*it);
|
|
if( sockaddr_storage_isValidNet(addr) &&
|
|
!sockaddr_storage_isLoopbackNet(addr) &&
|
|
!sockaddr_storage_isLinkLocalNet(addr) &&
|
|
sockaddr_storage_ipv6_to_ipv4(addr) )
|
|
{
|
|
prefAddr = addr;
|
|
validAddr = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* If no satisfactory local address has been found yet relax and
|
|
* accept also link local addresses */
|
|
if(!validAddr) for (auto it = addrs.begin(); it!=addrs.end(); ++it)
|
|
{
|
|
sockaddr_storage& addr(*it);
|
|
if( sockaddr_storage_isValidNet(addr) &&
|
|
!sockaddr_storage_isLoopbackNet(addr) &&
|
|
sockaddr_storage_ipv6_to_ipv4(addr) )
|
|
{
|
|
prefAddr = addr;
|
|
validAddr = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* If no satisfactory local address has been found yet relax and
|
|
* accept also loopback addresses */
|
|
if(!validAddr) for (auto it = addrs.begin(); it!=addrs.end(); ++it)
|
|
{
|
|
sockaddr_storage& addr(*it);
|
|
if( sockaddr_storage_isValidNet(addr) &&
|
|
sockaddr_storage_ipv6_to_ipv4(addr) )
|
|
{
|
|
prefAddr = addr;
|
|
validAddr = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!validAddr)
|
|
{
|
|
RS_ERR("no valid local network address found. Report to developers.");
|
|
print_stacktrace();
|
|
|
|
return false;
|
|
}
|
|
|
|
/* check addresses */
|
|
{ RS_STACK_MUTEX(mNetMtx);
|
|
|
|
sockaddr_storage_copy(mLocalAddr, oldAddr);
|
|
addrChanged = !sockaddr_storage_sameip(prefAddr, mLocalAddr);
|
|
|
|
// update address.
|
|
sockaddr_storage_copyip(mLocalAddr, prefAddr);
|
|
sockaddr_storage_copy(mLocalAddr, mNetFlags.mLocalAddr);
|
|
|
|
if(sockaddr_storage_isLoopbackNet(mLocalAddr))
|
|
mNetStatus = RS_NET_LOOPBACK;
|
|
|
|
// Check if local port is valid, reset it if not
|
|
if (!sockaddr_storage_port(mLocalAddr))
|
|
{
|
|
/* Using same port as external may make some NAT happier */
|
|
uint16_t port = sockaddr_storage_port(mExtAddr);
|
|
|
|
/* Avoid to automatically set a local port to a reserved one < 1024
|
|
* that needs special permissions or root access.
|
|
* This do not impede the user to set a reserved port manually,
|
|
* which make sense in some cases. */
|
|
|
|
std::cerr << __PRETTY_FUNCTION__ << " local port is 0. Ext port is " << port ;
|
|
|
|
while (port < 1025)
|
|
port = static_cast<uint16_t>(RsRandom::random_u32());
|
|
|
|
std::cerr << " new ext port is " << port << ": using these for local/ext ports" << std::endl;
|
|
|
|
sockaddr_storage_setport(mLocalAddr, port);
|
|
sockaddr_storage_setport(mExtAddr, port); // this accounts for when the port was updated
|
|
addrChanged = true;
|
|
}
|
|
|
|
} // RS_STACK_MUTEX(mNetMtx);
|
|
|
|
if (addrChanged)
|
|
{
|
|
RsInfo() << __PRETTY_FUNCTION__ << " local address changed, resetting network." << std::endl;
|
|
|
|
if(rsEvents)
|
|
{
|
|
auto ev = std::make_shared<RsNetworkEvent>();
|
|
ev->mNetworkEventCode = RsNetworkEventCode::LOCAL_IP_UPDATED;
|
|
ev->mIPAddress = sockaddr_storage_iptostring(mLocalAddr);
|
|
rsEvents->postEvent(ev);
|
|
}
|
|
|
|
needOwnAddrUpdate = true;
|
|
|
|
netReset();
|
|
}
|
|
|
|
if (mPeerMgr)
|
|
{
|
|
// Retrieve last known IP, if none, update own addresse to get current.
|
|
peerState ps;
|
|
mPeerMgr->getOwnNetStatus(ps);
|
|
needOwnAddrUpdate |= ps.ipAddrs.mLocal.mAddrs.empty();
|
|
needOwnAddrUpdate |= ps.ipAddrs.mExt.mAddrs.empty();
|
|
if (needOwnAddrUpdate)
|
|
{
|
|
mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**********************************************************************************************
|
|
************************************** Interfaces *****************************************
|
|
**********************************************************************************************/
|
|
|
|
/* to allow resets of network stuff */
|
|
void p3NetMgrIMPL::addNetListener(pqiNetListener *listener)
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
mNetListeners.push_back(listener);
|
|
}
|
|
|
|
|
|
|
|
bool p3NetMgrIMPL::setLocalAddress(const struct sockaddr_storage &addr)
|
|
{
|
|
bool changed = false;
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
if (!sockaddr_storage_same(mLocalAddr, addr))
|
|
{
|
|
changed = true;
|
|
}
|
|
|
|
mLocalAddr = addr;
|
|
mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr);
|
|
}
|
|
|
|
if (changed)
|
|
{
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::setLocalAddress() Calling NetReset" << std::endl;
|
|
#endif
|
|
rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::setLocalAddress() local address changed, resetting network");
|
|
netReset();
|
|
}
|
|
return true;
|
|
}
|
|
bool p3NetMgrIMPL::getExtAddress(struct sockaddr_storage& addr)
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
if(mNetFlags.mExtAddrOk)
|
|
{
|
|
addr = mNetFlags.mExtAddr ;
|
|
return true ;
|
|
}
|
|
else
|
|
return false ;
|
|
}
|
|
|
|
bool p3NetMgrIMPL::setExtAddress(const struct sockaddr_storage &addr)
|
|
{
|
|
bool changed = false;
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
if (!sockaddr_storage_same(mExtAddr, addr))
|
|
{
|
|
changed = true;
|
|
}
|
|
|
|
mExtAddr = addr;
|
|
mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr);
|
|
}
|
|
|
|
if (changed)
|
|
{
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::setExtAddress() Calling NetReset" << std::endl;
|
|
#endif
|
|
|
|
if(rsEvents)
|
|
{
|
|
auto ev = std::make_shared<RsNetworkEvent>();
|
|
ev->mNetworkEventCode = RsNetworkEventCode::EXTERNAL_IP_UPDATED;
|
|
ev->mIPAddress = sockaddr_storage_iptostring(addr);
|
|
rsEvents->postEvent(ev);
|
|
}
|
|
|
|
rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::setExtAddress() ext address changed, resetting network");
|
|
netReset();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool p3NetMgrIMPL::setNetworkMode(uint32_t netMode)
|
|
{
|
|
uint32_t oldNetMode;
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
/* only change TRY flags */
|
|
|
|
oldNetMode = mNetMode;
|
|
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::setNetworkMode()";
|
|
std::cerr << " Existing netMode: " << mNetMode;
|
|
std::cerr << " Input netMode: " << netMode;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mNetMode &= ~(RS_NET_MODE_TRYMODE);
|
|
|
|
switch(netMode & RS_NET_MODE_ACTUAL)
|
|
{
|
|
case RS_NET_MODE_EXT:
|
|
mNetMode |= RS_NET_MODE_TRY_EXT;
|
|
break;
|
|
case RS_NET_MODE_UPNP:
|
|
mNetMode |= RS_NET_MODE_TRY_UPNP;
|
|
break;
|
|
case RS_NET_MODE_HIDDEN:
|
|
mNetMode |= RS_NET_MODE_TRY_LOOPBACK;
|
|
break;
|
|
default:
|
|
case RS_NET_MODE_UDP:
|
|
mNetMode |= RS_NET_MODE_TRY_UDP;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if ((netMode & RS_NET_MODE_ACTUAL) != (oldNetMode & RS_NET_MODE_ACTUAL))
|
|
{
|
|
#ifdef NETMGR_DEBUG_RESET
|
|
std::cerr << "p3NetMgrIMPL::setNetworkMode() Calling NetReset" << std::endl;
|
|
#endif
|
|
rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::setNetworkMode() Net Mode changed, resetting network");
|
|
netReset();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool p3NetMgrIMPL::setVisState(uint16_t vs_disc, uint16_t vs_dht)
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
mVsDisc = vs_disc;
|
|
mVsDht = vs_dht;
|
|
|
|
/* if we've started up - then tweak Dht On/Off */
|
|
if (mNetStatus != RS_NET_UNKNOWN)
|
|
{
|
|
enableNetAssistConnect(mVsDht != RS_VS_DHT_OFF);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**********************************************************************************************
|
|
************************************** Interfaces *****************************************
|
|
**********************************************************************************************/
|
|
|
|
void p3NetMgrIMPL::addNetAssistFirewall(uint32_t id, pqiNetAssistFirewall *fwAgent)
|
|
{
|
|
mFwAgents[id] = fwAgent;
|
|
}
|
|
|
|
|
|
bool p3NetMgrIMPL::enableNetAssistFirewall(bool on)
|
|
{
|
|
std::map<uint32_t, pqiNetAssistFirewall *>::iterator it;
|
|
for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it)
|
|
{
|
|
(it->second)->enable(on);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool p3NetMgrIMPL::netAssistFirewallEnabled()
|
|
{
|
|
std::map<uint32_t, pqiNetAssistFirewall *>::iterator it;
|
|
for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it)
|
|
{
|
|
if ((it->second)->getEnabled())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool p3NetMgrIMPL::netAssistFirewallActive()
|
|
{
|
|
std::map<uint32_t, pqiNetAssistFirewall *>::iterator it;
|
|
for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it)
|
|
{
|
|
if ((it->second)->getActive())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool p3NetMgrIMPL::netAssistFirewallShutdown()
|
|
{
|
|
std::map<uint32_t, pqiNetAssistFirewall *>::iterator it;
|
|
for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it)
|
|
{
|
|
(it->second)->shutdown();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool p3NetMgrIMPL::netAssistFirewallPorts(uint16_t iport, uint16_t eport)
|
|
{
|
|
std::map<uint32_t, pqiNetAssistFirewall *>::iterator it;
|
|
for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it)
|
|
{
|
|
(it->second)->setInternalPort(iport);
|
|
(it->second)->setExternalPort(eport);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool p3NetMgrIMPL::netAssistExtAddress(struct sockaddr_storage &extAddr)
|
|
{
|
|
std::map<uint32_t, pqiNetAssistFirewall *>::iterator it;
|
|
for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it)
|
|
{
|
|
if ((it->second)->getActive())
|
|
{
|
|
if ((it->second)->getExternalAddress(extAddr))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void p3NetMgrIMPL::addNetAssistConnect(uint32_t id, pqiNetAssistConnect *dht)
|
|
{
|
|
mDhts[id] = dht;
|
|
}
|
|
|
|
bool p3NetMgrIMPL::enableNetAssistConnect(bool on)
|
|
{
|
|
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::enableNetAssistConnect(" << on << ")";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
std::map<uint32_t, pqiNetAssistConnect *>::iterator it;
|
|
for(it = mDhts.begin(); it != mDhts.end(); ++it)
|
|
{
|
|
(it->second)->enable(on);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool p3NetMgrIMPL::netAssistConnectEnabled()
|
|
{
|
|
std::map<uint32_t, pqiNetAssistConnect *>::iterator it;
|
|
for(it = mDhts.begin(); it != mDhts.end(); ++it)
|
|
{
|
|
if ((it->second)->getEnabled())
|
|
{
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::netAssistConnectEnabled() YES";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::netAssistConnectEnabled() NO";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
bool p3NetMgrIMPL::netAssistConnectActive()
|
|
{
|
|
std::map<uint32_t, pqiNetAssistConnect *>::iterator it;
|
|
for(it = mDhts.begin(); it != mDhts.end(); ++it)
|
|
{
|
|
if ((it->second)->getActive())
|
|
|
|
{
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::netAssistConnectActive() ACTIVE";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::netAssistConnectActive() INACTIVE";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
bool p3NetMgrIMPL::netAssistConnectStats(uint32_t &netsize, uint32_t &localnetsize)
|
|
{
|
|
std::map<uint32_t, pqiNetAssistConnect *>::iterator it;
|
|
for(it = mDhts.begin(); it != mDhts.end(); ++it)
|
|
{
|
|
if (((it->second)->getActive()) && ((it->second)->getNetworkStats(netsize, localnetsize)))
|
|
|
|
{
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::netAssistConnectStats(";
|
|
std::cerr << netsize << ", " << localnetsize << ")";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::netAssistConnectStats() INACTIVE";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
bool p3NetMgrIMPL::netAssistConnectShutdown()
|
|
{
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::netAssistConnectShutdown()";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
std::map<uint32_t, pqiNetAssistConnect *>::iterator it;
|
|
for(it = mDhts.begin(); it != mDhts.end(); ++it)
|
|
{
|
|
(it->second)->shutdown();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool p3NetMgrIMPL::netAssistFriend(const RsPeerId &id, bool on)
|
|
{
|
|
std::map<uint32_t, pqiNetAssistConnect *>::iterator it;
|
|
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::netAssistFriend(" << id << ", " << on << ")";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
for(it = mDhts.begin(); it != mDhts.end(); ++it)
|
|
{
|
|
if (on)
|
|
(it->second)->findPeer(id);
|
|
else
|
|
(it->second)->dropPeer(id);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool p3NetMgrIMPL::netAssistKnownPeer(const RsPeerId &id, const struct sockaddr_storage &addr, uint32_t flags)
|
|
{
|
|
std::map<uint32_t, pqiNetAssistConnect *>::iterator it;
|
|
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::netAssistKnownPeer(" << id << ")";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
for(it = mDhts.begin(); it != mDhts.end(); ++it)
|
|
{
|
|
(it->second)->addKnownPeer(id, addr, flags);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool p3NetMgrIMPL::netAssistBadPeer(const struct sockaddr_storage &addr, uint32_t reason, uint32_t flags, uint32_t age)
|
|
{
|
|
std::map<uint32_t, pqiNetAssistConnect *>::iterator it;
|
|
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::netAssistBadPeer(" << sockaddr_storage_iptostring(addr) << ")";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
for(it = mDhts.begin(); it != mDhts.end(); ++it)
|
|
{
|
|
(it->second)->addBadPeer(addr, reason, flags, age);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool p3NetMgrIMPL::netAssistAttach(bool on)
|
|
{
|
|
std::map<uint32_t, pqiNetAssistConnect *>::iterator it;
|
|
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::netAssistAttach(" << on << ")";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
for(it = mDhts.begin(); it != mDhts.end(); ++it)
|
|
{
|
|
(it->second)->setAttachMode(on);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
bool p3NetMgrIMPL::netAssistStatusUpdate(const RsPeerId &id, int state)
|
|
{
|
|
std::map<uint32_t, pqiNetAssistConnect *>::iterator it;
|
|
|
|
#ifdef NETMGR_DEBUG
|
|
std::cerr << "p3NetMgrIMPL::netAssistStatusUpdate(" << id << ", " << state << ")";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
for(it = mDhts.begin(); it != mDhts.end(); ++it)
|
|
{
|
|
(it->second)->ConnectionFeedback(id, state);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool p3NetMgrIMPL::netAssistSetAddress( const struct sockaddr_storage & /*laddr*/,
|
|
const struct sockaddr_storage & /*eaddr*/,
|
|
uint32_t /*mode*/)
|
|
{
|
|
#if 0
|
|
std::map<uint32_t, pqiNetAssistConnect *>::iterator it;
|
|
for(it = mDhts.begin(); it != mDhts.end(); ++it)
|
|
{
|
|
(it->second)->setExternalInterface(laddr, eaddr, mode);
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
void p3NetMgrIMPL::netAssistTick()
|
|
{
|
|
std::map<uint32_t, pqiNetAssistConnect *>::iterator it;
|
|
for(it = mDhts.begin(); it != mDhts.end(); ++it)
|
|
{
|
|
(it->second)->tick();
|
|
}
|
|
|
|
std::map<uint32_t, pqiNetAssistFirewall *>::iterator fit;
|
|
for(fit = mFwAgents.begin(); fit != mFwAgents.end(); ++fit)
|
|
{
|
|
(fit->second)->tick();
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
**********************************************************************
|
|
******************** Network State ***********************************
|
|
**********************************************************************
|
|
**********************************************************************/
|
|
|
|
bool p3NetMgrIMPL::getUPnPState()
|
|
{
|
|
return netAssistFirewallActive();
|
|
}
|
|
|
|
bool p3NetMgrIMPL::getUPnPEnabled()
|
|
{
|
|
return netAssistFirewallEnabled();
|
|
}
|
|
|
|
bool p3NetMgrIMPL::getDHTEnabled()
|
|
{
|
|
return netAssistConnectEnabled();
|
|
}
|
|
|
|
|
|
void p3NetMgrIMPL::getNetStatus(pqiNetStatus &status)
|
|
{
|
|
/* cannot lock local stack, then call DHT... as this can cause lock up */
|
|
/* must extract data... then update mNetFlags */
|
|
|
|
bool dhtOk = netAssistConnectActive();
|
|
uint32_t netsize = 0, rsnetsize = 0;
|
|
netAssistConnectStats(netsize, rsnetsize);
|
|
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* quick update of the stuff that can change! */
|
|
mNetFlags.mDhtOk = dhtOk;
|
|
mNetFlags.mDhtNetworkSize = netsize;
|
|
mNetFlags.mDhtRsNetworkSize = rsnetsize;
|
|
|
|
status = mNetFlags;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************************************
|
|
************************************** ExtAddrFinder *****************************************
|
|
**********************************************************************************************/
|
|
|
|
bool p3NetMgrIMPL::getIPServersEnabled()
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
return mUseExtAddrFinder;
|
|
}
|
|
|
|
void p3NetMgrIMPL::getIPServersList(std::list<std::string>& ip_servers)
|
|
{
|
|
mExtAddrFinder->getIPServersList(ip_servers);
|
|
}
|
|
|
|
void p3NetMgrIMPL::getCurrentExtIPList(std::list<std::string>& ip_list)
|
|
{
|
|
ip_list.clear();
|
|
sockaddr_storage addr;
|
|
if(mExtAddrFinder->hasValidIPV4(addr))
|
|
ip_list.push_back(sockaddr_storage_iptostring(addr));
|
|
if(mExtAddrFinder->hasValidIPV6(addr))
|
|
ip_list.push_back(sockaddr_storage_iptostring(addr));
|
|
}
|
|
|
|
void p3NetMgrIMPL::setIPServersEnabled(bool b)
|
|
{
|
|
if (mUseExtAddrFinder != b)
|
|
{
|
|
mExtAddrFinder->reset(true);
|
|
if (b)
|
|
mExtAddrFinder->start_request();
|
|
}
|
|
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
mUseExtAddrFinder = b;
|
|
}
|
|
|
|
#ifdef NETMGR_DEBUG
|
|
RS_DBG("set mUseExtAddrFinder to ", b);
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************************************
|
|
************************************** NetStateBox ******************************************
|
|
**********************************************************************************************/
|
|
|
|
RsNetState p3NetMgrIMPL::getNetStateMode()
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
return mNetStateBox.getNetStateMode();
|
|
}
|
|
|
|
RsNetworkMode p3NetMgrIMPL::getNetworkMode()
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
return mNetStateBox.getNetworkMode();
|
|
}
|
|
|
|
RsNatTypeMode p3NetMgrIMPL::getNatTypeMode()
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
return mNetStateBox.getNatTypeMode();
|
|
}
|
|
|
|
RsNatHoleMode p3NetMgrIMPL::getNatHoleMode()
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
return mNetStateBox.getNatHoleMode();
|
|
}
|
|
|
|
RsConnectModes p3NetMgrIMPL::getConnectModes()
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
return mNetStateBox.getConnectModes();
|
|
}
|
|
|
|
|
|
/* These are the regular updates from Dht / Stunners */
|
|
void p3NetMgrIMPL::updateNetStateBox_temporal()
|
|
{
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() ";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
struct sockaddr_storage tmpaddr;
|
|
sockaddr_storage_clear(tmpaddr);
|
|
|
|
#ifdef RS_USE_DHT_STUNNER
|
|
uint8_t isstable = 0;
|
|
|
|
if (mDhtStunner)
|
|
{
|
|
|
|
/* input network bits */
|
|
if (mDhtStunner->getExternalAddr(tmpaddr, isstable))
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
mNetStateBox.setAddressStunDht(tmpaddr, isstable);
|
|
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() DhtStunner: ";
|
|
std::cerr << sockaddr_storage_tostring(tmpaddr);
|
|
std::cerr << " Stable: " << (uint32_t) isstable;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
if (mProxyStunner)
|
|
{
|
|
|
|
/* input network bits */
|
|
if (mProxyStunner->getExternalAddr(tmpaddr, isstable))
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
mNetStateBox.setAddressStunProxy(tmpaddr, isstable);
|
|
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() ProxyStunner: ";
|
|
std::cerr << sockaddr_storage_tostring(tmpaddr);
|
|
std::cerr << " Stable: " << (uint32_t) isstable;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
}
|
|
}
|
|
#endif // RS_USE_DHT_STUNNER
|
|
|
|
|
|
{
|
|
bool dhtOn = netAssistConnectEnabled();
|
|
bool dhtActive = netAssistConnectActive();
|
|
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
mNetStateBox.setDhtState(dhtOn, dhtActive);
|
|
}
|
|
|
|
|
|
/* now we check if a WebIP address is required? */
|
|
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
auto netstate = mNetStateBox.getNetStateMode();
|
|
auto netMode = mNetStateBox.getNetworkMode();
|
|
auto natType = mNetStateBox.getNatTypeMode();
|
|
auto natHole = mNetStateBox.getNatHoleMode();
|
|
auto connect = mNetStateBox.getConnectModes();
|
|
#ifdef SUSPENDED
|
|
auto netstatestr = NetStateNetStateString(netstate);
|
|
auto connectstr = NetStateConnectModesString(connect);
|
|
auto natholestr = NetStateNatHoleString(natHole);
|
|
auto nattypestr = NetStateNatTypeString(natType);
|
|
auto netmodestr = NetStateNetworkModeString(netMode);
|
|
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() NetStateBox Thinking";
|
|
std::cerr << std::endl;
|
|
std::cerr << "\tNetState: " << netstatestr;
|
|
std::cerr << std::endl;
|
|
std::cerr << "\tConnectModes: " << connectstr;
|
|
std::cerr << std::endl;
|
|
std::cerr << "\tNetworkMode: " << netmodestr;
|
|
std::cerr << std::endl;
|
|
std::cerr << "\tNatHole: " << natholestr;
|
|
std::cerr << std::endl;
|
|
std::cerr << "\tNatType: " << nattypestr;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
}
|
|
#endif
|
|
|
|
updateNatSetting();
|
|
|
|
}
|
|
|
|
#define NET_STUNNER_PERIOD_FAST (-1) // default of Stunner.
|
|
#define NET_STUNNER_PERIOD_SLOW (120) // This needs to be as small Routers will allow... try 2 minutes.
|
|
// FOR TESTING ONLY.
|
|
//#define NET_STUNNER_PERIOD_SLOW (60) // 3 minutes.
|
|
|
|
void p3NetMgrIMPL::updateNatSetting()
|
|
{
|
|
bool updateRefreshRate = false;
|
|
RsNatTypeMode natType = RsNatTypeMode::UNKNOWN;
|
|
RsNatHoleMode natHole = RsNatHoleMode::UNKNOWN;
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
natType = mNetStateBox.getNatTypeMode();
|
|
natHole = mNetStateBox.getNatHoleMode();
|
|
if ((natType != mOldNatType) || (natHole != mOldNatHole))
|
|
{
|
|
mOldNatType = natType;
|
|
mOldNatHole = natHole;
|
|
updateRefreshRate = true;
|
|
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() NatType Change!";
|
|
// std::cerr << "\tNatType: " << NetStateNatTypeString(natType);
|
|
// std::cerr << "\tNatHole: "k << NetStateNatHoleString(natHole);
|
|
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// MUST also use this chance to set ATTACH flag for DHT.
|
|
if (updateRefreshRate)
|
|
{
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() Updating Refresh Rate, based on changed NatType";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
#ifdef RS_USE_DHT_STUNNER
|
|
if (mProxyStunner) {
|
|
switch(natType)
|
|
{
|
|
case RsNatTypeMode::RESTRICTED_CONE:
|
|
{
|
|
if ((natHole == RsNatHoleMode::NONE) || (natHole == RsNatHoleMode::UNKNOWN))
|
|
{
|
|
mProxyStunner->setRefreshPeriod(NET_STUNNER_PERIOD_FAST);
|
|
}
|
|
else
|
|
{
|
|
mProxyStunner->setRefreshPeriod(NET_STUNNER_PERIOD_SLOW);
|
|
}
|
|
break;
|
|
}
|
|
case RsNatTypeMode::NONE:
|
|
case RsNatTypeMode::UNKNOWN:
|
|
case RsNatTypeMode::SYMMETRIC:
|
|
case RsNatTypeMode::DETERM_SYM:
|
|
case RsNatTypeMode::FULL_CONE:
|
|
case RsNatTypeMode::OTHER:
|
|
|
|
mProxyStunner->setRefreshPeriod(NET_STUNNER_PERIOD_SLOW);
|
|
break;
|
|
}
|
|
}
|
|
#endif // RS_USE_DHT_STUNNER
|
|
|
|
/* This controls the Attach mode of the DHT...
|
|
* which effectively makes the DHT "attach" to Open Nodes.
|
|
* So that messages can get through.
|
|
* We only want to be attached - if we don't have a stable DHT port.
|
|
*/
|
|
if ((natHole == RsNatHoleMode::NONE) || (natHole == RsNatHoleMode::UNKNOWN))
|
|
{
|
|
switch(natType)
|
|
{
|
|
/* switch to attach mode if we have a bad firewall */
|
|
case RsNatTypeMode::UNKNOWN:
|
|
case RsNatTypeMode::SYMMETRIC:
|
|
case RsNatTypeMode::RESTRICTED_CONE:
|
|
case RsNatTypeMode::DETERM_SYM:
|
|
case RsNatTypeMode::OTHER:
|
|
netAssistAttach(true);
|
|
|
|
break;
|
|
/* switch off attach mode if we have a nice firewall */
|
|
case RsNatTypeMode::NONE:
|
|
case RsNatTypeMode::FULL_CONE:
|
|
netAssistAttach(false);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Switch off Firewall Mode (Attach)
|
|
netAssistAttach(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void p3NetMgrIMPL::updateNetStateBox_startup()
|
|
{
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() ";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
/* fill in the data */
|
|
struct sockaddr_storage tmpip;
|
|
|
|
/* net Assist */
|
|
if (netAssistExtAddress(tmpip))
|
|
{
|
|
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() ";
|
|
std::cerr << "Ext supplied from netAssistExternalAddress()";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
if (sockaddr_storage_isValidNet(tmpip))
|
|
{
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() ";
|
|
std::cerr << "netAssist Returned: " << sockaddr_storage_tostring(tmpip);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mNetStateBox.setAddressUPnP(true, tmpip);
|
|
}
|
|
else
|
|
{
|
|
mNetStateBox.setAddressUPnP(false, tmpip);
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() ";
|
|
std::cerr << "ERROR Bad Address supplied from netAssistExternalAddress()";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() ";
|
|
std::cerr << " netAssistExtAddress() is not active";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mNetStateBox.setAddressUPnP(false, tmpip);
|
|
}
|
|
|
|
|
|
/* ExtAddrFinder */
|
|
if (mUseExtAddrFinder)
|
|
{
|
|
tmpip = mLocalAddr;
|
|
bool extFinderOk = mExtAddrFinder->hasValidIPV4(tmpip);
|
|
|
|
if (extFinderOk)
|
|
{
|
|
sockaddr_storage_setport(tmpip, guessNewExtPort());
|
|
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() ";
|
|
std::cerr << "ExtAddrFinder Returned: " << sockaddr_storage_iptostring(tmpip);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
mNetStateBox.setAddressWebIP(true, tmpip);
|
|
}
|
|
else
|
|
{
|
|
mNetStateBox.setAddressWebIP(false, tmpip);
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() ";
|
|
std::cerr << " ExtAddrFinder hasn't found an address yet";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef NETMGR_DEBUG_STATEBOX
|
|
std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() ";
|
|
std::cerr << " ExtAddrFinder is not active";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
mNetStateBox.setAddressWebIP(false, tmpip);
|
|
}
|
|
|
|
|
|
/* finally - if the user has set Forwarded, pass it on */
|
|
if (mNetMode & RS_NET_MODE_TRY_EXT)
|
|
{
|
|
mNetStateBox.setPortForwarded(true, 0); // Port unknown for now.
|
|
}
|
|
}
|
|
}
|
|
|
|
void p3NetMgrIMPL::updateNetStateBox_reset()
|
|
{
|
|
{
|
|
RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/
|
|
|
|
mNetStateBox.reset();
|
|
|
|
mOldNatHole = RsNatHoleMode::UNKNOWN;
|
|
mOldNatType = RsNatTypeMode::UNKNOWN;
|
|
|
|
}
|
|
}
|
|
|
|
p3NetMgr::~p3NetMgr() = default;
|
|
pqiNetAssist::~pqiNetAssist() = default;
|
|
pqiNetAssistPeerShare::~pqiNetAssistPeerShare() = default;
|
|
pqiNetAssistConnect::~pqiNetAssistConnect() = default;
|