Reworking of networking code to enable Net Restart.

* Stun code now runs continually - to check external network state.
  * Udpsorter controls DHT stun is on/off. (via p3ConnectMgr)
  * added code to enable threads to join/restart 
  * enabled NetRestart for UDP and TCP.
  * tweaked networking code for faster startup (now ~30 seconds - can still be improved).
  * tweaked debug messages for testing networking
  * Added test for checking external IP address determination.



git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@1492 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2009-08-04 23:22:44 +00:00
parent d5581629ef
commit 2bf94b909a
22 changed files with 774 additions and 81 deletions

View file

@ -20,7 +20,7 @@ UDP_OBJ = pqissludp.o
OTHER_OBJ = p3notify.o
TESTOBJ = net_test.o dht_test.o net_test1.o
TESTOBJ = net_test.o dht_test.o net_test1.o
#conn_test.o
TESTS = net_test dht_test net_test1

View file

@ -57,8 +57,6 @@
#include <iostream>
#include <sstream>
#define AUTHGPG_DEBUG 1
/* Turn a set of parameters into a string */
static std::string setKeyPairParams(bool useRsa, unsigned int blen,

View file

@ -53,7 +53,6 @@ static int verify_x509_callback(int preverify_ok, X509_STORE_CTX *ctx);
/***********
** #define AUTHSSL_DEBUG 1
**********/
#define AUTHSSL_DEBUG 1
#ifdef PQI_USE_SSLONLY

View file

@ -57,6 +57,7 @@ const uint32_t MAX_UPNP_INIT = 10; /* seconds UPnP timeout */
/****
* #define CONN_DEBUG 1
***/
#define CONN_DEBUG 1
/****
* #define P3CONNMGR_NO_TCP_CONNECTIONS 1
***/
@ -104,6 +105,22 @@ peerConnectState::peerConnectState()
return;
}
std::string textPeerConnectState(peerConnectState &state)
{
std::ostringstream out;
out << "Id: " << state.id << std::endl;
out << "NetMode: " << state.netMode << std::endl;
out << "VisState: " << state.visState << std::endl;
out << "laddr: " << inet_ntoa(state.localaddr.sin_addr)
<< ":" << ntohs(state.localaddr.sin_port) << std::endl;
out << "eaddr: " << inet_ntoa(state.serveraddr.sin_addr)
<< ":" << ntohs(state.serveraddr.sin_port) << std::endl;
std::string output = out.str();
return output;
}
p3ConnectMgr::p3ConnectMgr(p3AuthMgr *am)
:p3Config(CONFIG_TYPE_PEERS),
@ -246,6 +263,62 @@ void p3ConnectMgr::setOwnNetConfig(uint32_t netMode, uint32_t visState)
*
*/
/* Called to reseet the whole network stack. this call is
* triggered by udp stun address tracking.
*
* must:
* - reset UPnP and DHT.
* -
*/
void p3ConnectMgr::netReset()
{
std::cerr << "p3ConnectMgr::netReset()" << std::endl;
std::cerr << "p3ConnectMgr::netReset() shutdown" << std::endl;
shutdown(); /* blocking shutdown call */
std::cerr << "p3ConnectMgr::netReset() reset NetStatus" << std::endl;
{
RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/
mNetStatus = RS_NET_UNKNOWN;
}
std::cerr << "p3ConnectMgr::netReset() checkNetAddress" << std::endl;
/* check Network Address */
checkNetAddress();
/* reset udp network - handled by tou_init! */
/* reset tcp network - if necessary */
{
/* NOTE: nNetListeners should be protected via the Mutex.
* HOWEVER, as we NEVER change this list - once its setup
* we can get away without it - and assume its constant.
*
* NB: (*it)->reset_listener must be out of the mutex,
* as it calls back to p3ConnMgr.
*/
std::cerr << "p3ConnectMgr::netReset() resetting listeners" << std::endl;
std::list<pqiNetListener *>::const_iterator it;
for(it = mNetListeners.begin(); it != mNetListeners.end(); it++)
{
std::cerr << "p3ConnectMgr::netReset() reset listener" << std::endl;
(*it)->reset_listener();
}
}
std::cerr << "p3ConnectMgr::netReset() done" << std::endl;
}
/* to allow resets of network stuff */
void p3ConnectMgr::addNetListener(pqiNetListener *listener)
{
RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/
mNetListeners.push_back(listener);
}
void p3ConnectMgr::netStatusReset()
{
netFlagOk = true;
@ -284,6 +357,7 @@ void p3ConnectMgr::netStartup()
std::cerr << "p3ConnectMgr::netStartup() tou_stunkeepalive() enabled" << std::endl;
#endif
tou_stunkeepalive(1);
mStunMoreRequired = true;
ownState.netMode &= ~(RS_NET_MODE_ACTUAL);
@ -293,12 +367,6 @@ void p3ConnectMgr::netStartup()
case RS_NET_MODE_TRY_EXT: /* v similar to UDP */
ownState.netMode |= RS_NET_MODE_EXT;
mNetStatus = RS_NET_UDP_SETUP;
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::netStartup() disabling stunkeepalive() cos EXT" << std::endl;
#endif
tou_stunkeepalive(0);
mStunMoreRequired = false; /* only need to validate address (EXT) */
break;
case RS_NET_MODE_TRY_UDP:
@ -552,10 +620,6 @@ void p3ConnectMgr::netUpnpCheck()
/* UPnP Failed us! */
mUpnpAddrValid = false;
mNetStatus = RS_NET_UDP_SETUP;
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::netUpnpCheck() enabling stunkeepalive() cos UDP" << std::endl;
#endif
tou_stunkeepalive(1);
connMtx.unlock(); /* UNLOCK MUTEX */
}
@ -577,11 +641,6 @@ void p3ConnectMgr::netUpnpCheck()
mNetStatus = RS_NET_UDP_SETUP;
/* Fix netMode & Clear others! */
ownState.netMode = RS_NET_MODE_TRY_UPNP | RS_NET_MODE_UPNP;
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::netUpnpCheck() disabling stunkeepalive() cos uPnP" << std::endl;
#endif
tou_stunkeepalive(0);
mStunMoreRequired = false; /* only need to validate address (UPNP) */
connMtx.unlock(); /* UNLOCK MUTEX */
}
@ -645,8 +704,6 @@ void p3ConnectMgr::netUdpCheck()
#endif
ownState.netMode &= ~(RS_NET_MODE_ACTUAL);
ownState.netMode |= RS_NET_MODE_UNREACHABLE;
tou_stunkeepalive(0);
mStunMoreRequired = false; /* no point -> unreachable (EXT) */
/* send a system warning message */
pqiNotify *notify = getPqiNotify();
@ -882,44 +939,137 @@ void p3ConnectMgr::stunInit()
mStunMoreRequired = true;
}
/* This is continually called
*
* checks whether the ext address is consistent
*
* checks if UDP needs more stun peers - or not
* The status is passed onto the DHT.
*
*/
bool p3ConnectMgr::stunCheck()
{
/* check if we've got a Stun result */
bool stunOk = false;
#ifdef CONN_DEBUG
//std::cerr << "p3ConnectMgr::stunCheck()" << std::endl;
std::cerr << "p3ConnectMgr::stunCheck()" << std::endl;
#endif
{
RsStackMutex stack(connMtx); /********* LOCK STACK MUTEX ******/
/* check udp address stability */
bool netDone = false;
bool doNetReset = false;
/* if DONE -> return */
if (mStunStatus == RS_STUN_DONE)
{
return true;
RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/
mStunStatus = RS_STUN_DHT;
netDone = (mNetStatus == RS_NET_DONE);
}
if (mStunFound >= RS_STUN_FOUND_MIN)
struct sockaddr_in raddr;
socklen_t rlen = sizeof(raddr);
struct sockaddr_in eaddr;
socklen_t elen = sizeof(eaddr);
uint8_t stable;
uint32_t failCount;
time_t lastSent;
time_t now = time(NULL);
if (netDone)
{
mStunMoreRequired = false;
#ifdef CONN_DEBUG
std::cerr << "NetSetupDone: Checking if network is same" << std::endl;
#endif
if (0 < tou_extaddr((struct sockaddr *) &raddr, &rlen, &stable))
{
RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/
if ((mStunExtAddr.sin_addr.s_addr != raddr.sin_addr.s_addr) ||
(mStunAddrStable != stable))
{
#ifdef CONN_DEBUG
std::cerr << "Ext Address Changed -> netReset" << std::endl;
#endif
doNetReset = true;
}
else
{
#ifdef CONN_DEBUG
std::cerr << "Ext Address Same: ok!" << std::endl;
#endif
}
}
else
{
#ifdef CONN_DEBUG
std::cerr << "No Ext Address -> netReset" << std::endl;
#endif
doNetReset = true;
}
}
stunOk = (!mStunMoreRequired);
}
if (udpExtAddressCheck() && (stunOk))
if (doNetReset)
{
/* set external UDP address */
netAssistStun(false);
#ifdef CONN_DEBUG
std::cerr << "Resetting Network" << std::endl;
#endif
netReset();
}
int i = 0;
for(i = 0; tou_getstunpeer(i, (struct sockaddr *) &raddr, &rlen,
(struct sockaddr *) &eaddr, &elen,
&failCount, &lastSent); i++)
{
std::cerr << "STUN PEERS: ";
std::cerr << " raddr: " << inet_ntoa(raddr.sin_addr) << ":" << ntohs(raddr.sin_port);
std::cerr << " eaddr: " << inet_ntoa(eaddr.sin_addr) << ":" << ntohs(eaddr.sin_port);
if (lastSent)
{
std::cerr << " failCount: " << failCount << " lastSent: " << now-lastSent;
}
else
{
std::cerr << " Unused ";
}
std::cerr << std::endl;
}
/* pass on udp status to dht */
if (tou_needstunpeers())
{
RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/
mStunStatus = RS_STUN_DONE;
if (!mStunMoreRequired)
{
#ifdef CONN_DEBUG
std::cerr << "Telling DHT More Stun Required" << std::endl;
#endif
return true;
netAssistStun(true);
mStunMoreRequired = true;
}
}
return false;
else
{
RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/
if (mStunMoreRequired)
{
#ifdef CONN_DEBUG
std::cerr << "Telling DHT No More Stun Required" << std::endl;
#endif
netAssistStun(false);
mStunMoreRequired = false;
}
}
return true;
}
void p3ConnectMgr::stunStatus(std::string id, struct sockaddr_in raddr, uint32_t type, uint32_t flags)

View file

@ -162,6 +162,8 @@ class peerConnectState
};
std::string textPeerConnectState(peerConnectState &state);
class p3ConnectMgr: public pqiConnectCb, public p3Config
{
@ -177,6 +179,8 @@ void addNetAssistFirewall(uint32_t type, pqiNetAssistFirewall *);
bool checkNetAddress(); /* check our address is sensible */
void addNetListener(pqiNetListener *listener);
/*************** External Control ****************/
bool shutdown(); /* blocking shutdown call */
@ -273,6 +277,8 @@ virtual bool netAssistSetAddress( struct sockaddr_in &laddr,
/* Internal Functions */
void netReset();
void statusTick();
void netTick();
void netStartup();
@ -342,6 +348,8 @@ private:
RsMutex connMtx; /* protects below */
std::list<pqiNetListener *> mNetListeners;
time_t mNetInitTS;
uint32_t mNetStatus;

View file

@ -66,7 +66,7 @@ const int p3dhtzone = 3892;
#define DHT_DEFAULT_WAITTIME 1 /* Std sleep break period */
#define DHT_NUM_BOOTSTRAP_BINS 8
#define DHT_MIN_BOOTSTRAP_REQ_PERIOD 30
#define DHT_MIN_BOOTSTRAP_REQ_PERIOD 5
void printDhtPeerEntry(dhtPeerEntry *ent, std::ostream &out);
@ -1027,20 +1027,21 @@ int p3DhtMgr::checkStunState()
}
else if (mDhtState == DHT_STATE_FIND_STUN)
{
/* if we run out of stun peers -> get some more */
if (stunIds.size() < 1)
{
}
/* if we run out of stun peers -> get some more */
if (stunIds.size() < 1)
{
#ifdef DHT_DEBUG
std::cerr << "WARNING: out of Stun Peers - switching to Active Now" << std::endl;
std::cerr << "WARNING: out of Stun Peers - Fetching some more" << std::endl;
#endif
mDhtState = DHT_STATE_ACTIVE;
dhtMtx.unlock(); /* UNLOCK MUTEX */
mDhtState = DHT_STATE_ACTIVE;
dhtMtx.unlock(); /* UNLOCK MUTEX */
/* this is a locked function */
getDhtBootstrapList();
/* this is a locked function */
getDhtBootstrapList();
dhtMtx.lock(); /* LOCK MUTEX */
}
dhtMtx.lock(); /* LOCK MUTEX */
}
dhtMtx.unlock(); /* UNLOCK MUTEX */

View file

@ -134,5 +134,15 @@ virtual void peerConnectRequest(std::string id,
virtual void stunStatus(std::string id, struct sockaddr_in raddr, uint32_t type, uint32_t flags);
};
/* network listener interface - used to reset network addresses */
class pqiNetListener
{
public:
virtual int reset_listener() = 0;
};
#endif // PQI_MONITOR_H

View file

@ -186,6 +186,8 @@ int pqipersongrp::init_listener()
int pqipersongrp::restart_listener()
{
std::cerr << "pqipersongrp::restart_listener()" << std::endl;
// stop it,
// change the address.
// restart.
@ -197,6 +199,8 @@ int pqipersongrp::restart_listener()
if (haveListener)
{
std::cerr << "pqipersongrp::restart_listener() haveListener" << std::endl;
peerConnectState state;
mConnMgr->getOwnNetStatus(state);
@ -205,6 +209,9 @@ int pqipersongrp::restart_listener()
pqil -> resetlisten();
pqil -> setListenAddr(state.localaddr);
pqil -> setuplisten();
std::cerr << "pqipersongrp::restart_listener() done!" << std::endl;
}
return 1;
}

View file

@ -46,13 +46,15 @@ const unsigned long PQIPERSON_NO_LISTENER = 0x0001;
const unsigned long PQIPERSON_ALL_BW_LIMITED = 0x0010;
class pqipersongrp: public pqihandler, public pqiMonitor, public p3ServiceServer
class pqipersongrp: public pqihandler, public pqiMonitor, public p3ServiceServer, public pqiNetListener
{
public:
pqipersongrp(SecurityPolicy *, unsigned long flags);
/*************************** Setup *************************/
/* pqilistener */
virtual int reset_listener() { return restart_listener(); }
int init_listener();
int restart_listener();

View file

@ -171,7 +171,27 @@ int pqissllistenbase::setuplisten()
out << "\tSetup Port: " << ntohs(laddr.sin_port);
pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out.str());
std::cerr << out.str() << std::endl;
}
/* added a call to REUSEADDR, so that we can re-open an existing socket
* when we restart_listener.
*/
{
int on = 1;
if (setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
{
std::ostringstream out;
out << "pqissllistenbase::setuplisten()";
out << " Cannot setsockopt SO_REUSEADDR!" << std::endl;
showSocketError(out);
pqioutput(PQL_ALERT, pqissllistenzone, out.str());
std::cerr << out.str() << std::endl;
exit(1);
}
}
if (0 != (err = bind(lsock, (struct sockaddr *) &laddr, sizeof(laddr))))
{
@ -180,6 +200,7 @@ int pqissllistenbase::setuplisten()
out << " Cannot Bind to Local Address!" << std::endl;
showSocketError(out);
pqioutput(PQL_ALERT, pqissllistenzone, out.str());
std::cerr << out.str() << std::endl;
exit(1);
return -1;
@ -198,6 +219,7 @@ int pqissllistenbase::setuplisten()
out << err << std::endl;
showSocketError(out);
pqioutput(PQL_ALERT, pqissllistenzone, out.str());
std::cerr << out.str() << std::endl;
exit(1);
return -1;