Merging branches/v0.5-peernet/libbitdht (Merging r4237 through r4353 into '.')

There are many significant improvements to the DHT here. 
See commit logs on v0.5-peernet branch for details.

This is not the final merge, but brings over the majority of expected v0.5-peernet/libbitdht changes 




git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@4354 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2011-06-29 10:46:11 +00:00
parent f517442989
commit fff40eceac
40 changed files with 6843 additions and 746 deletions

View file

@ -37,7 +37,7 @@
**/
#define EXPECTED_REPLY 20
#define EXPECTED_REPLY 10 // Speed up queries
#define QUERY_IDLE_RETRY_PEER_PERIOD 300 // 5min = (mFns->bdNodesPerBucket() * 30)
@ -65,6 +65,7 @@ bdQuery::bdQuery(const bdNodeId *id, std::list<bdId> &startList, uint32_t queryF
bdPeer peer;
peer.mLastSendTime = 0;
peer.mLastRecvTime = 0;
peer.mPeerFlags = 0;
peer.mFoundTime = now;
peer.mPeerId = *it;
@ -81,8 +82,10 @@ bdQuery::bdQuery(const bdNodeId *id, std::list<bdId> &startList, uint32_t queryF
mQueryFlags = queryFlags;
mQueryTS = now;
mSearchTime = 0;
mClosestListSize = (int) (1.5 * mFns->bdNodesPerBucket());
mQueryIdlePeerRetryPeriod = QUERY_IDLE_RETRY_PEER_PERIOD;
mRequiredPeerFlags = BITDHT_PEER_STATUS_DHT_ENGINE_VERSION; // XXX to update later.
/* setup the limit of the search
* by default it is setup to 000000 = exact match
@ -126,7 +129,8 @@ int bdQuery::nextQuery(bdId &id, bdNodeId &targetNodeId)
bool notFinished = false;
std::multimap<bdMetric, bdPeer>::iterator it;
for(it = mClosest.begin(); it != mClosest.end(); it++)
int i = 0;
for(it = mClosest.begin(); it != mClosest.end(); it++, i++)
{
bool queryPeer = false;
@ -156,11 +160,15 @@ int bdQuery::nextQuery(bdId &id, bdNodeId &targetNodeId)
/* expecting every peer to be up-to-date is too hard...
* enough just to have received lists from each
* - replacement policy will still work.
*
* Need to wait at least EXPECTED_REPLY, to make sure their answers are pinged
*/
if (it->second.mLastRecvTime == 0)
if (((it->second.mLastRecvTime == 0) || (now - it->second.mLastRecvTime < EXPECTED_REPLY)) &&
(i < mFns->bdNodesPerBucket()))
{
#ifdef DEBUG_QUERY
fprintf(stderr, "NextQuery() Never Received: notFinished = true: ");
fprintf(stderr, "NextQuery() Never Received @Idx(%d) notFinished = true: ", i);
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
std::cerr << std::endl;
#endif
@ -241,7 +249,7 @@ int bdQuery::nextQuery(bdId &id, bdNodeId &targetNodeId)
{
mState = BITDHT_QUERY_SUCCESS;
}
else if ((mPotentialClosest.begin()->second).mPeerId.id == mId)
else if ((mPotentialPeers.begin()->second).mPeerId.id == mId)
{
mState = BITDHT_QUERY_PEER_UNREACHABLE;
}
@ -257,7 +265,7 @@ int bdQuery::nextQuery(bdId &id, bdNodeId &targetNodeId)
return 0;
}
int bdQuery::addPeer(const bdId *id, uint32_t mode)
int bdQuery::addClosestPeer(const bdId *id, uint32_t mode)
{
bdMetric dist;
time_t ts = time(NULL);
@ -276,7 +284,9 @@ int bdQuery::addPeer(const bdId *id, uint32_t mode)
int i = 0;
int actualCloser = 0;
int toDrop = 0;
for(it = mClosest.begin(); it != sit; it++, i++, actualCloser++)
// switched end condition to upper_bound to provide stability for NATTED peers.
// we will favour the older entries!
for(it = mClosest.begin(); it != eit; it++, i++, actualCloser++)
{
time_t sendts = ts - it->second.mLastSendTime;
bool hasSent = (it->second.mLastSendTime != 0);
@ -292,7 +302,8 @@ int bdQuery::addPeer(const bdId *id, uint32_t mode)
fprintf(stderr, "Searching.... %di = %d - %d peers closer than this one\n", i, actualCloser, toDrop);
#endif
if (i > mFns->bdNodesPerBucket() - 1)
if (i > mClosestListSize - 1)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Distance to far... dropping\n");
@ -304,11 +315,20 @@ int bdQuery::addPeer(const bdId *id, uint32_t mode)
for(it = sit; it != eit; it++, i++)
{
/* full id check */
if (it->second.mPeerId == *id)
if (mFns->bdSimilarId(id, &(it->second.mPeerId)))
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Peer Already here!\n");
#endif
if (mode)
{
/* also update port from incoming id, as we have definitely recved from it */
if (mFns->bdUpdateSimilarId(&(it->second.mPeerId), id))
{
/* updated it... must be Unstable */
it->second.mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE;
}
}
if (mode & BITDHT_PEER_STATUS_RECV_NODES)
{
/* only update recvTime if sendTime > checkTime.... (then its our query) */
@ -316,6 +336,7 @@ int bdQuery::addPeer(const bdId *id, uint32_t mode)
fprintf(stderr, "Updating LastRecvTime\n");
#endif
it->second.mLastRecvTime = ts;
it->second.mPeerFlags |= mode;
}
return 1;
}
@ -353,7 +374,7 @@ int bdQuery::addPeer(const bdId *id, uint32_t mode)
}
/* trim it back */
while(mClosest.size() > (uint32_t) (mFns->bdNodesPerBucket() - 1))
while(mClosest.size() > (uint32_t) (mClosestListSize - 1))
{
std::multimap<bdMetric, bdPeer>::iterator it;
it = mClosest.end();
@ -379,6 +400,7 @@ int bdQuery::addPeer(const bdId *id, uint32_t mode)
/* add it in */
bdPeer peer;
peer.mPeerId = *id;
peer.mPeerFlags = mode;
peer.mLastSendTime = 0;
peer.mLastRecvTime = 0;
peer.mFoundTime = ts;
@ -393,17 +415,71 @@ int bdQuery::addPeer(const bdId *id, uint32_t mode)
}
/* we also want to track unreachable node ... this allows us
* to detect if peer are online - but uncontactible by dht.
*
* simple list of closest.
/*******************************************************************************************
********************************* Add Peer Interface *************************************
*******************************************************************************************/
/**** These functions are called by bdNode to add peers to the query
* They add/update the three sets of lists.
*
* int bdQuery::addPeer(const bdId *id, uint32_t mode)
* Proper message from a peer.
*
* int bdQuery::addPotentialPeer(const bdId *id, const bdId *src, uint32_t srcmode)
* This returns 1 if worthy of pinging, 0 if to ignore.
*/
int bdQuery::addPotentialPeer(const bdId *id, uint32_t mode)
#define PEER_MESSAGE 0
#define FIND_NODE_RESPONSE 1
int bdQuery::addPeer(const bdId *id, uint32_t mode)
{
addClosestPeer(id, mode);
updatePotentialPeer(id, mode, PEER_MESSAGE);
updateProxy(id, mode);
return 1;
}
int bdQuery::addPotentialPeer(const bdId *id, const bdId *src, uint32_t srcmode)
{
// is it a Potential Proxy? Always Check This.
addProxy(id, src, srcmode);
int worthy = worthyPotentialPeer(id);
int shouldPing = 0;
if (worthy)
{
shouldPing = updatePotentialPeer(id, 0, FIND_NODE_RESPONSE);
}
return shouldPing;
}
/*******************************************************************************************
********************************* Closest Peer ********************************************
*******************************************************************************************/
/*******************************************************************************************
******************************** Potential Peer *******************************************
*******************************************************************************************/
/*******
* Potential Peers are a list of the closest answers to our queries.
* Lots of these peers will not be reachable.... so will only exist in this list.
* They will also never have there PeerFlags set ;(
*
*/
/*** utility functions ***/
int bdQuery::worthyPotentialPeer(const bdId *id)
{
bdMetric dist;
time_t ts = time(NULL);
mFns->bdDistance(&mId, &(id->id), &dist);
#ifdef DEBUG_QUERY
@ -412,7 +488,7 @@ int bdQuery::addPotentialPeer(const bdId *id, uint32_t mode)
fprintf(stderr, ", %u)\n", mode);
#endif
/* first we check if this is a worthy potential peer....
/* we check if this is a worthy potential peer....
* if it is already in mClosest -> false. old peer.
* if it is > mClosest.rbegin() -> false. too far way.
*/
@ -422,129 +498,399 @@ int bdQuery::addPotentialPeer(const bdId *id, uint32_t mode)
sit = mClosest.lower_bound(dist);
eit = mClosest.upper_bound(dist);
for(it = sit; it != eit; it++)
{
if (it->second.mPeerId == *id)
{
/* already there */
retval = 0;
#ifdef DEBUG_QUERY
fprintf(stderr, "Peer already in mClosest\n");
#endif
}
//empty loop.
}
/* check if outside range, & bucket is full */
if ((sit == mClosest.end()) && (mClosest.size() >= mFns->bdNodesPerBucket()))
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Peer to far away for Potential\n");
#endif
retval = 0; /* too far way */
return 0; /* too far way */
}
/* return if false; */
if (!retval)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Flagging as Not a Potential Peer!\n");
#endif
return retval;
}
/* finally if a worthy & new peer -> add into potential closest
* and repeat existance tests with PotentialPeers
*/
sit = mPotentialClosest.lower_bound(dist);
eit = mPotentialClosest.upper_bound(dist);
int i = 0;
for(it = mPotentialClosest.begin(); it != sit; it++, i++)
for(it = sit; it != eit; it++)
{
//empty loop.
}
if (i > mFns->bdNodesPerBucket() - 1)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Distance to far... dropping\n");
fprintf(stderr, "Flagging as Potential Peer!\n");
#endif
/* outside the list - so we won't add to mPotentialClosest
* but inside mClosest still - so should still try it
*/
retval = 1;
return retval;
}
for(it = sit; it != eit; it++, i++)
{
if (it->second.mPeerId == *id)
if (mFns->bdSimilarId(id, &(it->second.mPeerId)))
{
/* this means its already been pinged */
// Not updating Full Peer Id here... as inspection function.
#ifdef DEBUG_QUERY
fprintf(stderr, "Peer Already here in mPotentialClosest!\n");
fprintf(stderr, "Peer already in mClosest\n");
#endif
if (mode & BITDHT_PEER_STATUS_RECV_NODES)
return 0;
}
}
return 1; /* either within mClosest Range (but not there!), or there aren't enough peers */
}
/*****
*
* mLastSendTime ... is the last FIND_NODE_RESPONSE that we returned 1. (indicating to PING).
* mLastRecvTime ... is the last time we received an updatei about/from them
*
* The update is dependent on the flags passed in the function call. (saves duplicate code).
*
*
* XXX IMPORTANT TO DECIDE WHAT IS RETURNED HERE.
* original algorithm return 0 if exists in potential peers, 1 if unknown.
* This is used to limit the number of pings to non-responding potentials.
*
* MUST think about this. Need to install HISTORY tracking again. to look at the statistics.
*
* It is important that the potential Peers list extends all the way back to == mClosest().end().
* Otherwise we end up with [TARGET] .... [ POTENTIAL ] ..... [ CLOSEST ] ......
* and the gap between POT and CLOSEST will get hammered with pings.
*
*/
#define MIN_PING_POTENTIAL_PERIOD 300
int bdQuery::updatePotentialPeer(const bdId *id, uint32_t mode, uint32_t addType)
{
bdMetric dist;
time_t now = time(NULL);
mFns->bdDistance(&mId, &(id->id), &dist);
std::multimap<bdMetric, bdPeer>::iterator it, sit, eit;
sit = mPotentialPeers.lower_bound(dist);
eit = mPotentialPeers.upper_bound(dist);
bool found = false;
for(it = sit; it != eit; it++)
{
if (mFns->bdSimilarId(id, &(it->second.mPeerId)))
{
found = true;
it->second.mPeerFlags |= mode;
it->second.mLastRecvTime = now;
if (addType == FIND_NODE_RESPONSE)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Updating LastRecvTime\n");
#endif
it->second.mLastRecvTime = ts;
// We could lose peers here by not updating port... but should be okay.
if (now - it->second.mLastSendTime > MIN_PING_POTENTIAL_PERIOD)
{
it->second.mLastSendTime = now;
return 1;
}
}
#ifdef DEBUG_QUERY
fprintf(stderr, "Flagging as Not a Potential Peer!\n");
#endif
retval = 0;
return retval;
else if (mode)
{
/* also update port from incoming id, as we have definitely recved from it */
if (mFns->bdUpdateSimilarId(&(it->second.mPeerId), id))
{
/* updated it... must be Unstable */
it->second.mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE;
}
}
return 0;
}
}
#ifdef DEBUG_QUERY
fprintf(stderr, "Peer not in Query\n");
#endif
// Removing this check - so that we can have varying length PotentialPeers.
// Peer will always be added, then probably removed straight away.
/* trim it back */
while(mPotentialClosest.size() > (uint32_t) (mFns->bdNodesPerBucket() - 1))
#if 0
/* check if outside range, & bucket is full */
if ((sit == mPotentialPeers.end()) && (mPotentialPeers.size() >= mFns->bdNodesPerBucket()))
{
std::multimap<bdMetric, bdPeer>::iterator it;
it = mPotentialClosest.end();
if(!mPotentialClosest.empty())
{
--it;
#ifdef DEBUG_QUERY
fprintf(stderr, "Removing Furthest Peer: ");
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
fprintf(stderr, "\n");
fprintf(stderr, "Peer to far away for Potential\n");
#endif
mPotentialClosest.erase(it);
}
return 0;
}
#ifdef DEBUG_QUERY
fprintf(stderr, "bdQuery::addPotentialPeer(): Closer Peer!: ");
mFns->bdPrintId(std::cerr, id);
fprintf(stderr, "\n");
#endif
/* add it in */
bdPeer peer;
peer.mPeerId = *id;
peer.mPeerFlags = mode;
peer.mFoundTime = now;
peer.mLastRecvTime = now;
peer.mLastSendTime = 0;
peer.mLastRecvTime = ts;
peer.mFoundTime = ts;
mPotentialClosest.insert(std::pair<bdMetric, bdPeer>(dist, peer));
if (addType == FIND_NODE_RESPONSE)
{
peer.mLastSendTime = now;
}
mPotentialPeers.insert(std::pair<bdMetric, bdPeer>(dist, peer));
#ifdef DEBUG_QUERY
fprintf(stderr, "Flagging as Potential Peer!\n");
#endif
retval = 1;
return retval;
trimPotentialPeers_toClosest();
return 1;
}
int bdQuery::trimPotentialPeers_FixedLength()
{
/* trim it back */
while(mPotentialPeers.size() > (uint32_t) (mFns->bdNodesPerBucket()))
{
std::multimap<bdMetric, bdPeer>::iterator it;
it = mPotentialPeers.end();
it--; // must be more than 1 peer here?
#ifdef DEBUG_QUERY
fprintf(stderr, "Removing Furthest Peer: ");
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
fprintf(stderr, "\n");
#endif
mPotentialPeers.erase(it);
}
return 1;
}
int bdQuery::trimPotentialPeers_toClosest()
{
if (mPotentialPeers.size() <= (uint32_t) (mFns->bdNodesPerBucket()))
return 1;
std::multimap<bdMetric, bdPeer>::reverse_iterator it;
it = mClosest.rbegin();
bdMetric lastClosest = it->first;
/* trim it back */
while(mPotentialPeers.size() > (uint32_t) (mFns->bdNodesPerBucket()))
{
std::multimap<bdMetric, bdPeer>::iterator it;
it = mPotentialPeers.end();
it--; // must be more than 1 peer here?
if (lastClosest < it->first)
{
#ifdef DEBUG_QUERY
fprintf(stderr, "Removing Furthest Peer: ");
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
fprintf(stderr, "\n");
#endif
mPotentialPeers.erase(it);
}
else
{
return 1;
}
}
return 1;
}
/*******************************************************************************************
******************************** Potential Proxies ****************************************
*******************************************************************************************/
/********
* Potential Proxies. a list of peers that have returned our target in response to a query.
*
* We are particularly interested in peers with specific flags...
* But all the peers have been pinged already by the time they reach this list.
* So there are two options:
* 1) Track everythings mode history - which is a waste of resources.
* 2) Store the list, and ping later.
*
* We will store these in two lists: Flags & Unknown.
* we keep the most recent of each, and move around as required.
*
* we could also check the Closest/PotentialPeer lists to grab the flags,
* for an unknown peer?
*
* All Functions manipulating PotentialProxies are here.
* We need several functions:
*
* For Extracting Proxies.
bool bdQuery::proxies(std::list<bdId> &answer)
bool bdQuery::potentialProxies(std::list<bdId> &answer)
*
* For Adding/Updating Proxies.
int bdQuery::addProxy(const bdId *id, const bdId *src, uint32_t srcmode)
int bdQuery::updateProxy(const bdId *id, uint32_t mode)
*
*/
/*** Two Functions to extract Proxies... ***/
bool bdQuery::proxies(std::list<bdId> &answer)
{
/* get all the matches to our query */
std::list<bdPeer>::iterator it;
int i = 0;
for(it = mProxiesFlagged.begin(); it != mProxiesFlagged.end(); it++, i++)
{
answer.push_back(it->mPeerId);
}
return (i > 0);
}
bool bdQuery::potentialProxies(std::list<bdId> &answer)
{
/* get all the matches to our query */
std::list<bdPeer>::iterator it;
int i = 0;
for(it = mProxiesUnknown.begin(); it != mProxiesUnknown.end(); it++, i++)
{
answer.push_back(it->mPeerId);
}
return (i > 0);
}
int bdQuery::addProxy(const bdId *id, const bdId *src, uint32_t srcmode)
{
bdMetric dist;
time_t now = time(NULL);
mFns->bdDistance(&mId, &(id->id), &dist);
/* finally if it is an exact match, add as potential proxy */
int bucket = mFns->bdBucketDistance(&dist);
if ((bucket != 0) || (src == NULL))
{
/* not a potential proxy */
return 0;
}
#ifdef DEBUG_QUERY
fprintf(stderr, "Bucket = 0, Have Potential Proxy!\n");
#endif
bool found = false;
if (updateProxyList(src, srcmode, mProxiesUnknown))
{
found = true;
}
if (!found)
{
if (updateProxyList(src, srcmode, mProxiesFlagged))
{
found = true;
}
}
if (!found)
{
/* if we get here. its not in the list */
#ifdef DEBUG_QUERY
fprintf(stderr, "Adding Source to Proxy List:\n");
#endif
bdPeer peer;
peer.mPeerId = *src;
peer.mPeerFlags = srcmode;
peer.mLastSendTime = 0;
peer.mLastRecvTime = now;
peer.mFoundTime = now;
/* add it in */
if ((srcmode & mRequiredPeerFlags) == mRequiredPeerFlags)
{
mProxiesFlagged.push_front(peer);
}
else
{
mProxiesUnknown.push_front(peer);
}
}
trimProxies();
return 1;
}
int bdQuery::updateProxy(const bdId *id, uint32_t mode)
{
if (!updateProxyList(id, mode, mProxiesUnknown))
{
updateProxyList(id, mode, mProxiesFlagged);
}
trimProxies();
return 1;
}
/**** Utility functions that do all the work! ****/
int bdQuery::updateProxyList(const bdId *id, uint32_t mode, std::list<bdPeer> &searchProxyList)
{
std::list<bdPeer>::iterator it;
for(it = searchProxyList.begin(); it != searchProxyList.end(); it++)
{
if (mFns->bdSimilarId(id, &(it->mPeerId)))
{
/* found it ;( */
#ifdef DEBUG_QUERY
std::cerr << "bdQuery::updateProxyList() Found peer, updating";
std::cerr << std::endl;
#endif
time_t now = time(NULL);
if (mode)
{
/* also update port from incoming id, as we have definitely recved from it */
if (mFns->bdUpdateSimilarId(&(it->mPeerId), id))
{
/* updated it... must be Unstable */
it->mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE;
}
}
it->mPeerFlags |= mode;
it->mLastRecvTime = now;
/* now move it to the front of required list...
* note this could be exactly the same list as &searchProxyList, or a different one!
*/
bdPeer peer = *it;
it = searchProxyList.erase(it);
if ((peer.mPeerFlags & mRequiredPeerFlags) == mRequiredPeerFlags)
{
mProxiesFlagged.push_front(peer);
}
else
{
mProxiesUnknown.push_front(peer);
}
return 1;
break;
}
}
return 0;
}
#define MAX_POTENTIAL_PROXIES 10
int bdQuery::trimProxies()
{
/* drop excess Potential Proxies */
while(mProxiesUnknown.size() > MAX_POTENTIAL_PROXIES)
{
mProxiesUnknown.pop_back();
}
while(mProxiesFlagged.size() > MAX_POTENTIAL_PROXIES)
{
mProxiesFlagged.pop_back();
}
return 1;
}
/*******************************************************************************************
******************************** Potential Proxies ****************************************
*******************************************************************************************/
/* print query.
*/
@ -590,6 +936,18 @@ int bdQuery::printQuery()
fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime);
fprintf(stderr, "\n");
}
std::list<bdPeer>::iterator lit;
fprintf(stderr, "\nPotential Proxies:\n");
for(lit = mPotentialProxies.begin(); lit != mPotentialProxies.end(); lit++)
{
fprintf(stderr, "ProxyId: ");
mFns->bdPrintId(std::cerr, &(lit->mPeerId));
fprintf(stderr," Found: %ld ago", ts-lit->mFoundTime);
fprintf(stderr," LastSent: %ld ago", ts-lit->mLastSendTime);
fprintf(stderr," LastRecv: %ld ago", ts-lit->mLastRecvTime);
fprintf(stderr, "\n");
}
#else
// shortened version.
fprintf(stderr, "Closest Available Peer: ");
@ -598,6 +956,7 @@ int bdQuery::printQuery()
{
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first)));
fprintf(stderr," Flags: %x", it->second.mPeerFlags);
fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime);
fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime);
fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime);
@ -605,16 +964,42 @@ int bdQuery::printQuery()
fprintf(stderr, "\n");
fprintf(stderr, "Closest Potential Peer: ");
it = mPotentialClosest.begin();
if (it != mPotentialClosest.end())
it = mPotentialPeers.begin();
if (it != mPotentialPeers.end())
{
mFns->bdPrintId(std::cerr, &(it->second.mPeerId));
fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first)));
fprintf(stderr," Flags: %x", it->second.mPeerFlags);
fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime);
fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime);
fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime);
}
fprintf(stderr, "\n");
std::list<bdPeer>::iterator lit;
fprintf(stderr, "Flagged Proxies:\n");
for(lit = mProxiesFlagged.begin(); lit != mProxiesFlagged.end(); lit++)
{
fprintf(stderr, "ProxyId: ");
mFns->bdPrintId(std::cerr, &(lit->mPeerId));
fprintf(stderr," Flags: %x", it->second.mPeerFlags);
fprintf(stderr," Found: %ld ago", ts-lit->mFoundTime);
fprintf(stderr," LastSent: %ld ago", ts-lit->mLastSendTime);
fprintf(stderr," LastRecv: %ld ago", ts-lit->mLastRecvTime);
fprintf(stderr, "\n");
}
fprintf(stderr, "Potential Proxies:\n");
for(lit = mProxiesUnknown.begin(); lit != mProxiesUnknown.end(); lit++)
{
fprintf(stderr, "ProxyId: ");
mFns->bdPrintId(std::cerr, &(lit->mPeerId));
fprintf(stderr," Flags: %x", it->second.mPeerFlags);
fprintf(stderr," Found: %ld ago", ts-lit->mFoundTime);
fprintf(stderr," LastSent: %ld ago", ts-lit->mLastSendTime);
fprintf(stderr," LastRecv: %ld ago", ts-lit->mLastRecvTime);
fprintf(stderr, "\n");
}
#endif
return 1;