From 181ad06e331af65d88a356a8a125386b19a1d593 Mon Sep 17 00:00:00 2001 From: drbob Date: Sun, 17 Jul 2011 13:48:37 +0000 Subject: [PATCH] Added Exclusive Proxy Lock for DETERMINISTIC SYM Nats. * tweaked time periods as these type of connections take longer. * added NatHoleType() to ConnectStateBox logic - as its required for ProxyPort Determination. * added ConnectStateBox::getNetState() so we can work out if in ExclusiveNat mode. * added ExclusiveLock checks at Connection Initiation / Proxy Connection Auth & Connection Ends. * added Simulation of Symmetric / Exclusive Nat to UdpStunner. * exported ExclusiveProxyLock for GUI display. git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-netupgrade@4457 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/dht/connectstatebox.cc | 40 ++- libretroshare/src/dht/connectstatebox.h | 5 +- libretroshare/src/dht/p3bitdht.h | 8 +- libretroshare/src/dht/p3bitdht_interface.cc | 2 + libretroshare/src/dht/p3bitdht_peernet.cc | 280 ++++++++++++++++---- libretroshare/src/dht/p3bitdht_peers.cc | 2 + libretroshare/src/retroshare/rsdht.h | 2 + libretroshare/src/tcponudp/udpstunner.cc | 66 ++++- libretroshare/src/tcponudp/udpstunner.h | 11 +- 9 files changed, 338 insertions(+), 78 deletions(-) diff --git a/libretroshare/src/dht/connectstatebox.cc b/libretroshare/src/dht/connectstatebox.cc index a6f70df00..e042f8e8f 100644 --- a/libretroshare/src/dht/connectstatebox.cc +++ b/libretroshare/src/dht/connectstatebox.cc @@ -33,31 +33,35 @@ #define TESTING_PERIODS 1 +/* Have made the PROXY Attempts + MAX_TIME much larger, + * have have potential for this to take a while. + */ + #ifdef TESTING_PERIODS #define FAILED_WAIT_TIME (1800) // 5 minutes. #define TCP_WAIT_TIME (10) // 1/6 minutes. #define DIRECT_MAX_WAIT_TIME (30) // 1/6 minutes. - #define PROXY_MAX_WAIT_TIME (30) // 1/6 minutes. + #define PROXY_MAX_WAIT_TIME (120) // 1/6 minutes. #define RELAY_MAX_WAIT_TIME (30) // 1/6 minutes. #define REVERSE_WAIT_TIME (30) // 1/2 minutes. #define MAX_DIRECT_ATTEMPTS (3) - #define MAX_PROXY_ATTEMPTS (3) + #define MAX_PROXY_ATTEMPTS (10) #define MAX_RELAY_ATTEMPTS (3) #define MAX_DIRECT_FAILED_ATTEMPTS (1) - #define MAX_PROXY_FAILED_ATTEMPTS (1) + #define MAX_PROXY_FAILED_ATTEMPTS (2) #define MAX_RELAY_FAILED_ATTEMPTS (1) #else #define FAILED_WAIT_TIME (1800) // 30 minutes. #define TCP_WAIT_TIME (60) // 1 minutes. #define DIRECT_MAX_WAIT_TIME (60) // 1 minutes. - #define PROXY_MAX_WAIT_TIME (60) // 1 minutes. + #define PROXY_MAX_WAIT_TIME (120) // 1 minutes. #define RELAY_MAX_WAIT_TIME (60) // 1 minutes. #define REVERSE_WAIT_TIME (300) // 5 minutes. #define MAX_DIRECT_ATTEMPTS (10) - #define MAX_PROXY_ATTEMPTS (10) + #define MAX_PROXY_ATTEMPTS (20) #define MAX_RELAY_ATTEMPTS (10) #define MAX_DIRECT_FAILED_ATTEMPTS (3) @@ -81,6 +85,11 @@ PeerConnectStateBox::PeerConnectStateBox() } +uint32_t PeerConnectStateBox::getNetState() +{ + return mNetState; +} + std::string NetStateAsString(uint32_t netstate) { @@ -230,14 +239,15 @@ std::string PeerConnectStateBox::connectState() const std::ostringstream out; time_t now = time(NULL); out << str << "(" << mNoAttempts << "/" << mNoFailedAttempts << ") for " << now - mStateTS << " secs"; - out << " LA: " << mAttemptLength; if ( (mState == CSB_CONNECTED) || (mState == CSB_DIRECT_ATTEMPT) || - (mState == CSB_PROXY_ATTEMPT) || (mState == CSB_RELAY_ATTEMPT) ) + (mState == CSB_PROXY_ATTEMPT) || (mState == CSB_RELAY_ATTEMPT) || + (mState == CSB_FAILED_WAIT) ) { - // nothing here... as we are not dependent on the timer. + out << " Last Attempt: " << mAttemptLength; } else { + out << " LA: " << mAttemptLength; out << " NextAttempt: " << mNextAttemptTS - now; } @@ -245,7 +255,7 @@ std::string PeerConnectStateBox::connectState() const } -uint32_t convertNetStateToInternal(uint32_t netmode, uint32_t nattype) +uint32_t convertNetStateToInternal(uint32_t netmode, uint32_t nathole, uint32_t nattype) { uint32_t connNet = CSB_NETSTATE_UNKNOWN; @@ -253,6 +263,10 @@ uint32_t convertNetStateToInternal(uint32_t netmode, uint32_t nattype) { connNet = CSB_NETSTATE_FORWARD; } + else if ((nathole != RSNET_NATHOLE_UNKNOWN) && (nathole != RSNET_NATHOLE_NONE)) + { + connNet = CSB_NETSTATE_FORWARD; + } else if (netmode == RSNET_NETWORK_BEHINDNAT) { if ((nattype == RSNET_NATTYPE_RESTRICTED_CONE) || @@ -281,15 +295,15 @@ bool shouldUseProxyPortInternal(uint32_t netstate) return true; } -bool PeerConnectStateBox::shouldUseProxyPort(uint32_t netmode, uint32_t nattype) +bool PeerConnectStateBox::shouldUseProxyPort(uint32_t netmode, uint32_t nathole, uint32_t nattype) { - uint32_t netstate = convertNetStateToInternal(netmode, nattype); + uint32_t netstate = convertNetStateToInternal(netmode, nathole, nattype); return shouldUseProxyPortInternal(netstate); } -uint32_t PeerConnectStateBox::connectCb(uint32_t cbtype, uint32_t netmode, uint32_t nattype) +uint32_t PeerConnectStateBox::connectCb(uint32_t cbtype, uint32_t netmode, uint32_t nathole, uint32_t nattype) { - uint32_t netstate = convertNetStateToInternal(netmode, nattype); + uint32_t netstate = convertNetStateToInternal(netmode, nathole, nattype); std::cerr << "PeerConnectStateBox::connectCb("; if (cbtype == CSB_CONNECT_DIRECT) diff --git a/libretroshare/src/dht/connectstatebox.h b/libretroshare/src/dht/connectstatebox.h index 18dac027d..3b49a8a7e 100644 --- a/libretroshare/src/dht/connectstatebox.h +++ b/libretroshare/src/dht/connectstatebox.h @@ -84,11 +84,12 @@ class PeerConnectStateBox public: PeerConnectStateBox(); - uint32_t connectCb(uint32_t cbtype, uint32_t netmode, uint32_t nattype); + uint32_t connectCb(uint32_t cbtype, uint32_t netmode, uint32_t nathole, uint32_t nattype); uint32_t updateCb(uint32_t updateType); - bool shouldUseProxyPort(uint32_t netmode, uint32_t nattype); + bool shouldUseProxyPort(uint32_t netmode, uint32_t nathole, uint32_t nattype); + uint32_t getNetState(); std::string connectState() const; std::string mPeerId; diff --git a/libretroshare/src/dht/p3bitdht.h b/libretroshare/src/dht/p3bitdht.h index f7f578bc3..a6e40a841 100644 --- a/libretroshare/src/dht/p3bitdht.h +++ b/libretroshare/src/dht/p3bitdht.h @@ -71,6 +71,8 @@ class DhtPeerDetails time_t mPeerConnectTS; time_t mPeerConnectClosedTS; + bool mExclusiveProxyLock; + /* keeping the PeerCbMsg, as we will need it for debugging */ /* don't think this data is ever used for decisions??? */ @@ -109,6 +111,7 @@ class PeerAction uint32_t mMode; uint32_t mPoint; uint32_t mAnswer; + uint32_t mDelayOrBandwidth; }; @@ -226,9 +229,12 @@ void ConnectCalloutRelay(const std::string &peerId, struct sockaddr_in srcaddr, void Feedback_Connected(std::string pid); void Feedback_ConnectionFailed(std::string pid); -void UdpConnectionFailed_locked(DhtPeerDetails *dpd); void Feedback_ConnectionClosed(std::string pid); +void UdpConnectionFailed_locked(DhtPeerDetails *dpd); +void ReleaseProxyExclusiveMode_locked(DhtPeerDetails *dpd); + + /*********************************************************************************************** ************************** Internal Accounting (p3bitdht_peers.cc) **************************** diff --git a/libretroshare/src/dht/p3bitdht_interface.cc b/libretroshare/src/dht/p3bitdht_interface.cc index 3dee829c4..4be4205f3 100644 --- a/libretroshare/src/dht/p3bitdht_interface.cc +++ b/libretroshare/src/dht/p3bitdht_interface.cc @@ -185,6 +185,8 @@ void convertDhtPeerDetailsToRsDhtNetPeer(RsDhtNetPeer &status, const DhtPeerDeta status.mPeerReqState = details.mPeerReqState; + status.mExclusiveProxyLock = details.mExclusiveProxyLock; + status.mPeerConnectState = details.mPeerConnectState; switch(details.mPeerConnectMode) diff --git a/libretroshare/src/dht/p3bitdht_peernet.cc b/libretroshare/src/dht/p3bitdht_peernet.cc index e30574398..3e6ee2fb7 100644 --- a/libretroshare/src/dht/p3bitdht_peernet.cc +++ b/libretroshare/src/dht/p3bitdht_peernet.cc @@ -313,7 +313,7 @@ int p3BitDht::OnlinePeerCallback_locked(const bdId *id, uint32_t status, DhtPeer /* work out network state */ uint32_t connectFlags = dpd->mConnectLogic.connectCb(CSB_CONNECT_DIRECT, - mNetMgr->getNetworkMode(), mNetMgr->getNatTypeMode()); + mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()); bool useProxyPort = (connectFlags & CSB_ACTION_PROXY_PORT); switch(connectFlags & CSB_ACTION_MASK_MODE) @@ -414,7 +414,7 @@ int p3BitDht::UnreachablePeerCallback_locked(const bdId *id, uint32_t status, Dh /* work out network state */ uint32_t connectFlags = dpd->mConnectLogic.connectCb(CSB_CONNECT_UNREACHABLE, - mNetMgr->getNetworkMode(), mNetMgr->getNatTypeMode()); + mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()); bool useProxyPort = (connectFlags & CSB_ACTION_PROXY_PORT); switch(connectFlags & CSB_ACTION_MASK_MODE) @@ -580,6 +580,7 @@ int p3BitDht::ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId ca.mDestId = *destId; ca.mPoint = point; ca.mAnswer = connectionAllowed; + ca.mDelayOrBandwidth = 0; mActions.push_back(ca); } @@ -676,6 +677,7 @@ int p3BitDht::ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId ca.mProxyId = *proxyId; ca.mSrcId = *srcId; ca.mDestId = *destId; + ca.mDelayOrBandwidth = 0; /* Check Proxy ExtAddress Status (but only if connection is Allowed) */ if ((connectionAllowed == BITDHT_CONNECT_ANSWER_OKAY) && @@ -690,6 +692,7 @@ int p3BitDht::ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId bool connectOk = false; bool proxyPort = false; + bool exclusivePort = false; std::cerr << "dhtConnectionCallback(): Proxy... deciding which port to use."; std::cerr << std::endl; @@ -697,7 +700,7 @@ int p3BitDht::ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId if (dpd) { proxyPort = dpd->mConnectLogic.shouldUseProxyPort( - mNetMgr->getNetworkMode(), mNetMgr->getNatTypeMode()); + mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()); dpd->mConnectLogic.storeProxyPortChoice(0, proxyPort); @@ -705,6 +708,17 @@ int p3BitDht::ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId std::cerr << " UseProxyPort? " << proxyPort; std::cerr << std::endl; + if (proxyPort) + { + exclusivePort = (CSB_NETSTATE_EXCLUSIVENAT == dpd->mConnectLogic.getNetState()); + } + + if (exclusivePort) + { + std::cerr << "dhtConnectionCallback: we Require Exclusive Proxy Port for connection"; + std::cerr << std::endl; + } + connectOk = true; } else @@ -725,7 +739,7 @@ int p3BitDht::ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId { std::cerr << "dhtConnectionCallback() Proxy Connection Attempt to: "; bdStdPrintId(std::cerr, &(peerId)); - std::cerr << " is OkGo as we have Stable Own External Proxy Address"; + std::cerr << " is Ok as we have Stable Own External Proxy Address"; std::cerr << std::endl; if (point == BD_PROXY_CONNECTION_END_POINT) @@ -738,14 +752,62 @@ int p3BitDht::ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId std::cerr << "dhtConnectionCallback() ERROR Proxy Auth as SrcId"; std::cerr << std::endl; } + + /* check if we require exclusive use of the proxy port */ + if (exclusivePort) + { + std::cerr << "dhtConnectionCallback: Attempting to Grab ExclusiveLock of UdpStunner"; + std::cerr << std::endl; + int delay = mProxyStunner->grabExclusiveMode(); + if (delay > 0) + { + /* great we got it! */ + ca.mDelayOrBandwidth = delay; + DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId.id), RSDHT_PEERTYPE_FRIEND); + if (dpd) + { + dpd->mExclusiveProxyLock = true; + + std::cerr << "dhtConnectionCallback: Success at grabbing ExclusiveLock of UdpStunner"; + std::cerr << std::endl; + + } + else + { + std::cerr << "PeerAction: Connect Proxy: ERROR Cannot find PeerStatus"; + std::cerr << std::endl; + connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL; + mProxyStunner->releaseExclusiveMode(); + } + } + else + { + /* failed to get exclusive mode - must wait */ + connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL; + + std::cerr << "dhtConnectionCallback: Failed to Grab ExclusiveLock, Returning TEMPUNAVAIL"; + std::cerr << std::endl; + } + } + } else { - connectionAllowed = BITDHT_CONNECT_ERROR_UNREACHABLE; - std::cerr << "dhtConnectionCallback() Proxy Connection"; - std::cerr << " is Discarded, as Own External Proxy Address is Not Stable!"; - std::cerr << std::endl; + if (exclusivePort) + { + connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL; + std::cerr << "dhtConnectionCallback() Proxy Connection"; + std::cerr << " is Discarded, as External Proxy Address is Not Stable! (EXCLUSIVE MODE)"; + std::cerr << std::endl; + } + else + { + connectionAllowed = BITDHT_CONNECT_ERROR_UNREACHABLE; + std::cerr << "dhtConnectionCallback() Proxy Connection"; + std::cerr << " is Discarded, as Own External Proxy Address is Not Stable!"; + std::cerr << std::endl; + } } } else @@ -853,6 +915,8 @@ int p3BitDht::ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId { if (errcode) { + ReleaseProxyExclusiveMode_locked(dpd); + dpd->mPeerReqStatusMsg = "STOPPED: "; dpd->mPeerReqStatusMsg += decodeConnectionError(errcode); dpd->mPeerReqState = RSDHT_PEERREQ_STOPPED; @@ -1032,23 +1096,22 @@ int p3BitDht::doActions() std::cerr << " mode: " << action.mMode; std::cerr << std::endl; - bool connectionRequested = false; + bool doConnectionRequest = false; bool connectionReqFailed = false; + bool grabbedExclusivePort = false; + + // Parameters that will be used for the Connect Request. + struct sockaddr_in connAddr; // We zero this address. (DHT Layer handles most cases) + sockaddr_clear(&connAddr); + uint32_t connStart = 1; /* > 0 indicates GO (number indicates required startup delay) */ + uint32_t connDelay = 0; + + uint32_t failReason = CSB_UPDATE_MODE_UNAVAILABLE; if ((action.mMode == BITDHT_CONNECT_MODE_DIRECT) || (action.mMode == BITDHT_CONNECT_MODE_RELAY)) { - struct sockaddr_in laddr; // We zero this address. The DHT layer should be able to handle this! - sockaddr_clear(&laddr); - uint32_t start = 1; - if (mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode, start)) - { - connectionRequested = true; - } - else - { - connectionReqFailed = true; - } + doConnectionRequest = true; } else if (action.mMode == BITDHT_CONNECT_MODE_PROXY) { @@ -1056,6 +1119,7 @@ int p3BitDht::doActions() uint8_t extStable = 0; sockaddr_clear(&extaddr); bool proxyPort = true; + bool exclusivePort = false; bool connectOk = false; std::cerr << "PeerAction: Proxy... deciding which port to use."; @@ -1068,8 +1132,12 @@ int p3BitDht::doActions() { connectOk = true; proxyPort = dpd->mConnectLogic.getProxyPortChoice(); - - + if (proxyPort) + { + std::cerr << "PeerAction: Using ProxyPort. NetState indicates Exclusive Mode"; + std::cerr << std::endl; + exclusivePort = (CSB_NETSTATE_EXCLUSIVENAT == dpd->mConnectLogic.getNetState()); + } } else { @@ -1091,25 +1159,55 @@ int p3BitDht::doActions() bdStdPrintId(std::cerr, &(action.mDestId)); std::cerr << " is OkGo as we have Stable Own External Proxy Address"; std::cerr << std::endl; - - int start = 1; - if (mUdpBitDht->ConnectionRequest(&extaddr, &(action.mDestId.id), action.mMode, start)) + + /* check if we require exclusive use of the proxy port */ + if (exclusivePort) { - connectionRequested = true; + int delay = mProxyStunner->grabExclusiveMode(); + if (delay > 0) + { + /* great we got it! */ + connAddr = extaddr; + connDelay = delay; + doConnectionRequest = true; + grabbedExclusivePort = true; + } + else + { + /* failed to get exclusive mode - must wait */ + connectionReqFailed = true; + failReason = CSB_UPDATE_RETRY_ATTEMPT; + } } else { - connectionReqFailed = true; + /* stable and non-exclusive - go for it */ + connAddr = extaddr; + connStart = 1; + doConnectionRequest = true; } } else { - std::cerr << "PeerAction: ERROR Proxy Connection Attempt to: "; + std::cerr << "PeerAction: WARNING Proxy Connection Attempt to: "; bdStdPrintId(std::cerr, &(action.mDestId)); std::cerr << " is Discarded, as Own External Proxy Address is Not Stable!"; std::cerr << std::endl; connectionReqFailed = true; + if (exclusivePort) + { + failReason = CSB_UPDATE_RETRY_ATTEMPT; + std::cerr << "PeerAction: As Exclusive Mode, Port Will stabilise => RETRY"; + std::cerr << std::endl; + + } + else + { + failReason = CSB_UPDATE_MODE_UNAVAILABLE; + std::cerr << "PeerAction: Not Exclusive Mode, => MODE UNAVAILABLE"; + std::cerr << std::endl; + } } } else @@ -1119,38 +1217,48 @@ int p3BitDht::doActions() std::cerr << " is Discarded, as Failed to get Own External Proxy Address."; std::cerr << std::endl; + connectionReqFailed = true; + failReason = CSB_UPDATE_RETRY_ATTEMPT; + } + } + + if (doConnectionRequest) + { + // XXX TO DO. + //if (mUdpBitDht->ConnectionRequest(&connAddr, &(action.mDestId.id), action.mMode, connStart, connDelay)) + if (mUdpBitDht->ConnectionRequest(&connAddr, &(action.mDestId.id), action.mMode, connStart)) + { RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ + std::cerr << "PeerAction: Connection Attempt to: "; + bdStdPrintId(std::cerr, &(action.mDestId)); + std::cerr << " has gone ahead"; + std::cerr << std::endl; + + DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RSDHT_PEERTYPE_FRIEND); if (dpd) { - dpd->mConnectLogic.updateCb(CSB_UPDATE_FAILED_ATTEMPT); + dpd->mPeerReqStatusMsg = "Connect Request"; + dpd->mPeerReqState = RSDHT_PEERREQ_RUNNING; + dpd->mPeerReqMode = action.mMode; + dpd->mPeerReqTS = now; + + if (grabbedExclusivePort) + { + dpd->mExclusiveProxyLock = true; + } + } + else + { + std::cerr << "PeerAction: Connect ERROR Cannot find PeerStatus"; + std::cerr << std::endl; } - } - } - - if (connectionRequested) - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - std::cerr << "PeerAction: Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " has gone ahead"; - std::cerr << std::endl; - - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RSDHT_PEERTYPE_FRIEND); - if (dpd) - { - dpd->mPeerReqStatusMsg = "Connect Request"; - dpd->mPeerReqState = RSDHT_PEERREQ_RUNNING; - dpd->mPeerReqMode = action.mMode; - dpd->mPeerReqTS = now; } else { - std::cerr << "PeerAction: Connect ERROR Cannot find PeerStatus"; - std::cerr << std::endl; + connectionReqFailed = true; + failReason = CSB_UPDATE_MODE_UNAVAILABLE; } } @@ -1161,11 +1269,16 @@ int p3BitDht::doActions() std::cerr << " is Discarded, as Mode is Unavailable"; std::cerr << std::endl; + if (grabbedExclusivePort) + { + mProxyStunner->releaseExclusiveMode(); + } + RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RSDHT_PEERTYPE_FRIEND); if (dpd) { - dpd->mConnectLogic.updateCb(CSB_UPDATE_MODE_UNAVAILABLE); + dpd->mConnectLogic.updateCb(failReason); dpd->mPeerReqStatusMsg = "Req Mode Unavailable"; dpd->mPeerReqState = RSDHT_PEERREQ_STOPPED; @@ -1185,8 +1298,13 @@ int p3BitDht::doActions() std::cerr << " and "; bdStdPrintId(std::cerr, &(action.mDestId)); std::cerr << " mode: " << action.mMode; + std::cerr << " delay/bandwidth: " << action.mDelayOrBandwidth; std::cerr << std::endl; + // XXX TODO + //mUdpBitDht->ConnectionAuth(&(action.mSrcId), &(action.mProxyId), &(action.mDestId), + // action.mMode, action.mPoint, action.mAnswer, action.mDelayOrBandwidth); + mUdpBitDht->ConnectionAuth(&(action.mSrcId), &(action.mProxyId), &(action.mDestId), action.mMode, action.mPoint, action.mAnswer); @@ -1238,8 +1356,13 @@ int p3BitDht::doActions() std::cerr << " and "; bdStdPrintId(std::cerr, &(action.mDestId)); std::cerr << " mode: " << action.mMode; + std::cerr << " delay/bandwidth: " << action.mDelayOrBandwidth; std::cerr << std::endl; + // XXX TO DO. + //initiateConnection(&(action.mSrcId), &(action.mProxyId), &(action.mDestId), + // action.mMode, action.mPoint, action.mAnswer, action.mDelayOrBandwidth); + initiateConnection(&(action.mSrcId), &(action.mProxyId), &(action.mDestId), action.mMode, action.mPoint, action.mAnswer); } @@ -1256,6 +1379,9 @@ int p3BitDht::doActions() struct sockaddr_in laddr; sockaddr_clear(&laddr); uint32_t start = 1; + // XXX TO DO. + //mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode, start, 0); + mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode, start); } break; @@ -1271,6 +1397,9 @@ int p3BitDht::doActions() struct sockaddr_in laddr; sockaddr_clear(&laddr); uint32_t start = 0; + + // XXX TO DO. + //mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode, start, 0); mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode, start); } break; @@ -1283,11 +1412,6 @@ int p3BitDht::doActions() std::cerr << " mode: " << action.mMode; std::cerr << std::endl; - struct sockaddr_in laddr; - sockaddr_clear(&laddr); - uint32_t start = 0; - mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode, start); - std::string peerRsId; bool foundPeerId = false; { @@ -1883,6 +2007,8 @@ void p3BitDht::Feedback_Connected(std::string pid) std::cerr << "p3BitDht::monitorConnections() ERROR Request not active, can't stop"; std::cerr << std::endl; } + + ReleaseProxyExclusiveMode_locked(dpd); } void p3BitDht::Feedback_ConnectionFailed(std::string pid) @@ -1983,10 +2109,50 @@ void p3BitDht::UdpConnectionFailed_locked(DhtPeerDetails *dpd) std::cerr << "p3BitDht::monitorConnections() ERROR Request not active, can't stop"; std::cerr << std::endl; } + + ReleaseProxyExclusiveMode_locked(dpd); } +void p3BitDht::ReleaseProxyExclusiveMode_locked(DhtPeerDetails *dpd) +{ +#ifdef DEBUG_BITDHT_COMMON + std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked()"; + bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); + std::cerr << std::endl; +#endif + + if (dpd->mExclusiveProxyLock) + { + if (mProxyStunner->releaseExclusiveMode()) + { + dpd->mExclusiveProxyLock = false; + + std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked() Lock released by Connection to peer: "; + bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); + std::cerr << std::endl; + } + else + { + dpd->mExclusiveProxyLock = false; + + std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked() ERROR ProxyStunner is not Locked"; + bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); + std::cerr << std::endl; + } + + } + else + { +#ifdef DEBUG_BITDHT_COMMON + std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked() Don't Have a Lock"; + std::cerr << std::endl; +#endif + } + +} + void p3BitDht::ConnectionFeedback(std::string pid, int mode) { diff --git a/libretroshare/src/dht/p3bitdht_peers.cc b/libretroshare/src/dht/p3bitdht_peers.cc index 26e719abe..d0847d6ea 100644 --- a/libretroshare/src/dht/p3bitdht_peers.cc +++ b/libretroshare/src/dht/p3bitdht_peers.cc @@ -89,6 +89,8 @@ bool p3BitDht::findPeer(std::string pid) dpd->mPeerReqMode = 0; //dpd->mPeerReqProxyId; dpd->mPeerReqTS = time(NULL); + + dpd->mExclusiveProxyLock = false; dpd->mPeerCbMsg = "No CB Yet"; dpd->mPeerCbMode = 0; diff --git a/libretroshare/src/retroshare/rsdht.h b/libretroshare/src/retroshare/rsdht.h index acb101366..dd38760a6 100644 --- a/libretroshare/src/retroshare/rsdht.h +++ b/libretroshare/src/retroshare/rsdht.h @@ -105,6 +105,8 @@ class RsDhtNetPeer // connect mode uint32_t mPeerConnectMode; + bool mExclusiveProxyLock; + std::string mPeerConnectProxyId; // Req Status. diff --git a/libretroshare/src/tcponudp/udpstunner.cc b/libretroshare/src/tcponudp/udpstunner.cc index c866ecdbe..d3b854bea 100644 --- a/libretroshare/src/tcponudp/udpstunner.cc +++ b/libretroshare/src/tcponudp/udpstunner.cc @@ -23,10 +23,11 @@ * */ -#include "udpstunner.h" +#include "tcponudp/udpstunner.h" #include #include +#include "util/rsrandom.h" #include "util/rsprint.h" static const int STUN_TTL = 64; @@ -56,6 +57,9 @@ UdpStunner::UdpStunner(UdpPublisher *pub) { #ifdef UDPSTUN_ALLOW_LOCALNET mAcceptLocalNet = false; + mSimExclusiveNat = false; + mSimSymmetricNat = false; + mSimUnstableExt = false; #endif @@ -81,10 +85,29 @@ void UdpStunner::SetAcceptLocalNet() mAcceptLocalNet = true; } + // For Local Testing Only (Releases should have the #define disabled) +void UdpStunner::SimExclusiveNat() +{ + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + + mSimExclusiveNat = true; + mSimUnstableExt = true; +} + +void UdpStunner::SimSymmetricNat() +{ + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + + mSimSymmetricNat = true; + mSimUnstableExt = true; +} + + + #endif -int UdpStunner::setExclusiveMode() /* returns seconds since last send/recv */ +int UdpStunner::grabExclusiveMode() /* returns seconds since last send/recv */ { RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ @@ -127,7 +150,7 @@ int UdpStunner::setExclusiveMode() /* returns seconds since last send/recv */ return commsage; } -int UdpStunner::cancelExclusiveMode() +int UdpStunner::releaseExclusiveMode() { RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ @@ -143,6 +166,21 @@ int UdpStunner::cancelExclusiveMode() time_t now = time(NULL); mExclusiveMode = false; + +#ifdef UDPSTUN_ALLOW_LOCALNET + /* if we are simulating an exclusive NAT, then immediately after we release - it'll become unstable. + * This is even harser than reality... so better test. + * + * In reality, it will only become unstable if we have tried a UDP connection. + */ + + if (mSimExclusiveNat) + { + mSimUnstableExt = true; + } +#endif + + #ifdef DEBUG_UDP_STUNNER_FILTER std::cerr << "UdpStunner::cancelExclusiveMode() Canceled. Was in ExclusiveMode for: " << now - mExclusiveModeTS; std::cerr << " secs"; @@ -336,6 +374,7 @@ bool UdpStunner::externalAddr(struct sockaddr_in &external, uint8_t &stable) std::cerr << std::endl; #endif + return true; } #ifdef DEBUG_UDP_STUNNER @@ -780,6 +819,23 @@ bool UdpStunner::locked_recvdStun(const struct sockaddr_in &remote, const str std::cerr << out.str() << std::endl; #endif +#ifdef UDPSTUN_ALLOW_LOCALNET + struct sockaddr_in fakeExtaddr = extaddr; + if (mSimUnstableExt) + { + std::cerr << "UdpStunner::locked_recvdStun() TEST SIM UNSTABLE EXT: Forcing Port to be wrong to sim an ExclusiveNat"; + std::cerr << std::endl; + +#define UNSTABLE_PORT_RANGE 100 + + fakeExtaddr.sin_port = htons(ntohs(fakeExtaddr.sin_port) - (UNSTABLE_PORT_RANGE / 2) + RSRandom::random_u32() % UNSTABLE_PORT_RANGE); + if (!mSimSymmetricNat) + { + mSimUnstableExt = false; + } + } +#endif + bool found = true; std::list::iterator it; for(it = mStunList.begin(); it != mStunList.end(); it++) @@ -788,7 +844,11 @@ bool UdpStunner::locked_recvdStun(const struct sockaddr_in &remote, const str (remote.sin_port == it->remote.sin_port)) { it->failCount = 0; +#ifdef UDPSTUN_ALLOW_LOCALNET + it->eaddr = fakeExtaddr; +#else it->eaddr = extaddr; +#endif it->response = true; found = true; diff --git a/libretroshare/src/tcponudp/udpstunner.h b/libretroshare/src/tcponudp/udpstunner.h index 274d75afa..297cffa30 100644 --- a/libretroshare/src/tcponudp/udpstunner.h +++ b/libretroshare/src/tcponudp/udpstunner.h @@ -84,10 +84,12 @@ virtual ~UdpStunner() { return; } #ifdef UDPSTUN_ALLOW_LOCALNET // For Local Testing Mode. void SetAcceptLocalNet(); + void SimExclusiveNat(); + void SimSymmetricNat(); #endif -int setExclusiveMode(); /* returns seconds since last send/recv */ -int cancelExclusiveMode(); +int grabExclusiveMode(); /* returns seconds since last send/recv */ +int releaseExclusiveMode(); void setTargetStunPeriod(int32_t sec_per_stun); @@ -142,6 +144,10 @@ bool locked_checkExternalAddress(); #ifdef UDPSTUN_ALLOW_LOCALNET // For Local Testing Mode. bool mAcceptLocalNet; + bool mSimUnstableExt; + bool mSimExclusiveNat; + bool mSimSymmetricNat; + #endif bool mPassiveStunMode; @@ -150,6 +156,7 @@ bool locked_checkExternalAddress(); bool mExclusiveMode; /* when this is switched on, the stunner stays silent (and extAddr is maintained) */ time_t mExclusiveModeTS; + }; /* generic stun functions */