Significant improvements to DHT behaviour, and reconnection attempts.

* Added GUI interface for auto connect state.
 * Added HTTP retrieval and storage of DHT peers update.
 * Added code for partial recv() from DHT peers.
 * Disabled Chat/Disc/Udplayer/tcpstream debug output.
 * Added Unreachable Check to connMgr.
 * Added auto reconnect functions to connMgr (#define to disable).
 * Restructured DHT notify code... much cleaner.
 * DHT now flags out of date DHT results.
 * DHT notifies ConnMgr on any results (same or diff).
 * Added Fns to cleanup old udp connection.
 * other bugfixes.



git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@369 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2008-03-02 14:25:59 +00:00
parent 7b3fc2976e
commit 63828f77a8
20 changed files with 708 additions and 203 deletions

View File

@ -36,6 +36,8 @@ class DHTClient
/* initialise from file */
virtual bool loadServers(std::string filename) = 0;
virtual bool loadServersFromWeb(std::string storename) = 0;
virtual bool loadServers(std::istream&) = 0;
/* check that its working */
virtual bool dhtActive() = 0;
@ -53,6 +55,8 @@ class DHTClientDummy: public DHTClient
/* initialise from file */
virtual bool loadServers(std::string filename) { return true; }
virtual bool loadServersFromWeb(std::string storename) { return true; }
virtual bool loadServers(std::istream&) { return true; }
/* check that its working */
virtual bool dhtActive() { return true; }

View File

@ -27,6 +27,9 @@
#include "dht/opendhtstr.h"
#include "dht/b64.h"
#include <fstream>
#include <sstream>
#include "util/rsnet.h"
const std::string openDHT_Client = "Retroshare V0.4";
const std::string openDHT_Agent = "RS-HTTP-V0.4";
@ -43,8 +46,12 @@ bool OpenDHTClient::loadServers(std::string filename)
/* open the file */
std::ifstream file(filename.c_str());
/* chew first line */
file.ignore(1024, '\n');
return loadServers(file);
}
bool OpenDHTClient::loadServers(std::istream &instr)
{
std::string line;
char number[1024];
@ -55,10 +62,13 @@ bool OpenDHTClient::loadServers(std::string filename)
mServers.clear();
dhtMutex.unlock(); /**** UNLOCK ****/
while((!file.eof()) && (!file.fail()))
/* chew first line */
instr.ignore(1024, '\n');
while((!instr.eof()) && (!instr.fail()))
{
line = "";
getline(file, line);
getline(instr, line);
if (3 == sscanf(line.c_str(), "%1023s %1023s %1023s", number, ipaddr, dnsname))
{
@ -92,9 +102,71 @@ bool OpenDHTClient::loadServers(std::string filename)
dhtMutex.unlock(); /**** UNLOCK ****/
}
dhtMutex.lock(); /**** LOCK ****/
uint32_t count = mServers.size();
dhtMutex.unlock(); /**** UNLOCK ****/
return (count >= MIN_DHT_SERVERS);
}
/******* refresh Servers from WebPage ******/
bool OpenDHTClient::loadServersFromWeb(std::string storename)
{
#ifdef OPENDHT_DEBUG
std::cerr << "OpenDHTClient::loadServersFromWeb()" << std::endl;
#endif
std::string response;
if (!openDHT_getDHTList(response))
{
#ifdef OPENDHT_DEBUG
std::cerr << "OpenDHTClient::loadServersFromWeb() Web GET failed" << std::endl;
#endif
return false;
}
std::string::size_type i;
if (std::string::npos == (i = response.find("\r\n\r\n")))
{
#ifdef OPENDHT_DEBUG
std::cerr << "OpenDHTClient::loadServersFromWeb() Failed to Find Content" << std::endl;
#endif
return false;
}
/* now step past 4 chars */
i += 4;
std::string content(response, i, response.length() - i);
#ifdef OPENDHT_DEBUG
std::cerr << "OpenDHTClient::loadServersFromWeb() Content:" << std::endl;
std::cerr << content << std::endl;
std::cerr << "<== OpenDHTClient::loadServersFromWeb() Content" << std::endl;
#endif
std::istringstream iss(content);
if (loadServers(iss))
{
#ifdef OPENDHT_DEBUG
std::cerr << "OpenDHTClient::loadServersFromWeb() Saving WebData to: ";
std::cerr << storename << std::endl;
#endif
/* save the data to file - replacing old data */
std::ofstream ofstr(storename.c_str());
ofstr << content;
ofstr.close();
return true;
}
return false;
}
bool OpenDHTClient::getServer(std::string &host, uint16_t &port, struct sockaddr_in &addr)
{
@ -439,11 +511,119 @@ bool OpenDHTClient::openDHT_sendMessage(std::string msg, std::string &response)
/* now wait for the response */
sleep(1);
int recvsize = 10240; /* 10kb */
void *inbuf = malloc(recvsize);
size = recv(sockfd, inbuf, recvsize, 0);
int recvsize = 51200; /* 50kb */
char *inbuf = (char *) malloc(recvsize);
uint32_t idx = 0;
while(0 < (size = recv(sockfd, &(inbuf[idx]), recvsize - idx, 0)))
{
std::cerr << "OpenDHTClient::openDHT_sendMessage()";
std::cerr << " Recvd Chunk:" << size;
std::cerr << std::endl;
response = (char *) inbuf;
idx += size;
}
std::cerr << "OpenDHTClient::openDHT_sendMessage()";
std::cerr << " Recvd Msg:" << idx;
response = std::string(inbuf, idx);
free(inbuf);
/* print it out */
std::cerr << "HTTP response *******************" << std::endl;
std::cerr << response;
std::cerr << std::endl;
std::cerr << "HTTP response *******************" << std::endl;
close(sockfd);
return true;
}
bool OpenDHTClient::openDHT_getDHTList(std::string &response)
{
struct sockaddr_in addr;
std::string host = "www.opendht.org";
uint16_t port = 80;
sockaddr_clear(&addr);
/* lookup the address */
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (!LookupDNSAddr(host, addr))
{
/* no address */
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
std::cerr << " ERROR: No Address";
std::cerr << std::endl;
return false;
}
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
std::cerr << " Connecting to:" << host << ":" << port;
std::cerr << " (" << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port) << ")";
std::cerr << std::endl;
/* create request */
std::string putheader = createHttpHeaderGET(host, port, "servers.txt", openDHT_Agent, 0);
/* open a socket */
int sockfd = unix_socket(PF_INET, SOCK_STREAM, 0);
/* connect */
int err = unix_connect(sockfd, (struct sockaddr *) &addr, sizeof(addr));
if (err)
{
unix_close(sockfd);
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
std::cerr << " ERROR: Failed to Connect";
std::cerr << std::endl;
return false;
}
std::cerr << "HTTP message *******************" << std::endl;
std::cerr << putheader;
std::cerr << std::endl;
std::cerr << "HTTP message *******************" << std::endl;
/* send data */
int sendsize = strlen(putheader.c_str());
int size = send(sockfd, putheader.c_str(), sendsize, 0);
if (sendsize != size)
{
unix_close(sockfd);
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
std::cerr << " ERROR: Failed to Send(1)";
std::cerr << std::endl;
return false;
}
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
std::cerr << " Send(1):" << size;
std::cerr << std::endl;
/* now wait for the response */
sleep(1);
int recvsize = 51200; /* 50kb */
char *inbuf = (char *) malloc(recvsize);
uint32_t idx = 0;
while(0 < (size = recv(sockfd, &(inbuf[idx]), recvsize - idx, 0)))
{
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
std::cerr << " Recvd Chunk:" << size;
std::cerr << std::endl;
idx += size;
}
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
std::cerr << " Recvd Msg:" << idx;
response = std::string(inbuf, idx);
free(inbuf);
/* print it out */

View File

@ -56,6 +56,9 @@ virtual bool searchKey(std::string key, std::list<std::string> &values);
/* Fns accessing data */
virtual bool loadServers(std::string filename);
virtual bool loadServersFromWeb(std::string storefname);
virtual bool loadServers(std::istream&);
virtual bool dhtActive();
private:
@ -67,6 +70,7 @@ void setServerFailed(std::string host);
/* generic send msg */
bool openDHT_sendMessage(std::string msg, std::string &response);
bool openDHT_getDHTList(std::string &response);
RsMutex dhtMutex;
std::map<std::string, dhtServer> mServers;

View File

@ -116,8 +116,12 @@ bool OpenDHTMgr::init()
}
filename += "servers.txt";
if (!mClient -> loadServersFromWeb(filename))
{
return mClient -> loadServers(filename);
}
return true;
}
bool OpenDHTMgr::shutdown()
{

View File

@ -43,6 +43,20 @@ std::string createHttpHeader(std::string host, uint16_t port, std::string agent,
return req.str();
};
std::string createHttpHeaderGET(std::string host, uint16_t port, std::string page, std::string agent, uint32_t length)
{
std::ostringstream req;
req << "GET /" << page << " HTTP/1.0\r\n";
req << "Host: " << host << ":" << port << "\r\n";
req << "User-Agent: " << agent << "\r\n";
//req << "Content-Type: text/xml\r\n";
//req << "Content-Length: " << length << "\r\n";
req << "\r\n";
return req.str();
};
std::string createOpenDHT_put(std::string key, std::string value, uint32_t ttl, std::string client)
{
std::ostringstream req;

View File

@ -32,6 +32,9 @@
std::string createHttpHeader(std::string host, uint16_t port,
std::string agent, uint32_t length);
std::string createHttpHeaderGET(std::string host, uint16_t port,
std::string page, std::string agent, uint32_t length);
std::string createOpenDHT_put(std::string key, std::string value,
uint32_t ttl, std::string client);

View File

@ -48,8 +48,12 @@ const uint32_t MAX_UPNP_INIT = 60; /* seconds UPnP timeout */
#define CONN_DEBUG 1
#define P3CONNMGR_NO_TCP_CONNECTIONS 1
/****
* #define P3CONNMGR_NO_AUTO_CONNECTION 1
***/
const uint32_t P3CONNMGR_TCP_DEFAULT_DELAY = 10; /* 10 Seconds should be enough! */
const uint32_t P3CONNMGR_UDP_DHT_DELAY = 300; /* 5 minutes */
const uint32_t P3CONNMGR_UDP_DHT_DELAY = 300 + 60; /* 5 minutes FIND + 1 minute for DHT POST */
const uint32_t P3CONNMGR_UDP_PROXY_DELAY = 30; /* 30 seconds */
void printConnectState(peerConnectState &peer);
@ -72,10 +76,11 @@ peerConnectState::peerConnectState()
:id("unknown"),
netMode(RS_NET_MODE_UNKNOWN), visState(RS_VIS_STATE_STD),
lastcontact(0),
lastavailable(0),
lastattempt(0),
name("nameless"), state(0), actions(0),
source(0),
inConnAttempt(0), lastattempt(0)
inConnAttempt(0)
{
sockaddr_clear(&localaddr);
sockaddr_clear(&serveraddr);
@ -241,10 +246,6 @@ void p3ConnectMgr::netStartup()
switch(ownState.netMode & RS_NET_MODE_TRYMODE)
{
case RS_NET_MODE_TRY_UPNP:
ownState.netMode |= RS_NET_MODE_UDP;
mNetStatus = RS_NET_UPNP_INIT;
break;
case RS_NET_MODE_TRY_EXT: /* v similar to UDP */
ownState.netMode |= RS_NET_MODE_EXT;
@ -256,11 +257,15 @@ void p3ConnectMgr::netStartup()
break;
case RS_NET_MODE_TRY_UDP:
default:
ownState.netMode |= RS_NET_MODE_UDP;
mNetStatus = RS_NET_UDP_SETUP;
break;
case RS_NET_MODE_TRY_UPNP:
default:
ownState.netMode |= RS_NET_MODE_UDP;
mNetStatus = RS_NET_UPNP_INIT;
break;
}
connMtx.unlock(); /* UNLOCK MUTEX */
}
@ -269,10 +274,78 @@ void p3ConnectMgr::netStartup()
void p3ConnectMgr::tick()
{
netTick();
statusTick();
tickMonitors();
}
#define MAX_AVAIL_PERIOD 900 // 15 minutes
#define MIN_RETRY_PERIOD 1900 // just over 30 minutes. (DHT retry period)
void p3ConnectMgr::statusTick()
{
/* iterate through peers ...
* if been available for long time ... remove flag
* if last attempt a while - retryConnect.
* etc.
*/
#ifdef CONN_DEBUG
//std::cerr << "p3ConnectMgr::statusTick()" << std::endl;
#endif
std::list<std::string> retryIds;
std::list<std::string>::iterator it2;
time_t now = time(NULL);
time_t oldavail = now - MAX_AVAIL_PERIOD;
time_t retry = now - MIN_RETRY_PERIOD;
{
RsStackMutex stack(connMtx); /****** LOCK MUTEX ******/
std::map<std::string, peerConnectState>::iterator it;
for(it = mFriendList.begin(); it != mFriendList.end(); it++)
{
if (it->second.state & RS_PEER_S_CONNECTED)
{
continue;
}
if ((it->second.state & RS_PEER_S_ONLINE) &&
(it->second.lastavailable < oldavail))
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::statusTick() ONLINE TIMEOUT for: ";
std::cerr << it->first;
std::cerr << std::endl;
#endif
it->second.state &= (~RS_PEER_S_ONLINE);
}
if (it->second.lastattempt < retry)
{
retryIds.push_back(it->first);
}
}
}
#ifndef P3CONNMGR_NO_AUTO_CONNECTION
for(it2 = retryIds.begin(); it2 != retryIds.end(); it2++)
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::statusTick() RETRY TIMEOUT for: ";
std::cerr << *it2;
std::cerr << std::endl;
#endif
/* retry it! */
retryConnect(*it2);
}
#endif
}
void p3ConnectMgr::netTick()
{
@ -481,6 +554,7 @@ void p3ConnectMgr::netUdpCheck()
if (mUpnpAddrValid || (ownState.netMode == RS_NET_MODE_EXT))
{
mode |= RS_NET_CONN_TCP_EXTERNAL;
mode |= RS_NET_CONN_UDP_DHT_SYNC;
}
else if (extAddrStable)
{
@ -496,7 +570,8 @@ void p3ConnectMgr::netUdpCheck()
std::cerr << "netMode => RS_NET_MODE_UNREACHABLE";
std::cerr << std::endl;
#endif
ownState.netMode = RS_NET_MODE_UNREACHABLE;
ownState.netMode &= ~(RS_NET_MODE_ACTUAL);
ownState.netMode |= RS_NET_MODE_UNREACHABLE;
tou_stunkeepalive(0);
}
@ -514,8 +589,86 @@ void p3ConnectMgr::netUdpCheck()
/* mode = 0 for error */
mDhtMgr->setExternalInterface(iaddr, extAddr, mode);
}
/* flag unreachables! */
if ((extValid) && (!extAddrStable))
{
netUnreachableCheck();
}
}
}
void p3ConnectMgr::netUnreachableCheck()
{
#ifdef CONN_DEBUG
std::cerr << "p3ConnectMgr::netUnreachableCheck()" << std::endl;
#endif
std::map<std::string, peerConnectState>::iterator it;
connMtx.lock(); /* LOCK MUTEX */
for(it = mFriendList.begin(); it != mFriendList.end(); it++)
{
/* get last contact detail */
if (it->second.state & RS_PEER_S_CONNECTED)
{
#ifdef CONN_DEBUG
std::cerr << "NUC() Ignoring Connected Peer" << std::endl;
#endif
continue;
}
peerAddrInfo details;
switch(it->second.source)
{
case RS_CB_DHT:
details = it->second.dht;
#ifdef CONN_DEBUG
std::cerr << "NUC() Using DHT data" << std::endl;
#endif
break;
case RS_CB_DISC:
details = it->second.disc;
#ifdef CONN_DEBUG
std::cerr << "NUC() Using DISC data" << std::endl;
#endif
break;
case RS_CB_PERSON:
details = it->second.peer;
#ifdef CONN_DEBUG
std::cerr << "NUC() Using PEER data" << std::endl;
#endif
break;
default:
continue;
break;
}
std::cerr << "NUC() Peer: " << it->first << std::endl;
/* Determine Reachability (only advisory) */
// if (ownState.netMode == RS_NET_MODE_UNREACHABLE) // MUST BE TRUE!
{
if (details.type & RS_NET_CONN_TCP_EXTERNAL)
{
/* reachable! */
it->second.state &= (~RS_PEER_S_UNREACHABLE);
#ifdef CONN_DEBUG
std::cerr << "NUC() Peer EXT TCP - reachable" << std::endl;
#endif
}
else
{
/* unreachable */
it->second.state |= RS_PEER_S_UNREACHABLE;
#ifdef CONN_DEBUG
std::cerr << "NUC() Peer !EXT TCP - unreachable" << std::endl;
#endif
}
}
}
connMtx.unlock(); /* UNLOCK MUTEX */
}
/******************************* UDP MAINTAINANCE ********************************
@ -1136,6 +1289,7 @@ bool p3ConnectMgr::connectResult(std::string id, bool success, uint32_t flags)
* From various sources
*/
void p3ConnectMgr::peerStatus(std::string id,
struct sockaddr_in laddr, struct sockaddr_in raddr,
uint32_t type, uint32_t flags, uint32_t source)
@ -1178,13 +1332,14 @@ void p3ConnectMgr::peerStatus(std::string id,
std::cerr << std::endl;
/* update the status */
time_t now = time(NULL);
peerAddrInfo details;
details.type = type;
details.found = true;
details.laddr = laddr;
details.raddr = raddr;
details.ts = time(NULL);
details.ts = now;
/* if source is DHT */
if (source == RS_CB_DHT)
@ -1198,6 +1353,7 @@ void p3ConnectMgr::peerStatus(std::string id,
/* If we get a info -> then they are online */
it->second.state |= RS_PEER_S_ONLINE;
it->second.lastavailable = now;
}
else if (source == RS_CB_DISC)
{
@ -1212,6 +1368,7 @@ void p3ConnectMgr::peerStatus(std::string id,
{
it->second.actions |= RS_PEER_ONLINE;
it->second.state |= RS_PEER_S_ONLINE;
it->second.lastavailable = now;
mStatusChanged = true;
}
@ -1231,7 +1388,9 @@ void p3ConnectMgr::peerStatus(std::string id,
it->second.localaddr = laddr;
it->second.serveraddr = raddr;
it->second.state |= RS_PEER_S_ONLINE;
it->second.lastavailable = now;
/* must be online to recv info (should be connected too!)
* but no need for action as should be connected already
@ -1274,7 +1433,7 @@ void p3ConnectMgr::peerStatus(std::string id,
}
/* Determine Reachability (only advisory) */
if (ownState.netMode == RS_NET_MODE_UDP)
if (ownState.netMode & RS_NET_MODE_UDP)
{
if ((details.type & RS_NET_CONN_UDP_DHT_SYNC) ||
(details.type & RS_NET_CONN_TCP_EXTERNAL))
@ -1288,7 +1447,7 @@ void p3ConnectMgr::peerStatus(std::string id,
it->second.state |= RS_PEER_S_UNREACHABLE;
}
}
else if (ownState.netMode == RS_NET_MODE_UNREACHABLE)
else if (ownState.netMode & RS_NET_MODE_UNREACHABLE)
{
if (details.type & RS_NET_CONN_TCP_EXTERNAL)
{
@ -1339,6 +1498,7 @@ void p3ConnectMgr::peerStatus(std::string id,
std::cerr << " source: " << source;
std::cerr << std::endl;
#ifndef P3CONNMGR_NO_AUTO_CONNECTION
#ifndef P3CONNMGR_NO_TCP_CONNECTIONS
@ -1430,7 +1590,16 @@ void p3ConnectMgr::peerStatus(std::string id,
std::cerr << std::endl;
}
#endif
#endif // P3CONNMGR_NO_TCP_CONNECTIONS
/* notify if they say we can, or we cannot connect ! */
if (details.type & RS_NET_CONN_UDP_DHT_SYNC)
{
retryConnectNotify(id);
}
#endif // P3CONNMGR_NO_AUTO_CONNECTION
if (it->second.inConnAttempt)
{
@ -1471,6 +1640,22 @@ void p3ConnectMgr::peerConnectRequest(std::string id, struct sockaddr_in radd
std::cerr << " source: " << source;
std::cerr << std::endl;
/******************** TCP PART *****************************/
std::cerr << "p3ConnectMgr::peerConnectRequest() Try TCP first";
std::cerr << std::endl;
retryConnectTCP(id);
/******************** UDP PART *****************************/
if (ownState.netMode & RS_NET_MODE_UNREACHABLE)
{
std::cerr << "p3ConnectMgr::peerConnectRequest() Unreachable - no UDP connection";
std::cerr << std::endl;
return;
}
/* look up the id */
std::map<std::string, peerConnectState>::iterator it;
connMtx.lock(); /* LOCK MUTEX */
@ -1502,6 +1687,7 @@ void p3ConnectMgr::peerConnectRequest(std::string id, struct sockaddr_in radd
return;
}
time_t now = time(NULL);
/* this is a UDP connection request (DHT only for the moment!) */
if (isValidNet(&(raddr.sin_addr)))
@ -1825,9 +2011,18 @@ bool p3ConnectMgr::addNeighbour(std::string id)
/*******************************************************************/
/*************** External Control ****************/
bool p3ConnectMgr::retryConnect(std::string id)
{
retryConnectTCP(id);
retryConnectNotify(id);
return true;
}
bool p3ConnectMgr::retryConnectTCP(std::string id)
{
/* push addresses onto stack */
std::cerr << "p3ConnectMgr::retryConnect()";
std::cerr << "p3ConnectMgr::retryConnectTCP()";
std::cerr << " id: " << id;
std::cerr << std::endl;
@ -1838,7 +2033,7 @@ bool p3ConnectMgr::retryConnect(std::string id)
if (mFriendList.end() == (it = mFriendList.find(id)))
{
std::cerr << "p3ConnectMgr::retryConnect() Peer is not Friend";
std::cerr << "p3ConnectMgr::retryConnectTCP() Peer is not Friend";
std::cerr << std::endl;
return false;
}
@ -1846,7 +2041,7 @@ bool p3ConnectMgr::retryConnect(std::string id)
/* if already connected -> done */
if (it->second.state & RS_PEER_S_CONNECTED)
{
std::cerr << "p3ConnectMgr::retryConnect() Peer Already Connected";
std::cerr << "p3ConnectMgr::retryConnectTCP() Peer Already Connected";
std::cerr << std::endl;
return true;
}
@ -1867,7 +2062,7 @@ bool p3ConnectMgr::retryConnect(std::string id)
&(it->second.localaddr.sin_addr))))
{
std::cerr << "p3ConnectMgr::retryConnect() Local Address Valid: ";
std::cerr << "p3ConnectMgr::retryConnectTCP() Local Address Valid: ";
std::cerr << inet_ntoa(it->second.localaddr.sin_addr);
std::cerr << ":" << ntohs(it->second.localaddr.sin_port);
std::cerr << std::endl;
@ -1892,7 +2087,7 @@ bool p3ConnectMgr::retryConnect(std::string id)
if (!localExists)
{
std::cerr << "p3ConnectMgr::retryConnect() Adding Local Addr to Queue";
std::cerr << "p3ConnectMgr::retryConnectTCP() Adding Local Addr to Queue";
std::cerr << std::endl;
/* add the local address */
@ -1905,16 +2100,19 @@ bool p3ConnectMgr::retryConnect(std::string id)
}
else
{
std::cerr << "p3ConnectMgr::retryConnect() Local Addr already in Queue";
std::cerr << "p3ConnectMgr::retryConnectTCP() Local Addr already in Queue";
std::cerr << std::endl;
}
}
/* otherwise try external ... (should check flags) */
if ((isValidNet(&(it->second.serveraddr.sin_addr))) &&
(it->second.netMode = RS_NET_MODE_EXT))
//if ((isValidNet(&(it->second.serveraddr.sin_addr))) &&
// (it->second.netMode = RS_NET_MODE_EXT))
/* always try external */
if (isValidNet(&(it->second.serveraddr.sin_addr)))
{
std::cerr << "p3ConnectMgr::retryConnect() Ext Address Valid (+EXT Flag): ";
std::cerr << "p3ConnectMgr::retryConnectTCP() Ext Address Valid: ";
std::cerr << inet_ntoa(it->second.serveraddr.sin_addr);
std::cerr << ":" << ntohs(it->second.serveraddr.sin_port);
std::cerr << std::endl;
@ -1940,7 +2138,7 @@ bool p3ConnectMgr::retryConnect(std::string id)
if (!remoteExists)
{
std::cerr << "p3ConnectMgr::retryConnect() Adding Ext Addr to Queue";
std::cerr << "p3ConnectMgr::retryConnectTCP() Adding Ext Addr to Queue";
std::cerr << std::endl;
/* add the remote address */
@ -1953,27 +2151,15 @@ bool p3ConnectMgr::retryConnect(std::string id)
}
else
{
std::cerr << "p3ConnectMgr::retryConnect() Ext Addr already in Queue";
std::cerr << "p3ConnectMgr::retryConnectTCP() Ext Addr already in Queue";
std::cerr << std::endl;
}
}
#endif
if (it->second.netMode == RS_NET_MODE_UDP)
{
std::cerr << "p3ConnectMgr::retryConnect() trying UDP connection!";
std::cerr << " id: " << id;
std::cerr << std::endl;
#endif // P3CONNMGR_NO_TCP_CONNECTIONS
/* attempt UDP connection */
mDhtMgr->notifyPeer(id);
}
else
{
std::cerr << "p3ConnectMgr::retryConnect() EXT/UNREACHABLE so not trying UDP connection!";
std::cerr << " id: " << id;
std::cerr << std::endl;
}
/* flag as last attempt to prevent loop */
it->second.lastattempt = time(NULL);
if (it->second.inConnAttempt)
{
@ -1984,7 +2170,7 @@ bool p3ConnectMgr::retryConnect(std::string id)
/* start a connection attempt */
if (it->second.connAddrs.size() > 0)
{
std::cerr << "p3ConnectMgr::retryConnect() Started CONNECT ATTEMPT! ";
std::cerr << "p3ConnectMgr::retryConnectTCP() Started CONNECT ATTEMPT! ";
std::cerr << " id: " << id;
std::cerr << std::endl;
@ -1993,7 +2179,7 @@ bool p3ConnectMgr::retryConnect(std::string id)
}
else
{
std::cerr << "p3ConnectMgr::retryConnect() No addr suitable for CONNECT ATTEMPT! ";
std::cerr << "p3ConnectMgr::retryConnectTCP() No addr suitable for CONNECT ATTEMPT! ";
std::cerr << " id: " << id;
std::cerr << std::endl;
}
@ -2001,6 +2187,58 @@ bool p3ConnectMgr::retryConnect(std::string id)
}
bool p3ConnectMgr::retryConnectNotify(std::string id)
{
/* push addresses onto stack */
std::cerr << "p3ConnectMgr::retryConnectNotify()";
std::cerr << " id: " << id;
std::cerr << std::endl;
/* look up the id */
std::map<std::string, peerConnectState>::iterator it;
connMtx.lock(); /* LOCK MUTEX */
connMtx.unlock(); /* UNLOCK MUTEX */
if (mFriendList.end() == (it = mFriendList.find(id)))
{
std::cerr << "p3ConnectMgr::retryConnectNotify() Peer is not Friend";
std::cerr << std::endl;
return false;
}
/* if already connected -> done */
if (it->second.state & RS_PEER_S_CONNECTED)
{
std::cerr << "p3ConnectMgr::retryConnectNotify() Peer Already Connected";
std::cerr << std::endl;
return true;
}
/* flag as last attempt to prevent loop */
it->second.lastattempt = time(NULL);
if (ownState.netMode & RS_NET_MODE_UNREACHABLE)
{
std::cerr << "p3ConnectMgr::retryConnectNotify() UNREACHABLE so no Notify!";
std::cerr << " id: " << id;
std::cerr << std::endl;
}
else
{
std::cerr << "p3ConnectMgr::retryConnectNotify() Notifying Peer";
std::cerr << " id: " << id;
std::cerr << std::endl;
/* attempt UDP connection */
mDhtMgr->notifyPeer(id);
}
return true;
}
bool p3ConnectMgr::setLocalAddress(std::string id, struct sockaddr_in addr)
{

View File

@ -126,6 +126,8 @@ class peerConnectState
time_t lastcontact;
/***** Below here not stored permanently *****/
time_t lastavailable;
time_t lastattempt;
std::string name;
@ -139,7 +141,6 @@ class peerConnectState
/* a list of connect attempts to make (in order) */
bool inConnAttempt;
time_t lastattempt;
peerConnectAddress currentConnAddr;
std::list<peerConnectAddress> connAddrs;
@ -216,6 +217,7 @@ bool connectResult(std::string id, bool success, uint32_t flags);
protected:
/* Internal Functions */
void statusTick();
void netTick();
void netStartup();
@ -236,6 +238,7 @@ void netUpnpInit();
void netUpnpCheck();
void netUdpCheck();
void netUnreachableCheck();
/* Udp / Stun functions */
bool udpInternalAddress(struct sockaddr_in iaddr);
@ -249,6 +252,9 @@ void stunCollect(std::string id, struct sockaddr_in addr, uint32_t flags);
/* monitor control */
void tickMonitors();
/* connect attempts */
bool retryConnectTCP(std::string id);
bool retryConnectNotify(std::string id);
/* temporary for testing */
virtual void loadConfiguration() { return; }

View File

@ -66,8 +66,8 @@
#define DHT_DEFAULT_WAITTIME 1 /* Std sleep break period */
/* TTLs for DHTs posts */
#define DHT_TTL_PUBLISH (DHT_PUBLISH_PERIOD + 30)
#define DHT_TTL_NOTIFY DHT_NOTIFY_PERIOD
#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...
void printDhtPeerEntry(dhtPeerEntry *ent, std::ostream &out);
@ -185,14 +185,17 @@ bool p3DhtMgr::setExternalInterface(
/* add / remove peers */
bool p3DhtMgr::findPeer(std::string id)
{
dhtMtx.lock(); /* LOCK MUTEX */
RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/
mDhtModifications = true;
std::map<std::string, dhtPeerEntry>::iterator it;
it = peers.find(id);
if (it == peers.end())
if (it != peers.end())
{
return true;
}
/* if they are not in the list -> add */
dhtPeerEntry ent;
ent.id = id;
@ -210,20 +213,13 @@ bool p3DhtMgr::findPeer(std::string id)
/* other fields don't matter */
peers[id] = ent;
}
else
{
/* ignore */
}
dhtMtx.unlock(); /* UNLOCK MUTEX */
return true;
}
bool p3DhtMgr::dropPeer(std::string id)
{
dhtMtx.lock(); /* LOCK MUTEX */
RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/
mDhtModifications = true;
@ -232,15 +228,11 @@ bool p3DhtMgr::dropPeer(std::string id)
it = peers.find(id);
if (it == peers.end())
{
/* ignore */
}
else
{
/* remove */
peers.erase(it);
return false;
}
dhtMtx.unlock(); /* UNLOCK MUTEX */
/* remove */
peers.erase(it);
return true;
}
@ -248,31 +240,46 @@ bool p3DhtMgr::dropPeer(std::string id)
/* post DHT key saying we should connect */
bool p3DhtMgr::notifyPeer(std::string id)
{
dhtMtx.lock(); /* LOCK MUTEX */
RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::notifyPeer() " << id << std::endl;
#endif
mDhtModifications = true;
/* once we are connected ... don't worry about them anymore */
std::map<std::string, dhtPeerEntry>::iterator it;
it = peers.find(id);
bool ret = true;
if (it == peers.end())
{
/* ignore */
ret = false;
return false;
}
else
time_t now = time(NULL);
if (now - it->second.notifyTS < 2 * DHT_NOTIFY_PERIOD)
{
/* drop the notify (too soon) */
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::notifyPeer() TO SOON - DROPPING" << std::endl;
#endif
return false;
}
it->second.notifyPending = RS_CONNECT_ACTIVE;
it->second.notifyTS = time(NULL);
/* Trigger search if not found! */
if (it->second.state != DHT_PEER_FOUND)
{
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::notifyPeer() PEER NOT FOUND - Trigger search" << std::endl;
#endif
it->second.lastTS = 0;
}
dhtMtx.unlock(); /* UNLOCK MUTEX */
mDhtModifications = true; /* no wait! */
return ret;
return true;
}
/* extract current peer status */
bool p3DhtMgr::getPeerStatus(std::string id,
struct sockaddr_in &laddr,
@ -680,12 +687,12 @@ int p3DhtMgr::checkPeerDHTKeys()
return repeatPeriod;
}
/* update timestamp */
/* update timestamp
* clear FOUND or INIT state.
* */
pit->second.lastTS = now;
if (pit->second.state == DHT_PEER_INIT)
{
pit->second.state = DHT_PEER_SEARCH;
}
dhtPeerEntry peer = (pit->second);
@ -705,8 +712,12 @@ int p3DhtMgr::checkNotifyDHT()
std::cerr << "p3DhtMgr::checkNotifyDHT()" << std::endl;
#endif
/* now loop through the peers */
uint32_t notifyType = 0;
dhtPeerEntry peer;
dhtPeerEntry own;
dhtMtx.lock(); /* LOCK MUTEX */
{
RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/
/* iterate through and find min time and suitable candidate */
std::map<std::string, dhtPeerEntry>::iterator it;
@ -716,46 +727,68 @@ int p3DhtMgr::checkNotifyDHT()
/* find the first with a notify flag */
for(it = peers.begin(); it != peers.end(); it++)
{
if ((it->second.state == DHT_PEER_FOUND) &&
(it->second.notifyPending == RS_CONNECT_ACTIVE))
if (it->second.notifyPending)
{
if (it->second.state == DHT_PEER_FOUND)
{
notifyType = it->second.notifyPending;
break;
}
/* if very old drop it */
if (now - it->second.notifyTS > DHT_NOTIFY_PERIOD)
{
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::checkNotifyDHT() Dropping OLD Notify: ";
std::cerr << it->first << std::endl;
#endif
it->second.notifyPending = 0;
}
}
}
/* now have - peer to handle */
if (it == peers.end())
{
dhtMtx.unlock(); /* UNLOCK MUTEX */
return repeatPeriod;
}
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::checkNotifyDHT() Notify From: ";
std::cerr << it->first << std::endl;
#endif
/* update timestamp */
it->second.notifyTS = now;
it->second.notifyPending = 0;
dhtPeerEntry peer = (it->second);
dhtPeerEntry own = ownEntry;
peer = (it->second);
own = ownEntry;
dhtMtx.unlock(); /* UNLOCK MUTEX */
} /******* UNLOCK ******/
if (notifyType == RS_CONNECT_ACTIVE)
{
/* publish notification (publish Our Id)
* We publish the connection attempt on peers hash,
* using our alternative hash..
* */
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::checkNotifyDHT() Posting Active Notify";
std::cerr << std::endl;
#endif
dhtNotify(peer.hash1, own.hash2, "");
}
if (dhtNotify(peer.hash1, own.hash2, ""))
{
/* feedback to say we started it! */
#ifdef P3DHTMGR_USE_LOCAL_UDP_CONN
connCb->peerConnectRequest(peer.id, peer.laddr, RS_CB_DHT);
#else
connCb->peerConnectRequest(peer.id, peer.raddr, RS_CB_DHT);
#endif
}
repeatPeriod = DHT_MIN_PERIOD;
return repeatPeriod;
return DHT_MIN_PERIOD;
}
@ -1239,14 +1272,13 @@ bool p3DhtMgr::resultDHT(std::string key, std::string value)
bool p3DhtMgr::dhtResultNotify(std::string idhash)
{
dhtMtx.lock(); /* LOCK MUTEX */
RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/
#ifdef DHT_DEBUG
std::cerr << "p3DhtMgr::dhtResultNotify() from idhash: ";
std::cerr << RsUtil::BinToHex(idhash) << std::endl;
#endif
std::map<std::string, dhtPeerEntry>::iterator it;
bool doNotify = false;
time_t now = time(NULL);
/* if notify - we must match on the second hash */
@ -1254,7 +1286,6 @@ bool p3DhtMgr::dhtResultNotify(std::string idhash)
/* update data */
std::string peerid;
struct sockaddr_in raddr, laddr;
if (it != peers.end())
{
@ -1263,22 +1294,14 @@ bool p3DhtMgr::dhtResultNotify(std::string idhash)
#endif
/* delay callback -> if they are not found */
it->second.notifyTS = now;
it->second.notifyPending = RS_CONNECT_PASSIVE;
mDhtModifications = true; /* no wait! */
if (it->second.state != DHT_PEER_FOUND)
{
doNotify = false;
it->second.notifyPending = RS_CONNECT_PASSIVE;
/* flag for immediate search */
mDhtModifications = true; /* no wait! */
it->second.lastTS = 0;
}
else
{
doNotify = true;
it->second.notifyPending = 0;
peerid = (it->second).id;
raddr = (it->second).raddr;
laddr = (it->second).laddr;
}
}
else
{
@ -1288,18 +1311,6 @@ bool p3DhtMgr::dhtResultNotify(std::string idhash)
#endif
}
dhtMtx.unlock(); /* UNLOCK MUTEX */
/* do callback */
if (doNotify)
{
#ifdef P3DHTMGR_USE_LOCAL_UDP_CONN
connCb->peerConnectRequest(peerid, laddr, RS_CB_DHT);
#else
connCb->peerConnectRequest(peerid, raddr, RS_CB_DHT);
#endif
}
return true;
}
@ -1316,7 +1327,6 @@ bool p3DhtMgr::dhtResultSearch(std::string idhash,
#endif
std::map<std::string, dhtPeerEntry>::iterator it;
bool doCb = false;
bool doNotify = false;
bool doStun = false;
uint32_t stunFlags = 0;
time_t now = time(NULL);
@ -1334,40 +1344,26 @@ bool p3DhtMgr::dhtResultSearch(std::string idhash,
#endif
it->second.lastTS = now;
/* has it changed??? */
if ((it->second.state != DHT_PEER_FOUND) ||
(0 != sockaddr_cmp(it->second.laddr,laddr)) ||
(0 != sockaddr_cmp(it->second.raddr,raddr)) ||
(it->second.type != type))
{
/* Do callback all the time */
ent = it->second;
doCb = true;
/* update info .... always */
it->second.state = DHT_PEER_FOUND;
it->second.laddr = laddr;
it->second.raddr = raddr;
it->second.type = type;
ent = it->second;
doCb = true;
if (it->second.notifyPending)
{
/* no wait if we have pendingNotification */
mDhtModifications = true;
}
/* do we have a pending notify */
if ((it->second.state == DHT_PEER_FOUND) &&
(it->second.notifyPending == RS_CONNECT_PASSIVE))
{
it->second.notifyPending = 0;
doNotify = true;
}
/* if stun not happy yet - doStun as well..
* as the DHT doesn't know if the Stun is happy - send
* it through always!
* if ((mDhtState != DHT_STATE_OFF) &&
* (mDhtState != DHT_STATE_ACTIVE))
*/
if (mDhtState != DHT_STATE_OFF)
{
/* do Stun always */
doStun = true;
stunFlags = RS_STUN_FRIEND | RS_STUN_ONLINE;
}
}
else
{
#ifdef DHT_DEBUG
@ -1381,21 +1377,10 @@ bool p3DhtMgr::dhtResultSearch(std::string idhash,
dhtMtx.unlock(); /* UNLOCK MUTEX */
/* if changed - do callback */
if (doCb)
{
connCb->peerStatus(ent.id,
ent.laddr, ent.raddr,
connCb->peerStatus(ent.id, ent.laddr, ent.raddr,
ent.type, 0, RS_CB_DHT);
//ent.type, RS_CB_LOCAL_ADDR | RS_CB_REMOTE_ADDR, RS_CB_DHT);
if (doNotify)
{
#ifdef P3DHTMGR_USE_LOCAL_UDP_CONN
connCb->peerConnectRequest(ent.id, ent.laddr, RS_CB_DHT);
#else
connCb->peerConnectRequest(ent.id, ent.raddr, RS_CB_DHT);
#endif
}
}
if (doStun)

View File

@ -101,6 +101,7 @@ class RsPeerDetails
/* basic stats */
uint32_t lastConnect; /* how long ago */
std::string autoconnect;
uint32_t connectPeriod;
};

View File

@ -325,6 +325,40 @@ bool p3Peers::getPeerDetails(std::string id, RsPeerDetails &d)
d.visState |= RS_VS_DHT_ON;
}
/* Finally determine AutoConnect Status */
std::ostringstream autostr;
if (pcs.inConnAttempt)
{
/*
*/
autostr << "Trying ";
switch(pcs.currentConnAddr.type)
{
case RS_NET_CONN_TCP_LOCAL:
autostr << "TCP (Local)";
break;
case RS_NET_CONN_TCP_EXTERNAL:
autostr << "TCP (External)";
break;
case RS_NET_CONN_UDP_DHT_SYNC:
autostr << "UDP (ETA: ";
autostr << 360 - (time(NULL) - pcs.currentConnAddr.ts);
autostr << ")";
break;
default:
autostr << "Unknown";
break;
}
}
else
{
autostr << "Idle";
}
d.autoconnect = autostr.str();
return true;
}

View File

@ -26,7 +26,9 @@
#include "services/p3chatservice.h"
#define CHAT_DEBUG 1
/****
* #define CHAT_DEBUG 1
****/
/************ NOTE *********************************
* This Service is so simple that there is no

View File

@ -59,7 +59,9 @@ const uint32_t P3DISC_FLAGS_PEER_ONLINE = 0x0010;
const uint32_t P3DISC_FLAGS_OWN_DETAILS = 0x0020;
#define P3DISC_DEBUG 1
/*****
* #define P3DISC_DEBUG 1
****/
/*********** NOTE ***************
*

View File

@ -39,7 +39,6 @@
/*
* #define DEBUG_TCP_STREAM 1
*/
#define DEBUG_TCP_STREAM 1
/*
*#define DEBUG_TCP_STREAM_EXTRA 1

View File

@ -403,6 +403,7 @@ int tou_close(int sockfd)
/* shut it down */
tous->tcp->close();
udps->removeUdpPeer(tous->tcp);
delete tous->tcp;
}

View File

@ -44,9 +44,9 @@
#include <errno.h>
*/
/*
*/ #define DEBUG_UDP_LAYER 1
/**/
/***
* #define DEBUG_UDP_LAYER 1
***/
static const int UDP_DEF_TTL = 64;

View File

@ -189,6 +189,30 @@ int UdpSorter::addUdpPeer(UdpPeer *peer, const struct sockaddr_in &raddr)
return ok;
}
int UdpSorter::removeUdpPeer(UdpPeer *peer)
{
RsStackMutex stack(sortMtx); /********** LOCK MUTEX *********/
/* check for duplicate */
std::map<struct sockaddr_in, UdpPeer *>::iterator it;
for(it = streams.begin(); it != streams.end(); it++)
{
if (it->second == peer)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::removeUdpPeer() SUCCESS" << std::endl;
#endif
streams.erase(it);
return 1;
}
}
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::removeUdpPeer() ERROR" << std::endl;
#endif
return 0;
}
/******************************* STUN Handling ********************************/

View File

@ -71,6 +71,7 @@ virtual ~UdpSorter() { return; }
/* add a TCPonUDP stream */
int addUdpPeer(UdpPeer *peer, const struct sockaddr_in &raddr);
int removeUdpPeer(UdpPeer *peer);
bool setStunKeepAlive(uint32_t required);
bool addStunPeer(const struct sockaddr_in &remote, const char *peerid);

View File

@ -164,6 +164,8 @@ void PeersDialog::insertPeers()
QTreeWidget *peerWidget = ui.peertreeWidget;
QTreeWidgetItem *oldSelect = getCurrentPeer();
QTreeWidgetItem *newSelect = NULL;
time_t now = time(NULL);
std::string oldId;
if (oldSelect)
{
@ -200,7 +202,7 @@ void PeersDialog::insertPeers()
item -> setText(2, QString::fromStdString(detail.name));
/* (2) Auto Connect */
item -> setText(3, QString::fromStdString("Yes"));
item -> setText(3, QString::fromStdString(detail.autoconnect));
/* (3) Trust Level */
item -> setText(4,QString::fromStdString(
@ -219,7 +221,7 @@ void PeersDialog::insertPeers()
/* less important ones */
/* () Last Contact */
item -> setText(6,QString::fromStdString(
RsPeerLastConnectString(detail.lastConnect)));
RsPeerLastConnectString(now - detail.lastConnect)));
/* () Org */
item -> setText(7, QString::fromStdString(detail.org));
@ -271,7 +273,7 @@ void PeersDialog::insertPeers()
}
else
{
if (detail.lastConnect < 10000)
if (now - detail.lastConnect < 3600)
{
for(i = 1; i < 12; i++)
{

View File

@ -101,6 +101,7 @@ class RsPeerDetails
/* basic stats */
uint32_t lastConnect; /* how long ago */
std::string autoconnect;
uint32_t connectPeriod;
};