Addition of a new Automatic DHT Bootstrap system. This will need to be tweaked as the numbers of users increase.

* hashed keys are posted to specific DHT entries, to create a series of bootstrap lists.
 * these are fetched as needed to bootstrap new clients.
 * Modified Bootstrap monitor program.

Created a minimal backup bootstrap list (temporary)
Added "-e" option to commandline to force 'external port' mode
Bugfix for multiple connection methods, could kill an active connection.



git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@397 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2008-03-21 19:06:34 +00:00
parent 22aff3aa60
commit 247e583a35
8 changed files with 783 additions and 104 deletions

View file

@ -2781,19 +2781,6 @@ bool p3ConnectMgr::addBootstrapStunPeers()
id = "8ad7c08e7778e0289de04843bf57a6ae";
stunCollect(RsUtil::HashId(id, false), dummyaddr, flags);
// Donated by public.
id = "8523688347027884059506005618ae74"; /* tm */
stunCollect(RsUtil::HashId(id, false), dummyaddr, flags);
id = "1bd15b320269fa1561ceb1162fd042f0"; /* cp */
stunCollect(RsUtil::HashId(id, false), dummyaddr, flags);
id = "2cf2361f2afcd6d871159714bbbfc502"; /* cc */
stunCollect(RsUtil::HashId(id, false), dummyaddr, flags);
id = "128646cdf761970376a62c52c372c931"; /* rf */
stunCollect(RsUtil::HashId(id, false), dummyaddr, flags);
return true;
}

View file

@ -36,6 +36,8 @@
* #define P3DHTMGR_USE_LOCAL_UDP_CONN 1 // For Testing only
****/
#define DHT_DEBUG 1
/**** DHT State Variables ****
* TODO:
* (1) notify call in.
@ -57,9 +59,12 @@
#define DHT_RESTART_PERIOD 300 /* 5 min */
#define DHT_DEFAULT_PERIOD 300 /* Default period if no work to do */
#define DHT_MIN_PERIOD 1 /* to ensure we don't get too many requests */
#define DHT_SHORT_PERIOD 10 /* a short period */
#define DHT_DEFAULT_WAITTIME 1 /* Std sleep break period */
#define DHT_NUM_BOOTSTRAP_BINS 1
#define DHT_MIN_BOOTSTRAP_REQ_PERIOD 30
void printDhtPeerEntry(dhtPeerEntry *ent, std::ostream &out);
@ -102,6 +107,9 @@ p3DhtMgr::p3DhtMgr(std::string id, pqiConnectCb *cb)
mDhtOn = false;
mDhtState = DHT_STATE_OFF;
mBootstrapAllowed = true;
mLastBootstrapListTS = 0;
dhtMtx.unlock(); /* UNLOCK MUTEX */
return;
@ -139,6 +147,26 @@ bool p3DhtMgr::getDhtActive()
return act;
}
void p3DhtMgr::setBootstrapAllowed(bool on)
{
dhtMtx.lock(); /* LOCK MUTEX */
mBootstrapAllowed = on;
dhtMtx.unlock(); /* UNLOCK MUTEX */
}
bool p3DhtMgr::getBootstrapAllowed()
{
dhtMtx.lock(); /* LOCK MUTEX */
bool on = mBootstrapAllowed;
dhtMtx.unlock(); /* UNLOCK MUTEX */
return on;
}
/******************************** PEER MANAGEMENT **********************************
*
*/
@ -391,7 +419,6 @@ void p3DhtMgr::run()
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::run() state = ACTIVE -> do stuff" << std::endl;
#endif
doStun();
period = checkOwnDHTKeys();
#ifdef DHT_DEBUG
@ -409,6 +436,15 @@ void p3DhtMgr::run()
period = tmpperiod;
if (tmpperiod2 < period)
period = tmpperiod2;
/* finally we need to keep stun going */
if (checkStunState_Active())
{
/* still more stun to do */
period = DHT_SHORT_PERIOD;
doStun();
}
}
break;
default:
@ -528,6 +564,21 @@ int p3DhtMgr::checkOwnDHTKeys()
dhtMtx.unlock(); /* UNLOCK MUTEX */
}
/* dhtBootstrap -> if allowed and EXT port */
if (peer.type & RS_NET_CONN_TCP_EXTERNAL)
{
dhtMtx.lock(); /* LOCK MUTEX */
bool doBootstrapPub = mBootstrapAllowed;
dhtMtx.unlock(); /* UNLOCK MUTEX */
if (doBootstrapPub)
{
dhtBootstrap(randomBootstrapId(), peer.hash1, "");
}
}
/* restart immediately */
repubPeriod = DHT_MIN_PERIOD;
return repubPeriod;
@ -868,11 +919,17 @@ int p3DhtMgr::checkStunState()
}
else if (mDhtState == DHT_STATE_FIND_STUN)
{
/* if we run out of stun peers -> just go to active */
/* if we run out of stun peers -> get some more */
if (stunIds.size() < 1)
{
std::cerr << "WARNING: out of Stun Peers - without getting id" << std::endl;
std::cerr << "WARNING: out of Stun Peers - switching to Active Now" << std::endl;
mDhtState = DHT_STATE_ACTIVE;
dhtMtx.unlock(); /* UNLOCK MUTEX */
/* this is a locked function */
getDhtBootstrapList();
dhtMtx.lock(); /* LOCK MUTEX */
}
}
@ -880,6 +937,103 @@ int p3DhtMgr::checkStunState()
return 1;
}
int p3DhtMgr::checkStunState_Active()
{
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::checkStunState_Active()" << std::endl;
#endif
dhtMtx.lock(); /* LOCK MUTEX */
bool stunReq = mStunRequired;
bool moreIds = ((mStunRequired) && (stunIds.size() < 1));
dhtMtx.unlock(); /* UNLOCK MUTEX */
if (moreIds)
/* if we run out of stun peers -> get some more */
{
std::cerr << "WARNING: out of Stun Peers - getting more" << std::endl;
getDhtBootstrapList();
}
return stunReq;
}
bool p3DhtMgr::getDhtBootstrapList()
{
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::getDHTBootstrapList()" << std::endl;
#endif
dhtMtx.lock(); /* LOCK MUTEX */
time_t now = time(NULL);
if (now - mLastBootstrapListTS < DHT_MIN_BOOTSTRAP_REQ_PERIOD)
{
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::getDHTBootstrapList() Waiting: ";
std::cerr << DHT_MIN_BOOTSTRAP_REQ_PERIOD-(now-mLastBootstrapListTS);
std::cerr << " secs" << std::endl;
#endif
dhtMtx.unlock(); /* UNLOCK MUTEX */
return false;
}
mLastBootstrapListTS = now;
std::string bootId = randomBootstrapId();
dhtMtx.unlock(); /* UNLOCK MUTEX */
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::getDHTBootstrapList() bootId: 0x";
std::cerr << RsUtil::BinToHex(bootId) << std::endl;
#endif
dhtSearch(bootId, DHT_MODE_SEARCH);
return true;
}
std::string p3DhtMgr::BootstrapId(uint32_t bin)
{
/* generate these from an equation! (makes it easy)
* Make sure that NUM_BOOTSTRAP_BINS doesn't affect ids
*/
std::ostringstream genId;
genId << "BootstrapId";
uint32_t id = (bin % DHT_NUM_BOOTSTRAP_BINS) * 1234;
genId << id;
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::BootstrapId() generatedId: ";
std::cerr << genId.str() << std::endl;
#endif
/* now hash this to create a bootstrap Bin Id */
std::string bootId = RsUtil::HashId(genId.str(), false);
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::BootstrapId() bootId: 0x";
std::cerr << RsUtil::BinToHex(bootId) << std::endl;
#endif
return bootId;
}
std::string p3DhtMgr::randomBootstrapId()
{
uint32_t rnd = DHT_NUM_BOOTSTRAP_BINS * (rand() / (RAND_MAX + 1.0));
return BootstrapId(rnd);
}
void p3DhtMgr::checkDHTStatus()
{
dhtMtx.lock(); /* LOCK MUTEX */
@ -1157,7 +1311,17 @@ bool p3DhtMgr::dhtSearch(std::string idhash, uint32_t mode)
}
bool p3DhtMgr::dhtBootstrap(std::string storehash, std::string ownIdHash, std::string sign)
{
std::cerr << "p3DhtMgr::dhtBootstrap()" << std::endl;
std::ostringstream value;
value << "RSDHT:" << std::setw(2) << std::setfill('0') << DHT_MODE_BOOTSTRAP << ":";
value << ownIdHash;
/* call to the real DHT */
return publishDHT(storehash, value.str(), DHT_TTL_BOOTSTRAP);
}
/****************************** DHT FEEDBACK INTERFACE *********************************
@ -1280,6 +1444,23 @@ bool p3DhtMgr::resultDHT(std::string key, std::string value)
break;
}
case DHT_MODE_BOOTSTRAP:
{
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::resultDHT() BOOTSTRAP msg" << std::endl;
#endif
/* get the hash */
std::string bootId = value.substr(loc);
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::resultDHT() BOOTSTRAP msg, IdHash:->" << RsUtil::BinToHex(bootId) << "<-" << std::endl;
#endif
/* call out */
dhtResultBootstrap(bootId);
break;
}
default:
return false;
@ -1292,6 +1473,37 @@ bool p3DhtMgr::resultDHT(std::string key, std::string value)
bool p3DhtMgr::dhtResultBootstrap(std::string idhash)
{
RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::dhtResultBootstrap() from idhash: ";
std::cerr << RsUtil::BinToHex(idhash) << std::endl;
#endif
/* Temp - to avoid duplication during testing */
if (stunIds.end() == std::find(stunIds.begin(), stunIds.end(), idhash))
{
stunIds.push_back(idhash);
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::dhtResultBootstrap() adding to StunList";
std::cerr << std::endl;
#endif
}
else
{
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::dhtResultBootstrap() DUPLICATE not adding to List";
std::cerr << std::endl;
#endif
}
return true;
}
bool p3DhtMgr::dhtResultNotify(std::string idhash)

View file

@ -55,7 +55,7 @@
#define DHT_MODE_SEARCH 1
#define DHT_MODE_PUBLISH 1
#define DHT_MODE_NOTIFY 2
#define DHT_MODE_BOOTSTRAP 3
/* TIMEOUTS: Reference Values are set here... */
@ -68,9 +68,7 @@
/* TTLs for DHTs posts */
#define DHT_TTL_PUBLISH (DHT_PUBLISH_PERIOD + 120) // for a little overlap.
#define DHT_TTL_NOTIFY (DHT_NOTIFY_PERIOD + 60) // for time to find it...
#define DHT_TTL_BOOTSTRAP (DHT_PUBLISH_PERIOD) // To start with.
class dhtPeerEntry
{
@ -107,6 +105,9 @@ void setDhtOn(bool on);
bool getDhtOn();
bool getDhtActive();
void setBootstrapAllowed(bool on);
bool getBootstrapAllowed();
/* set key data */
bool setExternalInterface(struct sockaddr_in laddr,
struct sockaddr_in raddr, uint32_t type);
@ -139,6 +140,8 @@ virtual bool dhtResultSearch(std::string id,
struct sockaddr_in &laddr, struct sockaddr_in &raddr,
uint32_t type, std::string sign);
virtual bool dhtResultBootstrap(std::string idhash);
protected:
/* can block briefly (called only from thread) */
@ -149,8 +152,13 @@ virtual bool dhtPublish(std::string id,
virtual bool dhtNotify(std::string peerid, std::string ownId,
std::string sign);
virtual bool dhtSearch(std::string id, uint32_t mode);
virtual bool dhtBootstrap(std::string storehash, std::string ownIdHash,
std::string sign); /* to publish bootstrap */
/********** Actual DHT Work Functions ************************
* These involve a very simple LOW-LEVEL interface ...
@ -191,6 +199,7 @@ virtual void run();
/* search scheduling */
void checkDHTStatus();
int checkStunState();
int checkStunState_Active(); /* when in active state */
int doStun();
int checkPeerDHTKeys();
int checkOwnDHTKeys();
@ -198,6 +207,10 @@ int checkNotifyDHT();
void clearDhtData();
/* IP Bootstrap */
bool getDhtBootstrapList();
std::string BootstrapId(uint32_t bin);
std::string randomBootstrapId();
/* other feedback through callback */
pqiConnectCb *connCb;
@ -218,6 +231,8 @@ void clearDhtData();
uint32_t mDhtState;
time_t mDhtActiveTS;
bool mBootstrapAllowed;
time_t mLastBootstrapListTS;
};

View file

@ -216,9 +216,6 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState)
case CONNECT_FIREWALLED:
case CONNECT_FAILED:
/* notify up */
if (pqipg)
pqipg->notifyConnect(PeerId(), false);
if (active)
{
@ -228,13 +225,13 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState)
"CONNECT_FAILED->marking so!");
active = false;
activepqi = NULL;
return 1;
}
else
{
pqioutput(PQL_WARNING, pqipersonzone,
"CONNECT_FAIL+not activepqi->strange!");
// something strange!
// probably UDP connect has failed,
// TCP connection has been made since attempt started.
return -1;
}
}
@ -242,10 +239,14 @@ int pqiperson::notifyEvent(NetInterface *ni, int newState)
{
pqioutput(PQL_WARNING, pqipersonzone,
"CONNECT_FAILED+NOT active -> try connect again");
//connectattempt(pqi);
return 1;
}
/* notify up (But not if we are actually active: rtn -1 case above) */
if (pqipg)
pqipg->notifyConnect(PeerId(), false);
return 1;
break;
default:
break;
@ -361,6 +362,7 @@ int pqiperson::connect(uint32_t type, struct sockaddr_in raddr, uint32_t delay,
}
/* set the parameters */
(it->second)->reset();
(it->second)->connect_parameter(NET_PARAM_CONNECT_DELAY, delay);
(it->second)->connect_parameter(NET_PARAM_CONNECT_PERIOD, period);
(it->second)->connect(raddr);