diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index 075da3581..d42f68328 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -635,6 +635,7 @@ SOURCES += util/folderiterator.cc \ util/rsdiscspace.cc \ util/rsnet.cc \ util/rsnet_ss.cc \ + util/rsdnsutils.cc \ util/extaddrfinder.cc \ util/dnsresolver.cc \ util/rsprint.cc \ diff --git a/libretroshare/src/pqi/p3netmgr.cc b/libretroshare/src/pqi/p3netmgr.cc index 32b413e7b..21e45ac16 100644 --- a/libretroshare/src/pqi/p3netmgr.cc +++ b/libretroshare/src/pqi/p3netmgr.cc @@ -47,14 +47,15 @@ struct RsLog::logInfo p3netmgrzoneInfo = {RsLog::Default, "p3netmgr"}; /* Network setup States */ -const uint32_t RS_NET_NEEDS_RESET = 0x0000; -const uint32_t RS_NET_UNKNOWN = 0x0001; -const uint32_t RS_NET_UPNP_INIT = 0x0002; -const uint32_t RS_NET_UPNP_SETUP = 0x0003; -const uint32_t RS_NET_EXT_SETUP = 0x0004; -const uint32_t RS_NET_DONE = 0x0005; -const uint32_t RS_NET_LOOPBACK = 0x0006; -//const uint32_t RS_NET_DOWN = 0x0007; +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; @@ -68,6 +69,8 @@ const uint32_t MAX_UPNP_COMPLETE = 600; /* 10 min... seems to take a while */ //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 @@ -107,19 +110,17 @@ void pqiNetStatus::print(std::ostream &out) } -p3NetMgrIMPL::p3NetMgrIMPL() : mPeerMgr(nullptr), mLinkMgr(nullptr), - mNetMtx("p3NetMgr"), mNetStatus(RS_NET_UNKNOWN), mStatusChanged(false), - mDoNotNetCheckUntilTs(0) +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) { { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetMode = RS_NET_MODE_UDP; - - mUseExtAddrFinder = true; mExtAddrFinder = new ExtAddrFinder(); - mNetInitTS = 0; mNetFlags = pqiNetStatus(); mOldNetFlags = pqiNetStatus(); @@ -133,10 +134,6 @@ p3NetMgrIMPL::p3NetMgrIMPL() : mPeerMgr(nullptr), mLinkMgr(nullptr), mLocalAddr.ss_family = AF_INET; mExtAddr.ss_family = AF_INET; - // default to full. - mVsDisc = RS_VS_DISC_FULL; - mVsDht = RS_VS_DHT_FULL; - } #ifdef NETMGR_DEBUG @@ -235,6 +232,10 @@ void p3NetMgrIMPL::netReset() 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) @@ -242,7 +243,7 @@ void p3NetMgrIMPL::netReset() #ifdef NETMGR_DEBUG_RESET std::cerr << "p3NetMgrIMPL::netReset() restarting AddrFinder" << std::endl; #endif - mExtAddrFinder->reset() ; + mExtAddrFinder->reset(true) ; } else { @@ -265,7 +266,7 @@ void p3NetMgrIMPL::netReset() * as it calls back to p3ConnMgr. */ - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ struct sockaddr_storage iaddr = mLocalAddr; @@ -283,8 +284,7 @@ void p3NetMgrIMPL::netReset() } { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStatus = RS_NET_UNKNOWN; + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ netStatusReset_locked(); } @@ -311,8 +311,8 @@ bool p3NetMgrIMPL::shutdown() /* blocking shutdown call */ std::cerr << std::endl; #endif { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStatus = RS_NET_UNKNOWN; + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ + mNetStatus = RS_NET_SHUTDOWN; mNetInitTS = time(NULL); netStatusReset_locked(); } @@ -347,7 +347,7 @@ void p3NetMgrIMPL::netStartup() */ - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetInitTS = time(NULL); netStatusReset_locked(); @@ -460,35 +460,51 @@ void p3NetMgrIMPL::netStatusTick() uint32_t netStatus = 0; rstime_t age = 0; + bool needExtFinderUpdate = false; { - RsStackMutex stack(mNetMtx); /************** LOCK MUTEX ***************/ + 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(netStatus <= RS_NET_UPNP_SETUP && mUseExtAddrFinder) - { - sockaddr_storage tmpip = mLocalAddr; // copies local port and correctly inits the IP family + 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) - std::cerr << "Asking ExtAddrFinder for IP. Initializing port with " << sockaddr_storage_port(tmpip) << std::endl; + RS_DBG("Asking ExtAddrFinder for IP. Initializing port with ", sockaddr_storage_port(tmpip)); #endif - if(mExtAddrFinder->hasValidIP(tmpip) && sockaddr_storage_ipv6_to_ipv4(tmpip) && !sockaddr_storage_same(tmpip,mExtAddr)) - { + if(mExtAddrFinder->hasValidIPV4(tmpip)) + { + if(!sockaddr_storage_same(tmpip,mExtAddr)) + { #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext supplied by ExtAddrFinder" << std::endl; + 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) - std::cerr << "p3NetMgrIMPL::netExtCheck() "; - std::cerr << "ExtAddr: " << sockaddr_storage_tostring(tmpip); - std::cerr << std::endl; + RS_DBG("Ext supplied by ExtAddrFinder. ExtAddr: ", tmpip); #endif - setExtAddress(tmpip); - } - } + setExtAddress(tmpip); + } + } + } switch(netStatus) { @@ -578,7 +594,7 @@ void p3NetMgrIMPL::netDhtInit() uint32_t vs = 0; { - RsStackMutex stack(mNetMtx); /*********** LOCKED MUTEX ************/ + RS_STACK_MUTEX(mNetMtx); /*********** LOCKED MUTEX ************/ vs = mVsDht; } @@ -745,25 +761,16 @@ void p3NetMgrIMPL::netExtCheck() if (mUseExtAddrFinder) { #if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() checking ExtAddrFinder" << std::endl; + RS_DBG("checking ExtAddrFinder"); #endif - sockaddr_storage tmpip = mLocalAddr; // copies local port and correctly inits the IP family + sockaddr_storage tmpip; + sockaddr_storage_copy( mLocalAddr, tmpip); // copies local port and correctly inits the IP family - bool extFinderOk = mExtAddrFinder->hasValidIP(tmpip); - - if (extFinderOk && sockaddr_storage_ipv6_to_ipv4(tmpip)) + // Test for IPv4 first to be compatible with older versions. + if (mExtAddrFinder->hasValidIPV4(tmpip)) { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext supplied by ExtAddrFinder" << std::endl; -#endif sockaddr_storage_setport(tmpip, 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; address_votes[tmpip].n++ ; @@ -773,10 +780,22 @@ void p3NetMgrIMPL::netExtCheck() * (which it is not normally) */ mNetFlags.mExtAddrStableOk = true; - std::cerr << __PRETTY_FUNCTION__ << " ExtAddrFinder " - << " reported external address " - << sockaddr_storage_iptostring(tmpip) - << std::endl; + 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)); } } } @@ -967,7 +986,7 @@ void p3NetMgrIMPL::netExtCheck() if (netSetupDone) { - std::cerr << "p3NetMgrIMPL::netExtCheck() netSetupDone" << std::endl; + RS_DBG("netSetupDone"); /* Setup NetStateBox with this info */ updateNetStateBox_startup(); @@ -978,12 +997,14 @@ void p3NetMgrIMPL::netExtCheck() mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); } - /* inform DHT about our external address */ - RsPeerId fakeId; - netAssistKnownPeer(fakeId, mExtAddr, NETASSIST_KNOWN_PEER_SELF | NETASSIST_KNOWN_PEER_ONLINE); + /* 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); + } - std::cerr << __PRETTY_FUNCTION__ << " Network Setup Complete" - << std::endl; + RS_INFO("Network Setup Complete"); } } @@ -994,7 +1015,8 @@ void p3NetMgrIMPL::netExtCheck() bool p3NetMgrIMPL::checkNetAddress() { bool addrChanged = false; - bool validAddr = false; + bool validAddr = false; + bool needOwnAddrUpdate = false; sockaddr_storage prefAddr; sockaddr_storage oldAddr; @@ -1067,8 +1089,7 @@ bool p3NetMgrIMPL::checkNetAddress() if (!validAddr) { - RsErr() << __PRETTY_FUNCTION__ << " no valid local network address " - <<" found. Report to developers." << std::endl; + RS_ERR("no valid local network address found. Report to developers."); print_stacktrace(); return false; @@ -1109,6 +1130,7 @@ bool p3NetMgrIMPL::checkNetAddress() sockaddr_storage_setport(mExtAddr, port); // this accounts for when the port was updated addrChanged = true; } + } // RS_STACK_MUTEX(mNetMtx); if (addrChanged) @@ -1123,11 +1145,24 @@ bool p3NetMgrIMPL::checkNetAddress() rsEvents->postEvent(ev); } - if (mPeerMgr) mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); + 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; } @@ -1139,7 +1174,7 @@ bool p3NetMgrIMPL::checkNetAddress() /* to allow resets of network stuff */ void p3NetMgrIMPL::addNetListener(pqiNetListener *listener) { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetListeners.push_back(listener); } @@ -1149,7 +1184,7 @@ bool p3NetMgrIMPL::setLocalAddress(const struct sockaddr_storage &addr) { bool changed = false; { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ if (!sockaddr_storage_same(mLocalAddr, addr)) { changed = true; @@ -1171,7 +1206,7 @@ bool p3NetMgrIMPL::setLocalAddress(const struct sockaddr_storage &addr) } bool p3NetMgrIMPL::getExtAddress(struct sockaddr_storage& addr) { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ if(mNetFlags.mExtAddrOk) { @@ -1186,7 +1221,7 @@ bool p3NetMgrIMPL::setExtAddress(const struct sockaddr_storage &addr) { bool changed = false; { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ if (!sockaddr_storage_same(mExtAddr, addr)) { changed = true; @@ -1220,7 +1255,7 @@ bool p3NetMgrIMPL::setNetworkMode(uint32_t netMode) { uint32_t oldNetMode; { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ /* only change TRY flags */ oldNetMode = mNetMode; @@ -1266,7 +1301,7 @@ bool p3NetMgrIMPL::setNetworkMode(uint32_t netMode) bool p3NetMgrIMPL::setVisState(uint16_t vs_disc, uint16_t vs_dht) { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mVsDisc = vs_disc; mVsDht = vs_dht; @@ -1628,7 +1663,7 @@ void p3NetMgrIMPL::getNetStatus(pqiNetStatus &status) uint32_t netsize = 0, rsnetsize = 0; netAssistConnectStats(netsize, rsnetsize); - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ /* quick update of the stuff that can change! */ mNetFlags.mDhtOk = dhtOk; @@ -1652,7 +1687,7 @@ void p3NetMgrIMPL::getNetStatus(pqiNetStatus &status) bool p3NetMgrIMPL::getIPServersEnabled() { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ return mUseExtAddrFinder; } @@ -1661,15 +1696,32 @@ void p3NetMgrIMPL::getIPServersList(std::list& ip_servers) mExtAddrFinder->getIPServersList(ip_servers); } +void p3NetMgrIMPL::getCurrentExtIPList(std::list& 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) { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + mExtAddrFinder->reset(true); + if (b) + mExtAddrFinder->start_request(); + } + + { + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mUseExtAddrFinder = b; } #ifdef NETMGR_DEBUG - std::cerr << "p3NetMgr: setIPServers to " << b << std::endl ; + RS_DBG("set mUseExtAddrFinder to ", b); #endif } @@ -1682,31 +1734,31 @@ void p3NetMgrIMPL::setIPServersEnabled(bool b) RsNetState p3NetMgrIMPL::getNetStateMode() { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ return mNetStateBox.getNetStateMode(); } RsNetworkMode p3NetMgrIMPL::getNetworkMode() { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ return mNetStateBox.getNetworkMode(); } RsNatTypeMode p3NetMgrIMPL::getNatTypeMode() { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ return mNetStateBox.getNatTypeMode(); } RsNatHoleMode p3NetMgrIMPL::getNatHoleMode() { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ return mNetStateBox.getNatHoleMode(); } RsConnectModes p3NetMgrIMPL::getConnectModes() { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ return mNetStateBox.getConnectModes(); } @@ -1730,7 +1782,7 @@ void p3NetMgrIMPL::updateNetStateBox_temporal() /* input network bits */ if (mDhtStunner->getExternalAddr(tmpaddr, isstable)) { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetStateBox.setAddressStunDht(tmpaddr, isstable); #ifdef NETMGR_DEBUG_STATEBOX @@ -1749,7 +1801,7 @@ void p3NetMgrIMPL::updateNetStateBox_temporal() /* input network bits */ if (mProxyStunner->getExternalAddr(tmpaddr, isstable)) { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetStateBox.setAddressStunProxy(tmpaddr, isstable); #ifdef NETMGR_DEBUG_STATEBOX @@ -1768,7 +1820,7 @@ void p3NetMgrIMPL::updateNetStateBox_temporal() bool dhtOn = netAssistConnectEnabled(); bool dhtActive = netAssistConnectActive(); - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetStateBox.setDhtState(dhtOn, dhtActive); } @@ -1777,7 +1829,7 @@ void p3NetMgrIMPL::updateNetStateBox_temporal() #ifdef NETMGR_DEBUG_STATEBOX { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ auto netstate = mNetStateBox.getNetStateMode(); auto netMode = mNetStateBox.getNetworkMode(); @@ -1823,7 +1875,7 @@ void p3NetMgrIMPL::updateNatSetting() RsNatTypeMode natType = RsNatTypeMode::UNKNOWN; RsNatHoleMode natHole = RsNatHoleMode::UNKNOWN; { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ natType = mNetStateBox.getNatTypeMode(); natHole = mNetStateBox.getNatHoleMode(); @@ -1925,7 +1977,7 @@ void p3NetMgrIMPL::updateNetStateBox_startup() std::cerr << std::endl; #endif { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ /* fill in the data */ struct sockaddr_storage tmpip; @@ -1973,8 +2025,8 @@ void p3NetMgrIMPL::updateNetStateBox_startup() /* ExtAddrFinder */ if (mUseExtAddrFinder) { - tmpip = mLocalAddr; - bool extFinderOk = mExtAddrFinder->hasValidIP(tmpip); + tmpip = mLocalAddr; + bool extFinderOk = mExtAddrFinder->hasValidIPV4(tmpip); if (extFinderOk) { @@ -2020,7 +2072,7 @@ void p3NetMgrIMPL::updateNetStateBox_startup() void p3NetMgrIMPL::updateNetStateBox_reset() { { - RsStackMutex stack(mNetMtx); /****** STACK LOCK MUTEX *******/ + RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ mNetStateBox.reset(); diff --git a/libretroshare/src/pqi/p3netmgr.h b/libretroshare/src/pqi/p3netmgr.h index a847c07b1..e7b341098 100644 --- a/libretroshare/src/pqi/p3netmgr.h +++ b/libretroshare/src/pqi/p3netmgr.h @@ -120,6 +120,7 @@ virtual bool shutdown() = 0; /* blocking shutdown call */ virtual bool getIPServersEnabled() = 0; virtual void setIPServersEnabled(bool b) = 0; virtual void getIPServersList(std::list& ip_servers) = 0; +virtual void getCurrentExtIPList(std::list& ip_list) = 0; // ONLY USED by p3face-config.cc WHICH WILL BE REMOVED. virtual void getNetStatus(pqiNetStatus &status) = 0; @@ -171,6 +172,7 @@ virtual bool shutdown(); /* blocking shutdown call */ virtual bool getIPServersEnabled(); virtual void setIPServersEnabled(bool b); virtual void getIPServersList(std::list& ip_servers); +virtual void getCurrentExtIPList(std::list& ip_list); // ONLY USED by p3face-config.cc WHICH WILL BE REMOVED. virtual void getNetStatus(pqiNetStatus &status); @@ -307,12 +309,13 @@ void netStatusReset_locked(); uint16_t mVsDisc; uint16_t mVsDht; - rstime_t mNetInitTS; + rstime_t mNetInitTS; uint32_t mNetStatus; bool mStatusChanged; - bool mUseExtAddrFinder; + bool mUseExtAddrFinder; + rstime_t mNetExtAddrFinderTs; /* network status flags (read by rsiface) */ pqiNetStatus mNetFlags; diff --git a/libretroshare/src/retroshare/rspeers.h b/libretroshare/src/retroshare/rspeers.h index 3fdbbaf17..f49ef7fc2 100644 --- a/libretroshare/src/retroshare/rspeers.h +++ b/libretroshare/src/retroshare/rspeers.h @@ -788,6 +788,7 @@ public: virtual bool setProxyServer(const uint32_t type, const std::string &addr, const uint16_t port) = 0; virtual void getIPServersList(std::list& ip_servers) = 0; + virtual void getCurrentExtIPList(std::list& ip_list) = 0; virtual void allowServerIPDetermination(bool) = 0; virtual bool resetOwnExternalAddressList() = 0; virtual bool getAllowServerIPDetermination() = 0 ; diff --git a/libretroshare/src/rsserver/p3peers.cc b/libretroshare/src/rsserver/p3peers.cc index c44877fc5..7011d7aef 100644 --- a/libretroshare/src/rsserver/p3peers.cc +++ b/libretroshare/src/rsserver/p3peers.cc @@ -373,7 +373,7 @@ bool p3Peers::getPeerDetails(const RsPeerId& id, RsPeerDetails &d) sockaddr_storage_ipv6_to_ipv4(it->mAddr); std::string toto; toto += sockaddr_storage_tostring(it->mAddr); - rs_sprintf_append(toto, " %ld sec", time(NULL) - it->mSeenTime); + rs_sprintf_append(toto, " %ld sec loc", time(NULL) - it->mSeenTime); d.ipAddressList.push_back(toto); } for(it = ps.ipAddrs.mExt.mAddrs.begin(); it != ps.ipAddrs.mExt.mAddrs.end(); ++it) @@ -381,7 +381,7 @@ bool p3Peers::getPeerDetails(const RsPeerId& id, RsPeerDetails &d) sockaddr_storage_ipv6_to_ipv4(it->mAddr); std::string toto; toto += sockaddr_storage_tostring(it->mAddr); - rs_sprintf_append(toto, " %ld sec", time(NULL) - it->mSeenTime); + rs_sprintf_append(toto, " %ld sec ext", time(NULL) - it->mSeenTime); d.ipAddressList.push_back(toto); } } @@ -859,9 +859,15 @@ void p3Peers::getIPServersList(std::list& ip_servers) { mNetMgr->getIPServersList(ip_servers) ; } +void p3Peers::getCurrentExtIPList(std::list& ip_list) +{ + mNetMgr->getCurrentExtIPList(ip_list) ; +} bool p3Peers::resetOwnExternalAddressList() { - return mPeerMgr->resetOwnExternalAddressList(); + //TODO Phenom 2021-10-30: Need to call something like mNetMgr->netReset(); + // to update this addresslist. + return mPeerMgr->resetOwnExternalAddressList(); } void p3Peers::allowServerIPDetermination(bool b) { @@ -1287,7 +1293,11 @@ bool p3Peers::getShortInvite(std::string& invite, const RsPeerId& _sslId, Retros } #else sockaddr_storage tLocal; - if(sockaddr_storage_inet_pton(tLocal, tDetails.localAddr) && sockaddr_storage_isValidNet(tLocal) && sockaddr_storage_ipv6_to_ipv4(tLocal) && tDetails.localPort ) + bool validLoc = sockaddr_storage_inet_pton(tLocal, tDetails.localAddr) + && sockaddr_storage_isValidNet(tLocal) + && tDetails.localPort; + bool isLocIpv4 = sockaddr_storage_ipv6_to_ipv4(tLocal); + if(validLoc && isLocIpv4) { uint32_t t4Addr = reinterpret_cast(tLocal).sin_addr.s_addr; @@ -1305,7 +1315,11 @@ bool p3Peers::getShortInvite(std::string& invite, const RsPeerId& _sslId, Retros } sockaddr_storage tExt; - if(sockaddr_storage_inet_pton(tExt, tDetails.extAddr) && sockaddr_storage_isValidNet(tExt) && sockaddr_storage_ipv6_to_ipv4(tExt) && tDetails.extPort ) + bool validExt = sockaddr_storage_inet_pton(tExt, tDetails.extAddr) + && sockaddr_storage_isValidNet(tExt) + && tDetails.extPort; + bool isExtIpv4 = sockaddr_storage_ipv6_to_ipv4(tExt); + if(validExt && isExtIpv4) { uint32_t t4Addr = reinterpret_cast(tExt).sin_addr.s_addr; @@ -1321,6 +1335,17 @@ bool p3Peers::getShortInvite(std::string& invite, const RsPeerId& _sslId, Retros offset += 4+2; } + else if(validExt && !isExtIpv4) + { + // External address is IPv6, save it on LOCATOR + sockaddr_storage_setport(tExt,tDetails.extPort); + std::string tLocator = sockaddr_storage_tostring(tExt); + + addPacketHeader(RsShortInviteFieldType::LOCATOR, tLocator.size(),buf,offset,buf_size); + memcpy(&buf[offset],tLocator.c_str(),tLocator.size()); + + offset += tLocator.size(); + } #endif } @@ -1595,13 +1620,31 @@ std::string p3Peers::GetRetroshareInvite( const RsPeerId& sslId, RetroshareInvit if (getPeerDetails(ssl_id, detail)) { - if(!(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) || detail.isHiddenNode) - detail.ipAddressList.clear(); + if( !(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) + || detail.isHiddenNode) + detail.ipAddressList.clear(); + + //Check if external address is IPv6, then move it to ipAddressList as RsCertificate only allow 4 numbers. + sockaddr_storage tExt; + bool validExt = sockaddr_storage_inet_pton(tExt, detail.extAddr) + && sockaddr_storage_isValidNet(tExt) + && detail.extPort; + bool isExtIpv4 = sockaddr_storage_ipv6_to_ipv4(tExt); + + if( !(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) + && !detail.isHiddenNode + && validExt && !isExtIpv4) + { + sockaddr_storage_setport(tExt,detail.extPort); + detail.ipAddressList.push_front(sockaddr_storage_tostring(tExt) + " "); // Space needed to later parse. + detail.extAddr = ""; //Clear it to not trigg error. + detail.extPort = 0; + } unsigned char *mem_block = nullptr; size_t mem_block_size = 0; - if(!AuthGPG::getAuthGPG()->exportPublicKey( RsPgpId(detail.gpg_id), mem_block, mem_block_size, false, !!(invite_flags & RetroshareInviteFlags::PGP_SIGNATURES) )) + if(!AuthGPG::getAuthGPG()->exportPublicKey( RsPgpId(detail.gpg_id), mem_block, mem_block_size, false, !!(invite_flags & RetroshareInviteFlags::PGP_SIGNATURES) )) { std::cerr << "Cannot output certificate for id \"" << detail.gpg_id << "\". Sorry." << std::endl; diff --git a/libretroshare/src/rsserver/p3peers.h b/libretroshare/src/rsserver/p3peers.h index 56f1f73e6..c2ff96d10 100644 --- a/libretroshare/src/rsserver/p3peers.h +++ b/libretroshare/src/rsserver/p3peers.h @@ -132,6 +132,7 @@ public: virtual bool isProxyAddress(const uint32_t type, const sockaddr_storage &addr); virtual void getIPServersList(std::list& ip_servers) override; + virtual void getCurrentExtIPList(std::list& ip_list) override; virtual void allowServerIPDetermination(bool) override; virtual bool getAllowServerIPDetermination() override; virtual bool resetOwnExternalAddressList() override; diff --git a/libretroshare/src/util/dnsresolver.cc b/libretroshare/src/util/dnsresolver.cc index 3b68a052e..7ce9edee6 100644 --- a/libretroshare/src/util/dnsresolver.cc +++ b/libretroshare/src/util/dnsresolver.cc @@ -41,8 +41,6 @@ const rstime_t MAX_TIME_BEFORE_RETRY = 300 ; /* seconds before retrying an ip address */ const rstime_t MAX_KEEP_DNS_ENTRY = 3600 ; /* seconds during which a DNS entry is considered valid */ -static const std::string ADDR_AGENT = "Mozilla/5.0"; - void *solveDNSEntries(void *p) { bool more_to_go = true ; diff --git a/libretroshare/src/util/extaddrfinder.cc b/libretroshare/src/util/extaddrfinder.cc index b214dc779..03b9f33a9 100644 --- a/libretroshare/src/util/extaddrfinder.cc +++ b/libretroshare/src/util/extaddrfinder.cc @@ -19,9 +19,13 @@ * along with this program. If not, see . * * * *******************************************************************************/ + +//#define EXTADDRSEARCH_DEBUG + #include "extaddrfinder.h" #include "pqi/pqinetwork.h" +#include "rsdebug.h" #include "util/rsstring.h" #include "util/rsmemory.h" @@ -38,286 +42,237 @@ #include #include "util/rstime.h" -const uint32_t MAX_IP_STORE = 300; /* seconds ip address timeout */ +#include -//#define EXTADDRSEARCH_DEBUG +const uint32_t MAX_IP_STORE = 300; /* seconds ip address timeout */ -static const std::string ADDR_AGENT = "Mozilla/5.0"; - -static std::string scan_ip(const std::string& text) +class ZeroInt { - std::set digits ; - digits.insert('0') ; digits.insert('3') ; digits.insert('6') ; - digits.insert('1') ; digits.insert('4') ; digits.insert('7') ; - digits.insert('2') ; digits.insert('5') ; digits.insert('8') ; - digits.insert('9') ; +public: + ZeroInt() : n(0) {} + uint32_t n ; +}; - for(int i=0;i<(int)text.size();++i) - { - while(i < (int)text.size() && digits.find(text[i])==digits.end()) ++i ; - - if(i>=(int)text.size()) - return "" ; - - unsigned int a,b,c,d ; - - if(sscanf(text.c_str()+i,"%u.%u.%u.%u",&a,&b,&c,&d) != 4) - continue ; - - if(a < 256 && b<256 && c<256 && d<256) - { - std::string s ; - rs_sprintf(s, "%u.%u.%u.%u", a, b, c, d) ; - return s; - } - } - return "" ; -} - -static void getPage(const std::string& server_name,std::string& page) -{ - page = "" ; - int sockfd,n=0; // socket descriptor - struct sockaddr_in serveur; // server's parameters - memset(&serveur.sin_zero, 0, sizeof(serveur.sin_zero)); - - char buf[1024]; - char request[1024]; -#ifdef EXTADDRSEARCH_DEBUG - std::cout << "ExtAddrFinder: connecting to " << server_name << std::endl ; -#endif - // socket creation - - sockfd = unix_socket(PF_INET,SOCK_STREAM,0); - if (sockfd < 0) - { - std::cerr << "ExtAddrFinder: Failed to create socket" << std::endl; - return ; - } - - serveur.sin_family = AF_INET; - - // get server's ipv4 adress - - in_addr in ; - - if(!rsGetHostByName(server_name.c_str(),in)) /* l'hôte n'existe pas */ - { - std::cerr << "ExtAddrFinder: Unknown host " << server_name << std::endl; - unix_close(sockfd); - return ; - } - serveur.sin_addr = in ; - serveur.sin_port = htons(80); - -#ifdef EXTADDRSEARCH_DEBUG - printf("Connection attempt\n"); -#endif - std::cerr << "ExtAddrFinder: resolved hostname " << server_name << " to " << rs_inet_ntoa(in) << std::endl; - - sockaddr_storage server; - sockaddr_storage_setipv4(server, &serveur); - sockaddr_storage_setport(server, 80); - if(unix_connect(sockfd, server) == -1) - { - std::cerr << "ExtAddrFinder: Connection error to " << server_name << std::endl ; - unix_close(sockfd); - return ; - } -#ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Connection established to " << server_name << std::endl ; -#endif - - // envoi - if(snprintf( request, - 1024, - "GET / HTTP/1.0\r\n" - "Host: %s:%d\r\n" - "Connection: Close\r\n" - "\r\n", - server_name.c_str(), 80) > 1020) - { - std::cerr << "ExtAddrFinder: buffer overrun. The server name \"" << server_name << "\" is too long. This is quite unexpected." << std::endl; - unix_close(sockfd); - return ; - } - - if(send(sockfd,request,strlen(request),0)== -1) - { - std::cerr << "ExtAddrFinder: Could not send request to " << server_name << std::endl ; - unix_close(sockfd); - return ; - } - // recéption - - while((n = recv(sockfd, buf, sizeof buf - 1, 0)) > 0) - { - buf[n] = '\0'; - page += std::string(buf,n) ; - } - // fermeture de la socket - - unix_close(sockfd); -#ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Got full page from " << server_name << std::endl ; -#endif -} - - -void* doExtAddrSearch(void *p) +void ExtAddrFinder::run() { std::vector res ; - ExtAddrFinder *af = (ExtAddrFinder*)p ; - - for(std::list::const_iterator it(af->_ip_servers.begin());it!=af->_ip_servers.end();++it) + for(auto& it : _ip_servers) { - std::string page ; - - getPage(*it,page) ; - std::string ip = scan_ip(page) ; - + std::string ip = ""; + rsGetHostByNameSpecDNS(it,"myip.opendns.com",ip,2); if(ip != "") res.push_back(ip) ; #ifdef EXTADDRSEARCH_DEBUG - std::cout << "ip found through " << *it << ": \"" << ip << "\"" << std::endl ; + RS_DBG("ip found through DNS ", it, ": \"", ip, "\""); #endif } if(res.empty()) { - // thread safe copy results. - // - { - RsStackMutex mtx(af->mAddrMtx) ; - - af->mFound = false ; - af->mFoundTS = time(NULL) ; - af->mSearching = false ; - } - return NULL ; + reset(); + return ; } - sort(res.begin(),res.end()) ; // eliminates outliers. + std::map addrV4_votes; + std::map addrV6_votes; + std::string all_addrV4_Found; + std::string all_addrV6_Found; - - - if(!sockaddr_storage_ipv4_aton(af->mAddr, res[res.size()/2].c_str())) + for(auto curRes : res) { - std::cerr << "ExtAddrFinder: Could not convert " << res[res.size()/2] << " into an address." << std::endl ; + sockaddr_storage addr; + sockaddr_storage_clear(addr); + bool validIP = sockaddr_storage_inet_pton(addr, curRes) + && sockaddr_storage_isValidNet(addr); + bool isIPv4 = sockaddr_storage_ipv6_to_ipv4(addr); + if( validIP && isIPv4 ) { - RsStackMutex mtx(af->mAddrMtx) ; - af->mFound = false ; - af->mFoundTS = time(NULL) ; - af->mSearching = false ; + addr.ss_family = AF_INET; + addrV4_votes[addr].n++ ; + all_addrV4_Found += sockaddr_storage_tostring(addr) + "\n"; } - return NULL ; + else if( validIP && !isIPv4) + { + addr.ss_family = AF_INET6; + addrV6_votes[addr].n++ ; + all_addrV6_Found += sockaddr_storage_tostring(addr) + "\n"; + } + else + RS_ERR("Invalid addresse reported: ", curRes) ; + } + if( (0 == addrV4_votes.size()) && (0 == addrV6_votes.size()) ) + { + RS_ERR("Could not find any external address."); + reset(); + return ; + } + + if( 1 < addrV4_votes.size() ) + RS_ERR("Multiple external IPv4 addresses reported: " + , all_addrV4_Found ) ; + + if( 1 < addrV6_votes.size() ) + RS_ERR("Multiple external IPv6 addresses reported: " + , all_addrV6_Found ) ; + { - RsStackMutex mtx(af->mAddrMtx) ; - af->mFound = true ; - af->mFoundTS = time(NULL) ; - af->mSearching = false ; + RS_STACK_MUTEX(mAddrMtx); + + mSearching = false ; + mFoundTS = time(NULL) ; + + // Only save more reported address if not only once. + uint32_t admax = 0 ; + sockaddr_storage_clear(mAddrV4); + for (auto it : addrV4_votes) + if (admax < it.second.n) + { + mAddrV4 = it.first ; + mFoundV4 = true ; + admax = it.second.n ; + } + + admax = 0 ; + sockaddr_storage_clear(mAddrV6); + for (auto it : addrV6_votes) + if (admax < it.second.n) + { + mAddrV6 = it.first ; + mFoundV6 = true ; + admax = it.second.n ; + } + } - return NULL ; + return ; } - void ExtAddrFinder::start_request() { - void *data = (void *)this; - pthread_t tid ; - - if(! pthread_create(&tid, 0, &doExtAddrSearch, data)) - pthread_detach(tid); /* so memory is reclaimed in linux */ - else - std::cerr << "(EE) Could not start ExtAddrFinder thread." << std::endl; + if (!isRunning()) + start("ExtAddrFinder"); } -bool ExtAddrFinder::hasValidIP(struct sockaddr_storage &addr) +bool ExtAddrFinder::hasValidIPV4(struct sockaddr_storage &addr) { #ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Getting ip." << std::endl ; + RS_DBG("Getting ip."); #endif { - RsStackMutex mut(mAddrMtx) ; - if(mFound) + RS_STACK_MUTEX(mAddrMtx) ; + if(mFoundV4) { #ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Has stored ip: responding with this ip." << std::endl ; + RS_DBG("Has stored ip responding with this ip:", sockaddr_storage_iptostring(mAddrV4)) ; #endif - sockaddr_storage_copyip(addr,mAddr); // just copy the IP so we dont erase the port. + sockaddr_storage_copyip(addr,mAddrV4); // just copy the IP so we dont erase the port. } } - rstime_t delta; + + testTimeOut(); + + RS_STACK_MUTEX(mAddrMtx) ; + return mFoundV4; +} + +bool ExtAddrFinder::hasValidIPV6(struct sockaddr_storage &addr) +{ +#ifdef EXTADDRSEARCH_DEBUG + RS_DBG("Getting ip."); +#endif + { - RsStackMutex mut(mAddrMtx) ; - //timeout the current ip - delta = time(NULL) - mFoundTS; + RS_STACK_MUTEX(mAddrMtx) ; + if(mFoundV6) + { +#ifdef EXTADDRSEARCH_DEBUG + RS_DBG("Has stored ip responding with this ip:", sockaddr_storage_iptostring(mAddrV6)) ; +#endif + sockaddr_storage_copyip(addr,mAddrV6); // just copy the IP so we dont erase the port. + } } - if((uint32_t)delta > MAX_IP_STORE) {//launch a research + + testTimeOut(); + + RS_STACK_MUTEX(mAddrMtx) ; + return mFoundV6; +} + +void ExtAddrFinder::testTimeOut() +{ + bool timeOut; + { + RS_STACK_MUTEX(mAddrMtx) ; + //timeout the current ip + timeOut = (mFoundTS + MAX_IP_STORE < time(NULL)); + } + if(timeOut || mFirstTime) {//launch a research if( mAddrMtx.trylock()) { if(!mSearching) { #ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: No stored ip: Initiating new search." << std::endl ; + RS_DBG("No stored ip: Initiating new search."); #endif mSearching = true ; start_request() ; } #ifdef EXTADDRSEARCH_DEBUG else - std::cerr << "ExtAddrFinder: Already searching." << std::endl ; + RS_DBG("Already searching."); #endif + mFirstTime = false; mAddrMtx.unlock(); } #ifdef EXTADDRSEARCH_DEBUG else - std::cerr << "ExtAddrFinder: (Note) Could not acquire lock. Busy." << std::endl ; + RS_DBG("(Note) Could not acquire lock. Busy."); #endif } - - RsStackMutex mut(mAddrMtx) ; - return mFound ; } -void ExtAddrFinder::reset() +void ExtAddrFinder::reset(bool firstTime /*=false*/) { - RsStackMutex mut(mAddrMtx) ; +#ifdef EXTADDRSEARCH_DEBUG + RS_DBG("firstTime=", firstTime); +#endif + RS_STACK_MUTEX(mAddrMtx) ; - mFound = false ; mSearching = false ; - mFoundTS = time(NULL) - MAX_IP_STORE; + mFoundV4 = false ; + mFoundV6 = false ; + mFirstTime = firstTime; + mFoundTS = time(nullptr); + sockaddr_storage_clear(mAddrV4); + sockaddr_storage_clear(mAddrV6); } ExtAddrFinder::~ExtAddrFinder() { #ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Deleting ExtAddrFinder." << std::endl ; + RS_DBG("Deleting ExtAddrFinder."); #endif - } ExtAddrFinder::ExtAddrFinder() : mAddrMtx("ExtAddrFinder") { #ifdef EXTADDRSEARCH_DEBUG - std::cerr << "ExtAddrFinder: Creating new ExtAddrFinder." << std::endl ; + RS_DBG("Creating new ExtAddrFinder."); #endif - RsStackMutex mut(mAddrMtx) ; + reset( true ); - mFound = false; - mSearching = false; - mFoundTS = time(NULL) - MAX_IP_STORE; - sockaddr_storage_clear(mAddr); - - _ip_servers.push_back(std::string( "checkip.dyndns.org" )) ; - _ip_servers.push_back(std::string( "www.myip.dk" )) ; - _ip_servers.push_back(std::string( "showip.net" )) ; - _ip_servers.push_back(std::string( "www.displaymyip.com")) ; +//https://unix.stackexchange.com/questions/22615/how-can-i-get-my-external-ip-address-in-a-shell-script + //Enter direct ip so local DNS cannot change it. + //DNS servers must recognize "myip.opendns.com" + _ip_servers.push_back(std::string( "208.67.222.222" )) ;//resolver1.opendns.com + _ip_servers.push_back(std::string( "208.67.220.220" )) ;//resolver2.opendns.com + _ip_servers.push_back(std::string( "208.67.222.220" )) ;//resolver3.opendns.com + _ip_servers.push_back(std::string( "208.67.220.222" )) ;//resolver4.opendns.com + _ip_servers.push_back(std::string( "2620:119:35::35" )) ;//resolver1.opendns.com + _ip_servers.push_back(std::string( "2620:119:53::53" )) ;//resolver2.opendns.com } - diff --git a/libretroshare/src/util/extaddrfinder.h b/libretroshare/src/util/extaddrfinder.h index 22a9a5689..1a2360bab 100644 --- a/libretroshare/src/util/extaddrfinder.h +++ b/libretroshare/src/util/extaddrfinder.h @@ -30,26 +30,31 @@ struct sockaddr ; -class ExtAddrFinder +class ExtAddrFinder: public RsThread { public: ExtAddrFinder() ; ~ExtAddrFinder() ; - bool hasValidIP(struct sockaddr_storage &addr) ; + bool hasValidIPV4(struct sockaddr_storage &addr) ; + bool hasValidIPV6(struct sockaddr_storage &addr) ; void getIPServersList(std::list& ip_servers) { ip_servers = _ip_servers ; } void start_request() ; - void reset() ; + void reset(bool firstTime = false) ; private: - friend void* doExtAddrSearch(void *p) ; + virtual void run(); + void testTimeOut(); - RsMutex mAddrMtx ; - rstime_t mFoundTS; - struct sockaddr_storage mAddr; - bool mFound ; - bool mSearching ; - std::list _ip_servers ; + RsMutex mAddrMtx; + bool mSearching; + bool mFoundV4; + bool mFoundV6; + bool mFirstTime; + rstime_t mFoundTS; + struct sockaddr_storage mAddrV4; + struct sockaddr_storage mAddrV6; + std::list _ip_servers; }; diff --git a/libretroshare/src/util/rsdebug.cc b/libretroshare/src/util/rsdebug.cc index ac121bca3..2bf093c27 100644 --- a/libretroshare/src/util/rsdebug.cc +++ b/libretroshare/src/util/rsdebug.cc @@ -40,6 +40,51 @@ std::error_condition rs_errno_to_condition(int errno_code) { return std::make_error_condition(static_cast(errno_code)); } +std::ostream& hex_dump(std::ostream& os, const void *buffer, + std::size_t bufsize, bool showPrintableChars /*= true*/) +{ + if (buffer == nullptr) { + return os; + } + auto oldFormat = os.flags(); + auto oldFillChar = os.fill(); + constexpr std::size_t maxline{8}; + // create a place to store text version of string + char renderString[maxline+1]; + char *rsptr{renderString}; + // convenience cast + const unsigned char *buf{reinterpret_cast(buffer)}; + + for (std::size_t linecount=maxline; bufsize; --bufsize, ++buf) { + os << std::setw(2) << std::setfill('0') << std::hex + << static_cast(*buf) << ' '; + *rsptr++ = std::isprint(*buf) ? *buf : '.'; + if (--linecount == 0) { + *rsptr++ = '\0'; // terminate string + if (showPrintableChars) { + os << " | " << renderString; + } + os << '\n'; + rsptr = renderString; + linecount = std::min(maxline, bufsize); + } + } + // emit newline if we haven't already + if (rsptr != renderString) { + if (showPrintableChars) { + for (*rsptr++ = '\0'; rsptr != &renderString[maxline+1]; ++rsptr) { + os << " "; + } + os << " | " << renderString; + } + os << '\n'; + } + + os.fill(oldFillChar); + os.flags(oldFormat); + return os; +} + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -211,3 +256,7 @@ void rslog(const RsLog::logLvl lvl, RsLog::logInfo *info, const std::string &msg lineCount++; } } +/// All the lines before are DEPRECATED!! +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// diff --git a/libretroshare/src/util/rsdebug.h b/libretroshare/src/util/rsdebug.h index e37e3070f..25d1f1969 100644 --- a/libretroshare/src/util/rsdebug.h +++ b/libretroshare/src/util/rsdebug.h @@ -210,6 +210,53 @@ struct RsNoDbg }; +//From https://codereview.stackexchange.com/a/165162 +/** + * @brief hex_dump: Send Hexadecimal Dump to stream + * @param os: Output Stream + * @param buffer: Buffer to send + * @param bufsize: Buffer's size + * @param showPrintableChars: If must send printable Char too + * @return + * basic string: + * 61 62 63 64 65 66 31 32 | abcdef12 + * 33 34 35 36 00 7a 79 78 | 3456.zyx + * 77 76 75 39 38 37 36 35 | wvu98765 + * 34 45 64 77 61 72 64 00 | 4Edward. + * + * wide string: + * 41 00 00 00 20 00 00 00 | A... ... + * 77 00 00 00 69 00 00 00 | w...i... + * 64 00 00 00 65 00 00 00 | d...e... + * 20 00 00 00 73 00 00 00 | ...s... + * 74 00 00 00 72 00 00 00 | t...r... + * 69 00 00 00 6e 00 00 00 | i...n... + * 67 00 00 00 2e 00 00 00 | g....... + * + * a double + * 49 92 24 49 92 24 09 40 | I.$I.$.@ + */ +std::ostream& hex_dump(std::ostream& os, const void *buffer, + std::size_t bufsize, bool showPrintableChars = true); + +/** + * @brief The hexDump struct + * Enable to print dump calling like that: + * const char test[] = "abcdef123456\0zyxwvu987654Edward"; + * RsDbg()< * + * * + * 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 . * + * * + *******************************************************************************/ + +//#define DEBUG_SPEC_DNS 1 + +#include "util/rsnet.h" + +#include "util/rsdebug.h" +#include "util/rsthreads.h" +#include "util/rsstring.h" + +#ifdef WINDOWS_SYS +#else +#include +#endif + +//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 +constexpr uint16_t DNSC_IN = 1; //Internet (IN) +//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 +constexpr uint16_t DNST_A = 1; //Ipv4 address +constexpr uint16_t DNST_AAAA =28; //Ipv6 address + +///Need to pack as we use sizeof them. (avoid padding) +#pragma pack(1) +//DNS header structure +struct DNS_HEADER +{ + unsigned short id; // identification number + + //Header flags https://www.bind9.net/dns-header-flags + unsigned char rd :1; //bit 07 Recursion Desired, indicates if the client means a recursive query + unsigned char tc :1; //bit 06 TrunCation, indicates that this message was truncated due to excessive length + unsigned char aa :1; //bit 05 Authoritative Answer, in a response, indicates if the DNS server is authoritative for the queried hostname + unsigned char opcode :4;//bit 01-04 The type can be QUERY (standard query, 0), IQUERY (inverse query, 1), or STATUS (server status request, 2) + unsigned char qr :1; //bit 00 Indicates if the message is a query (0) or a reply (1) + + unsigned char rcode :4; //bit 12-15 Response Code can be NOERROR (0), FORMERR (1, Format error), SERVFAIL (2), NXDOMAIN (3, Nonexistent domain), etc. + unsigned char cd :1; //bit 11 Checking Disabled [RFC 4035][RFC 6840][RFC Errata 4927] used by DNSSEC + unsigned char ad :1; //bit 10 Authentic Data [RFC 4035][RFC 6840][RFC Errata 4924] used by DNSSEC + unsigned char z :1; //bit 09 Zero, reserved for future use + unsigned char ra :1; //bit 08 Recursion Available [RFC 1035] in a response, indicates if the replying DNS server supports recursion + + unsigned short q_count; // number of question entries + unsigned short ans_count; // number of answer entries + unsigned short auth_count; // number of authority resource records entries + unsigned short add_count; // number of additional resource record entries +}; +//// OpCode text https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5 +//static const char *opcodetext[] = { "QUERY", "IQUERY", "STATUS", +// "RESERVED3", "NOTIFY", "UPDATE", +// "STATEFUL", "RESERVED7", "RESERVED8", +// "RESERVED9", "RESERVED10", "RESERVED11", +// "RESERVED12", "RESERVED13", "RESERVED14", +// "RESERVED15" }; +//// RCode text https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 +//static const char *rcodetext[] = { "NOERROR", "FORMERR", "SERVFAIL", +// "NXDOMAIN", "NOTIMP", "REFUSED", +// "YXDOMAIN", "YXRRSET", "NXRRSET", +// "NOTAUTH", "NOTZONE", "DSOTYPENI", +// "RESERVED12", "RESERVED13", "RESERVED14", +// "RESERVED15", "BADVERS", "BADKEY", +// "BADTIME", "BADMODE", "BADNAME", +// "BADALG", "BADTRUNC", "BADCOOKIE"}; + +//Constant sized fields of query structure +//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml +struct QUESTION +{ + unsigned short qtype; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 + unsigned short qclass; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 +}; + +//Constant sized fields of the resource record structure +struct RR_DATA +{ + unsigned short rtype; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 + unsigned short rclass; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 + unsigned int rttl; //Time To Live is the number of seconds left before the information expires. (32bits integer, so maximum 140 years) + unsigned short data_len;//Lenght of following data +}; +#pragma pack() + +bool rsGetHostByNameSpecDNS(const std::string& servername, const std::string& hostname, std::string& returned_addr, int timeout_s /*= -1*/) +{ +#ifdef DEBUG_SPEC_DNS + RS_DBG("servername=", servername, " hostname=", hostname); +#endif + + if (strlen(servername.c_str()) > 256) + { + RS_ERR("servername is too long > 256 chars: ", servername); + return false; + } + if (strlen(hostname.c_str()) > 256) + { + RS_ERR("hostname is too long > 256 chars: ", hostname); + return false; + } + + sockaddr_storage serverAddr; + bool validServer = sockaddr_storage_inet_pton(serverAddr, servername) + && sockaddr_storage_isValidNet(serverAddr); + bool isIPV4 = validServer && sockaddr_storage_ipv6_to_ipv4(serverAddr); + + if (!validServer) + { + in_addr in ; + if (!rsGetHostByName(servername, in)) + { + RS_ERR("servername is on an unknow format: ", servername); + return false; + } + + validServer = sockaddr_storage_inet_pton(serverAddr, rs_inet_ntoa(in)) + && sockaddr_storage_isValidNet(serverAddr); + isIPV4 = validServer && sockaddr_storage_ipv6_to_ipv4(serverAddr); + + if (!validServer) + { + RS_ERR("rsGetHostByName return bad answer: ", rs_inet_ntoa(in)); + return false; + } + } + + sockaddr_storage_setport( serverAddr, 53); + + //Set the DNS structure to standard queries + unsigned char buf[65536]; + struct DNS_HEADER* dns = (struct DNS_HEADER *)&buf; + dns->id = static_cast(htons(getpid())); //Transaction Id + //dns flags = 0x0100 Standard Query + dns->qr = 0; //Query/Response: Message is a query + dns->opcode = 0; //OpCode: Standard query + dns->aa = 0; //Authoritative: Server is not an authority for domain + dns->tc = 0; //TrunCated: Message is not truncated + dns->rd = 1; //Recursion Desired: Do query recursively + dns->ra = 0; //Recursion Available: Server cannot do recursive queries + dns->z = 0; //Z: reserved + dns->ad = 0; //Authentic Data: Answer/authority portion was not authenticated by the server + dns->cd = 0; //Checking Disabled: Unacceptable + dns->rcode = 0; //Response Code: No error + + dns->q_count = htons(1); //1 Question + dns->ans_count = 0; //0 Answer + dns->auth_count = 0; //0 Authority RRs + dns->add_count = 0; //0 Additional RRs + size_t curSendSize = sizeof(struct DNS_HEADER); + + //Point to the query server name portion + unsigned char* qname =static_cast(&buf[curSendSize]); + //First byte is Label Type: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-10 + qname[0] = 0x04; //One Label with Normal label lower 6 bits is the length of the label + memcpy(&qname[1],hostname.c_str(),strlen(hostname.c_str())); + size_t qnameSize = strlen((const char*)qname); + // Format Hostname like www.google.com to 3www6google3com + { + size_t last = qnameSize; + for(size_t i = qnameSize-1 ; i > 0 ; i--) + if(qname[i]=='.') + { + qname[i]=last-i-1; + last = i; + } + } + curSendSize += qnameSize +1; //With \0 terminator + + //Point to the query constant portion + struct QUESTION* qinfo =(struct QUESTION*)&buf[curSendSize]; + qinfo->qtype = htons(isIPV4 ? DNST_A : DNST_AAAA); //Type: A / AAAA(Host Address) + qinfo->qclass = htons(DNSC_IN); //Class: IN + curSendSize += sizeof(struct QUESTION); + +#ifdef DEBUG_SPEC_DNS + RS_DBG("Sending Packet:\n", hexDump(buf, curSendSize)); +#endif + int s = socket(serverAddr.ss_family , SOCK_DGRAM , IPPROTO_UDP); //UDP packet for DNS queries + + if (timeout_s > -1) + rs_setSockTimeout(s, true, timeout_s); + + ssize_t send_size = sendto( s, (char*)buf, curSendSize, 0 + , (struct sockaddr*)&serverAddr + , isIPV4 ? sizeof(sockaddr_in) + : sizeof(sockaddr_in6) + ); + if( send_size < 0) + { + RS_ERR("Send Failed with size = ", send_size); + return false; + } + +#ifdef DEBUG_SPEC_DNS + RS_DBG("Waiting answer..."); +#endif + //****************************************************************************************// + //--- Receive the answer ---// + //****************************************************************************************// + socklen_t sa_size = static_cast(isIPV4 ? sizeof(sockaddr_in) + : sizeof(sockaddr_in6) + ); + ssize_t rec_size=recvfrom( s,(char*)buf , 65536 , 0 + , (struct sockaddr*)&serverAddr + , &sa_size + ); + if(rec_size <= 0) + { + RS_ERR("Receive Failed"); + return false; + } +#ifdef DEBUG_SPEC_DNS + RS_DBG("Received:\n", hexDump(buf, rec_size)); +#endif + + + if (rec_size< static_cast(sizeof(struct DNS_HEADER)) ) + { + RS_ERR("Request received too small to get DNSHeader."); + return false; + } +#ifdef DEBUG_SPEC_DNS + //Point to the header portion + dns = (struct DNS_HEADER*) buf; + RS_DBG("The response contains :\n" + ,ntohs(dns->q_count) , " Questions.\n" + ,ntohs(dns->ans_count) , " Answers.\n" + ,ntohs(dns->auth_count) , " Authoritative Servers.\n" + ,ntohs(dns->add_count) , " Additional records."); +#endif + size_t curRecSize = sizeof(struct DNS_HEADER); + + + if (rec_size< static_cast(curRecSize + 1 + sizeof(struct QUESTION)) ) + { + RS_ERR("Request received too small to get Question return."); + return false; + } + //Point to the query portion + unsigned char* qnameRecv =static_cast(&buf[curRecSize]); + if (memcmp(qname,qnameRecv,qnameSize + 1 + sizeof(struct QUESTION)) ) + { + RS_ERR("Request received different from that sent."); + return false; + } + curRecSize += qnameSize + 1 + sizeof(struct QUESTION); + + if (rec_size< static_cast(curRecSize + 2) ) + { + RS_ERR("Request received too small to get Answer return."); + return false; + } + //Point to the Answer portion + unsigned char* reader = &buf[curRecSize]; + + size_t rLabelSize=0; + if((reader[0]&0xC0) == 0) + { + //Normal label lower 6 bits is the length of the label + rLabelSize=(reader[0]&~(0xC0)*256) + reader[1]; + } + else if ((reader[0]&0xC0) == 0xC0) + { + //Compressed label the lower 6 bits and the 8 bits from next octet form a pointer to the compression target. + //Don't need to read it, maybe the same as in Query + rLabelSize=0; + } + else + { + RS_ERR("Answer received with unmanaged label format."); + return false; + } + curRecSize += 2 + rLabelSize; + + if (rec_size< static_cast(curRecSize + sizeof(struct RR_DATA)) ) + { + RS_ERR("Request received too small to get Data return."); + return false; + } + //Point to the query portion + struct RR_DATA* rec_data = (struct RR_DATA *)&buf[curRecSize]; + if (rec_data->rtype!=qinfo->qtype) + { + RS_ERR("Answer's type received different from query sent."); + return false; + } + if (rec_data->rclass!=qinfo->qclass) + { + RS_ERR("Answer's class received different from query sent."); + return false; + } + curRecSize += sizeof(struct RR_DATA); + + if (rec_size< static_cast(curRecSize + ntohs(rec_data->data_len)) ) + { + RS_ERR("Request received too small to get Full Data return."); + return false; + } + + //Retrieve Address + if(ntohs(rec_data->data_len)==4) + { + if (isIPV4) + { + in_addr ipv4Add; + ipv4Add.s_addr=*(in_addr_t*)&buf[curRecSize]; +#ifdef DEBUG_SPEC_DNS + RS_DBG("Retrieve address: ", rs_inet_ntoa(ipv4Add)); +#endif + returned_addr = rs_inet_ntoa(ipv4Add); + return true; + } + } + else if(ntohs(rec_data->data_len)==16) + { + if (!isIPV4) + { + in6_addr ipv6Add; + ipv6Add =*(in6_addr*)&buf[curRecSize]; + + struct sockaddr_storage ss; + sockaddr_storage_clear(ss); + sockaddr_in6 addr_ipv6; + addr_ipv6.sin6_addr = ipv6Add; + sockaddr_storage_setipv6(ss,&addr_ipv6); + +#ifdef DEBUG_SPEC_DNS + RS_DBG("Retrieve address: ", sockaddr_storage_iptostring(ss).c_str()); +#endif + returned_addr = sockaddr_storage_iptostring(ss); + return true; + } + } + + RS_ERR("Retrieve unmanaged data size=", ntohs(rec_data->data_len)); + return false; +} diff --git a/libretroshare/src/util/rsnet.cc b/libretroshare/src/util/rsnet.cc index 1e5f79181..a0d6f7447 100644 --- a/libretroshare/src/util/rsnet.cc +++ b/libretroshare/src/util/rsnet.cc @@ -174,3 +174,17 @@ std::string rs_inet_ntoa(struct in_addr in) rs_sprintf(str, "%u.%u.%u.%u", (int) bytes[0], (int) bytes[1], (int) bytes[2], (int) bytes[3]); return str; } + +int rs_setSockTimeout( int sockfd, bool forReceive /*= true*/ + , int timeout_Sec /*= 0*/, int timeout_uSec /*= 0*/) +{ +#ifdef WINDOWS_SYS + DWORD timeout = timeout_Sec * 1000 + timeout_uSec; +#else + struct timeval timeout; + timeout.tv_sec = timeout_Sec; + timeout.tv_usec = timeout_uSec; +#endif + return setsockopt( sockfd, SOL_SOCKET, forReceive ? SO_RCVTIMEO : SO_SNDTIMEO + , (const char*)&timeout, sizeof timeout); +} diff --git a/libretroshare/src/util/rsnet.h b/libretroshare/src/util/rsnet.h index cad2c116a..33dff1c9e 100644 --- a/libretroshare/src/util/rsnet.h +++ b/libretroshare/src/util/rsnet.h @@ -84,6 +84,18 @@ bool isExternalNet(const struct in_addr *addr); // uses a re-entrant version of gethostbyname bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr) ; +/** + * @brief Get hostName address using specific DNS server. + * Using it allow to direct ask our Address to IP, so no need to have a DNS (IPv4 or IPv6). + * If we ask to a IPv6 DNS Server, it respond for our IPv6 address. + * @param servername: Address or name of DNS Server. + * @param hostname: HosteName to get IP ("myip.opendns.com" to get own). + * @param returned_addr: returned IP of hostname. + * @param timeout_s: Timeout in sec to wait server response. + * @return True in success. + */ +bool rsGetHostByNameSpecDNS(const std::string& servername, const std::string& hostname, std::string& returned_addr, int timeout_s = -1); + std::ostream& operator<<(std::ostream& o, const sockaddr_in&); std::ostream& operator<<(std::ostream& o, const sockaddr_storage&); @@ -159,4 +171,14 @@ bool sockaddr_storage_inet_ntop(const sockaddr_storage &addr, std::string &dst); int rs_setsockopt( int sockfd, int level, int optname, const uint8_t *optval, uint32_t optlen ); +/** + * @brief Set socket Timeout. + * @param sockfd: The socket to manage. + * @param forReceive: True for Receive, False for Send. + * @param timeout_Sec: Timeout second part. + * @param timeout_uSec: Timeout micro second part. + * @return 0 on success, -1 for errors. + */ +int rs_setSockTimeout( int sockfd, bool forReceive = true, int timeout_Sec = 0, int timeout_uSec = 0); + #endif /* RS_UNIVERSAL_NETWORK_HEADER */ diff --git a/libretroshare/src/util/rsnet_ss.cc b/libretroshare/src/util/rsnet_ss.cc index c084f516e..795ad6512 100644 --- a/libretroshare/src/util/rsnet_ss.cc +++ b/libretroshare/src/util/rsnet_ss.cc @@ -233,8 +233,7 @@ bool sockaddr_storage_setport(struct sockaddr_storage &addr, uint16_t port) bool sockaddr_storage_setipv4(struct sockaddr_storage &addr, const sockaddr_in *addr_ipv4) { #ifdef SS_DEBUG - std::cerr << "sockaddr_storage_setipv4()"; - std::cerr << std::endl; + RS_ERR(); #endif sockaddr_storage_clear(addr); @@ -249,7 +248,9 @@ bool sockaddr_storage_setipv4(struct sockaddr_storage &addr, const sockaddr_in * bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6 *addr_ipv6) { - std::cerr << "sockaddr_storage_setipv6()" << std::endl; +#ifdef SS_DEBUG + RS_ERR(); +#endif sockaddr_storage_clear(addr); struct sockaddr_in6 *ipv6_ptr = to_ipv6_ptr(addr); @@ -262,6 +263,7 @@ bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6 } #ifdef WINDOWS_SYS +#ifndef InetPtonA int inet_pton(int af, const char *src, void *dst) { sockaddr_storage ss; @@ -288,6 +290,7 @@ int inet_pton(int af, const char *src, void *dst) return 0; } #endif +#endif bool sockaddr_storage_inet_pton( sockaddr_storage &addr, const std::string& ipStr ) diff --git a/retroshare-gui/src/gui/settings/ServerPage.cpp b/retroshare-gui/src/gui/settings/ServerPage.cpp index 06f6d911c..8addc4349 100755 --- a/retroshare-gui/src/gui/settings/ServerPage.cpp +++ b/retroshare-gui/src/gui/settings/ServerPage.cpp @@ -66,11 +66,11 @@ /// // Tabs numbers *after* non relevant tabs are removed. So do not use them to add/remove tabs!! -const static uint32_t TAB_HIDDEN_SERVICE_OUTGOING = 0; +//nst static uint32_t TAB_HIDDEN_SERVICE_OUTGOING = 0; const static uint32_t TAB_HIDDEN_SERVICE_INCOMING = 1; const static uint32_t TAB_HIDDEN_SERVICE_I2P = 2; -const static uint32_t TAB_NETWORK = 0; +//nst static uint32_t TAB_NETWORK = 0; const static uint32_t TAB_HIDDEN_SERVICE = 1; const static uint32_t TAB_IP_FILTERS = 2; const static uint32_t TAB_RELAYS = 3; @@ -155,8 +155,8 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) ui.leBobB32Addr->hide(); ui.pbBobGenAddr->hide(); - QObject::connect(ui.filteredIpsTable,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(ipFilterContextMenu(const QPoint&))) ; - QObject::connect(ui.whiteListIpsTable,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(ipWhiteListContextMenu(const QPoint&))) ; + QObject::connect(ui.filteredIpsTable,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(ipFilterContextMenu(QPoint))) ; + QObject::connect(ui.whiteListIpsTable,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(ipWhiteListContextMenu(QPoint))) ; QObject::connect(ui.denyAll_CB,SIGNAL(toggled(bool)),this,SLOT(toggleIpFiltering(bool))); QObject::connect(ui.includeFromDHT_CB,SIGNAL(toggled(bool)),this,SLOT(toggleAutoIncludeDHT(bool))); QObject::connect(ui.includeFromFriends_CB,SIGNAL(toggled(bool)),this,SLOT(toggleAutoIncludeFriends(bool))); @@ -164,7 +164,7 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) QObject::connect(ui.groupIPRanges_SB,SIGNAL(valueChanged(int)),this,SLOT(setGroupIpLimit(int))); QObject::connect(ui.ipInputAddBlackList_PB,SIGNAL(clicked()),this,SLOT(addIpRangeToBlackList())); QObject::connect(ui.ipInputAddWhiteList_PB,SIGNAL(clicked()),this,SLOT(addIpRangeToWhiteList())); - QObject::connect(ui.ipInput_LE,SIGNAL(textChanged(const QString&)),this,SLOT(checkIpRange(const QString&))); + QObject::connect(ui.ipInput_LE,SIGNAL(textChanged(QString)),this,SLOT(checkIpRange(QString))); QObject::connect(ui.filteredIpsTable,SIGNAL(currentCellChanged(int,int,int,int)),this,SLOT(updateSelectedBlackListIP(int,int,int,int))); QObject::connect(ui.whiteListIpsTable,SIGNAL(currentCellChanged(int,int,int,int)),this,SLOT(updateSelectedWhiteListIP(int,int,int,int))); @@ -193,10 +193,10 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) QObject::connect(ui.localPort,SIGNAL(valueChanged(int)),this,SLOT(saveAddresses())); QObject::connect(ui.extPort,SIGNAL(valueChanged(int)),this,SLOT(saveAddresses())); - connect( ui.netModeComboBox, SIGNAL( activated ( int ) ), this, SLOT( toggleUPnP( ) ) ); - connect( ui.allowIpDeterminationCB, SIGNAL( toggled( bool ) ), this, SLOT( toggleIpDetermination(bool) ) ); - connect( ui.cleanKnownIPs_PB, SIGNAL( clicked( ) ), this, SLOT( clearKnownAddressList() ) ); - connect( ui.testIncoming_PB, SIGNAL( clicked( ) ), this, SLOT( saveAndTestInProxy() ) ); + connect( ui.netModeComboBox, SIGNAL( activated(int) ), this, SLOT( toggleUPnP() ) ); + connect( ui.allowIpDeterminationCB, SIGNAL( toggled(bool) ), this, SLOT( toggleIpDetermination(bool) ) ); + connect( ui.cleanKnownIPs_PB, SIGNAL( clicked() ), this, SLOT( clearKnownAddressList() ) ); + connect( ui.testIncoming_PB, SIGNAL( clicked() ), this, SLOT( saveAndTestInProxy() ) ); #ifdef SERVER_DEBUG std::cerr << "ServerPage::ServerPage() called"; @@ -228,7 +228,7 @@ ServerPage::ServerPage(QWidget * parent, Qt::WindowFlags flags) QObject::connect(ui.addPushButton,SIGNAL(clicked()),this,SLOT(addServer())); QObject::connect(ui.removePushButton,SIGNAL(clicked()),this,SLOT(removeServer())); - QObject::connect(ui.DhtLineEdit,SIGNAL(textChanged(const QString &)),this,SLOT(checkKey())); + QObject::connect(ui.DhtLineEdit,SIGNAL(textChanged(QString)),this,SLOT(checkKey())); QObject::connect(ui.enableCheckBox,SIGNAL(stateChanged(int)),this,SLOT(updateEnabled())); QObject::connect(ui.serverCheckBox,SIGNAL(stateChanged(int)),this,SLOT(updateEnabled())); @@ -433,8 +433,8 @@ void ServerPage::load() { if (detail.vs_disc != RS_VS_DISC_OFF) netIndex = 1; // PRIVATE - else - netIndex = 3; // NONE + //else //Use default value + // netIndex = 3; // NONE } whileBlocking(ui.discComboBox)->setCurrentIndex(netIndex); @@ -459,6 +459,7 @@ void ServerPage::load() whileBlocking(ui.ipAddressList)->clear(); + detail.ipAddressList.sort(); for(std::list::const_iterator it(detail.ipAddressList.begin());it!=detail.ipAddressList.end();++it) whileBlocking(ui.ipAddressList)->addItem(QString::fromStdString(*it)); @@ -824,10 +825,10 @@ void ServerPage::ipWhiteListContextMenu(const QPoint& /* point */) return ; } - QString range0 = RsNetUtil::printAddrRange(addr,0) ; - QString range1 = RsNetUtil::printAddrRange(addr,1) ; - QString range2 = RsNetUtil::printAddrRange(addr,2) ; - +// QString range0 = RsNetUtil::printAddrRange(addr,0) ; +// QString range1 = RsNetUtil::printAddrRange(addr,1) ; +// QString range2 = RsNetUtil::printAddrRange(addr,2) ; +// // contextMenu.addAction(QObject::tr("Whitelist only IP " )+range0,this,SLOT(enableBannedIp()))->setEnabled(false) ; //#warning UNIMPLEMENTED CODE // contextMenu.addAction(QObject::tr("Whitelist entire range ")+range1,this,SLOT(enableBannedIp()))->setEnabled(false) ; @@ -930,6 +931,28 @@ void ServerPage::updateStatus() else ui.iconlabel_ext->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/ledoff1.png")); + if (ui.ipAddressList->isEnabled() ) + { + whileBlocking(ui.ipAddressList)->clear(); + detail.ipAddressList.sort(); + for(auto& it : detail.ipAddressList) + whileBlocking(ui.ipAddressList)->addItem(QString::fromStdString(it).replace("sec",tr("sec")).replace("loc",tr("local")).replace("ext",tr("external"))); + } + + QString toolTip = tr("List of OpenDns servers used."); + if (ui.IPServersLV->isEnabled() ) + { + std::list ip_list; + rsPeers->getCurrentExtIPList(ip_list); + if ( !ip_list.empty() ) + { + toolTip += tr("\n\nList of found external IP:\n"); + for(std::list::const_iterator it(ip_list.begin());it!=ip_list.end();++it) + toolTip += " " + QString::fromStdString(*it) +"\n" ; + } + } + if(ui.IPServersLV->toolTip() != toolTip) + ui.IPServersLV->setToolTip(toolTip); } void ServerPage::toggleUPnP() @@ -1158,6 +1181,7 @@ void ServerPage::loadHiddenNode() // show what we have in ipAddresses. (should be nothing!) ui.ipAddressList->clear(); + detail.ipAddressList.sort(); for(std::list::const_iterator it(detail.ipAddressList.begin());it!=detail.ipAddressList.end();++it) whileBlocking(ui.ipAddressList)->addItem(QString::fromStdString(*it)); diff --git a/retroshare-gui/src/gui/settings/ServerPage.ui b/retroshare-gui/src/gui/settings/ServerPage.ui index d97187b54..6b78b988c 100755 --- a/retroshare-gui/src/gui/settings/ServerPage.ui +++ b/retroshare-gui/src/gui/settings/ServerPage.ui @@ -704,7 +704,7 @@ connecting when you have few friends. It also helps if you're behind a firewall or a VPN. - Allow RetroShare to ask my ip to these websites: + Allow RetroShare to ask my ip to these DNS servers: true @@ -719,6 +719,9 @@ behind a firewall or a VPN. 0 + + List of OpenDns servers used. + QAbstractItemView::NoEditTriggers