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

@ -63,7 +63,19 @@ static int tou_tick_all();
int tou_init(const struct sockaddr *my_addr, socklen_t addrlen)
{
if (tou_inited)
{
struct sockaddr_in *addr = (struct sockaddr_in *) my_addr;
udps->resetAddress(*addr);
if (!(udps->okay()))
{
std::cerr << "tou_init() FATAL ERROR: Cannot reset Udp Socket to: "
<< inet_ntoa(addr->sin_addr) << ":" << ntohs(addr->sin_port);
std::cerr << std::endl;
exit(1);
}
return 1;
}
tou_streams.resize(kInitStreamTable);
@ -101,6 +113,36 @@ int tou_stunkeepalive(int required)
return 1;
}
int tou_getstunpeer(int i, struct sockaddr *remote_addr, socklen_t *raddrlen,
struct sockaddr *ext_addr, socklen_t *eaddrlen,
uint32_t *failCount, time_t *lastSend)
{
if (!tou_inited)
return -1;
std::string id;
bool ret = udps->getStunPeer(i, id,
*((struct sockaddr_in *) remote_addr),
*((struct sockaddr_in *) ext_addr),
*failCount, *lastSend);
return ret;
}
int tou_needstunpeers()
{
if (!tou_inited)
return -1;
if (udps->needStunPeers())
return 1;
return 0;
}
int tou_tick_stunkeepalive()
{
if (!tou_inited)

View file

@ -79,6 +79,10 @@ int tou_stunpeer(const struct sockaddr *ext_addr, socklen_t addrlen, const char
int tou_stunkeepalive(int required);
int tou_tick_stunkeepalive();
int tou_getstunpeer(int i, struct sockaddr *remote_addr, socklen_t *raddrlen,
struct sockaddr *ext_addr, socklen_t *eaddrlen,
uint32_t *failCount, time_t *lastSend);
int tou_needstunpeers();
/* Connections are as similar to UNIX as possible

View file

@ -178,6 +178,33 @@ int UdpLayer::status(std::ostream &out)
return 1;
}
int UdpLayer::reset(struct sockaddr_in &local)
{
std::cerr << "UdpLayer::reset()" << std::endl;
/* stop the old thread */
{
RsStackMutex stack(sockMtx); /********** LOCK MUTEX *********/
std::cerr << "UdpLayer::reset() setting stopThread flag" << std::endl;
stopThread = true;
}
std::cerr << "UdpLayer::reset() joining" << std::endl;
join();
std::cerr << "UdpLayer::reset() closing socket" << std::endl;
close();
std::cerr << "UdpLayer::reset() resetting variables" << std::endl;
laddr = local;
errorState = 0;
ttl = UDP_DEF_TTL;
std::cerr << "UdpLayer::reset() opening socket" << std::endl;
openSocket();
}
int UdpLayer::close()
{
/* close socket if open */
@ -210,7 +237,21 @@ void UdpLayer::recv_loop()
{
/* select on the socket TODO */
fd_set rset;
for(;;) {
for(;;)
{
/* check if we need to stop */
bool toStop = false;
{
RsStackMutex stack(sockMtx); /********** LOCK MUTEX *********/
toStop = stopThread;
}
if (toStop)
{
std::cerr << "UdpLayer::recv_loop() stopping thread" << std::endl;
stop();
}
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
timeout.tv_sec = 0;
@ -311,6 +352,13 @@ int UdpLayer::openSocket()
#endif
setTTL(UDP_DEF_TTL);
// start up our thread.
{
RsStackMutex stack(sockMtx); /********** LOCK MUTEX *********/
stopThread = false;
}
start();
return 1;
}

View file

@ -70,9 +70,12 @@ class UdpLayer: public RsThread
UdpLayer(UdpReceiver *recv, struct sockaddr_in &local);
virtual ~UdpLayer() { return; }
int reset(struct sockaddr_in &local); /* calls join, close, openSocket */
int status(std::ostream &out);
/* setup connections */
int close();
int openSocket();
/* RsThread functions */
@ -88,7 +91,6 @@ void recv_loop(); /* uses callback to UdpReceiver */
int okay();
int tick();
int close();
/* data */
/* internals */
@ -110,6 +112,7 @@ virtual int sendUdpPacket(const void *data, int size, struct sockaddr_in &to);
int errorState;
int sockfd;
int ttl;
bool stopThread;
RsMutex sockMtx;
};

View file

@ -37,11 +37,20 @@ const int rsudpsorterzone = 28477;
static const int STUN_TTL = 64;
#define TOU_STUN_MIN_PEERS 5
/*
* #define DEBUG_UDP_SORTER 1
*/
const int32_t TOU_STUN_MAX_FAIL_COUNT = 3; /* 3 tries (could be higher?) */
const int32_t TOU_STUN_MAX_SEND_RATE = 5; /* every 5 seconds */
const int32_t TOU_STUN_MAX_RECV_RATE = 25; /* every 25 seconds */
const int32_t TOU_STUN_ADDR_MAX_AGE = 120; /* 2 minutes */
UdpSorter::UdpSorter(struct sockaddr_in &local)
:udpLayer(NULL), laddr(local), eaddrKnown(false), eaddrStable(false),
mStunKeepAlive(false), mStunLastRecv(0), mStunLastSend(0)
@ -54,6 +63,12 @@ UdpSorter::UdpSorter(struct sockaddr_in &local)
return;
}
bool UdpSorter::resetAddress(struct sockaddr_in &local)
{
return udpLayer->reset(local);
}
/* higher level interface */
void UdpSorter::recvPkt(void *data, int size, struct sockaddr_in &from)
@ -148,7 +163,9 @@ int UdpSorter::status(std::ostream &out)
int UdpSorter::openSocket()
{
udpLayer = new UdpLayer(this, laddr);
udpLayer->start();
// start is called by udpLayer now, for consistency
// with reset!
//udpLayer->start();
return 1;
}
@ -301,8 +318,19 @@ bool UdpSorter::locked_handleStunPkt(void *data, int size, struct sockaddr_in &f
bool UdpSorter::externalAddr(struct sockaddr_in &external, uint8_t &stable)
{
RsStackMutex stack(sortMtx); /********** LOCK MUTEX *********/
if (eaddrKnown)
{
/* address timeout */
if (time(NULL) - eaddrTime > TOU_STUN_ADDR_MAX_AGE)
{
std::cerr << "UdpSorter::externalAddr() eaddr expired";
std::cerr << std::endl;
return false;
}
external = eaddr;
if (eaddrStable)
@ -310,8 +338,15 @@ bool UdpSorter::externalAddr(struct sockaddr_in &external, uint8_t &stable)
else
stable = 0;
std::cerr << "UdpSorter::externalAddr() eaddr:" << inet_ntoa(external.sin_addr);
std::cerr << ":" << ntohs(external.sin_port) << " stable: " << (int) stable;
std::cerr << std::endl;
return true;
}
std::cerr << "UdpSorter::externalAddr() eaddr unknown";
std::cerr << std::endl;
return false;
}
@ -503,14 +538,8 @@ bool UdpStun_isStunPacket(void *data, int size)
/******************************* STUN Handling ********************************
* The KeepAlive part - slightly more complicated
*
*
*/
const int32_t TOU_STUN_MAX_FAIL_COUNT = 10; /* 10 tries (could be higher?) */
const int32_t TOU_STUN_MAX_SEND_RATE = 5; /* every 5 seconds */
const int32_t TOU_STUN_MAX_RECV_RATE = 25; /* every 25 seconds */
/******************************* STUN Handling ********************************/
bool UdpSorter::setStunKeepAlive(uint32_t required)
@ -536,12 +565,13 @@ bool UdpSorter::addStunPeer(const struct sockaddr_in &remote, const char *pee
std::cerr << std::endl;
#endif
storeStunPeer(remote, peerid);
sortMtx.lock(); /********** LOCK MUTEX *********/
bool needStun = (!eaddrKnown);
sortMtx.unlock(); /******** UNLOCK MUTEX *********/
storeStunPeer(remote, peerid, needStun);
if (needStun)
{
doStun(remote);
@ -550,7 +580,7 @@ bool UdpSorter::addStunPeer(const struct sockaddr_in &remote, const char *pee
return true;
}
bool UdpSorter::storeStunPeer(const struct sockaddr_in &remote, const char *peerid)
bool UdpSorter::storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool sent)
{
#ifdef DEBUG_UDP_SORTER
@ -571,11 +601,22 @@ bool UdpSorter::storeStunPeer(const struct sockaddr_in &remote, const char *p
std::cerr << std::endl;
#endif
/* already there */
if (sent)
{
it->failCount += 1;
it->lastsend = time(NULL);
}
return false;
}
}
TouStunPeer peer(std::string(peerid), remote);
if (sent)
{
peer.failCount += 1;
peer.lastsend = time(NULL);
}
mStunList.push_back(peer);
#ifdef DEBUG_UDP_SORTER
@ -704,10 +745,7 @@ bool UdpSorter::locked_recvdStun(const struct sockaddr_in &remote, const stru
locked_printStunList();
#endif
if (!eaddrKnown)
{
locked_checkExternalAddress();
}
locked_checkExternalAddress();
return found;
}
@ -722,13 +760,23 @@ bool UdpSorter::locked_checkExternalAddress()
bool found1 = false;
bool found2 = false;
std::list<TouStunPeer>::iterator it;
std::list<TouStunPeer>::iterator p1;
std::list<TouStunPeer>::iterator p2;
for(it = mStunList.begin(); it != mStunList.end(); it++)
time_t now = time(NULL);
/* iterator backwards - as these are the most recent */
std::list<TouStunPeer>::reverse_iterator it;
std::list<TouStunPeer>::reverse_iterator p1;
std::list<TouStunPeer>::reverse_iterator p2;
for(it = mStunList.rbegin(); it != mStunList.rend(); it++)
{
if (it->response && isExternalNet(&(it->eaddr.sin_addr)))
/* check:
1) have response.
2) have eaddr.
3) no fails.
4) recent age.
*/
time_t age = (now - it->lastsend);
if (it->response && isExternalNet(&(it->eaddr.sin_addr)) &&
(it->failCount == 0) && (age < TOU_STUN_ADDR_MAX_AGE))
{
if (!found1)
{
@ -757,6 +805,7 @@ bool UdpSorter::locked_checkExternalAddress()
}
eaddrKnown = true;
eaddr = p1->eaddr;
eaddrTime = now;
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::locked_checkExternalAddress() Found State:";
@ -803,6 +852,36 @@ bool UdpSorter::locked_printStunList()
return true;
}
bool UdpSorter::getStunPeer(int idx, std::string &id,
struct sockaddr_in &remote, struct sockaddr_in &eaddr,
uint32_t &failCount, time_t &lastSend)
{
RsStackMutex stack(sortMtx); /********** LOCK MUTEX *********/
std::list<TouStunPeer>::iterator it;
int i;
for(i=0, it=mStunList.begin(); (i<idx) && (it!=mStunList.end()); it++, i++);
if (it != mStunList.end())
{
id = RsUtil::BinToHex(it->id);
remote = it->remote;
eaddr = it->eaddr;
failCount = it->failCount;
lastSend = it->lastsend;
return true;
}
return false;
}
bool UdpSorter::needStunPeers()
{
RsStackMutex stack(sortMtx); /********** LOCK MUTEX *********/
return (mStunList.size() < TOU_STUN_MIN_PEERS);
}

View file

@ -49,10 +49,20 @@ class TouStunPeer
{
public:
TouStunPeer()
:response(false), lastsend(0), failCount(0) { return; }
:response(false), lastsend(0), failCount(0)
{
eaddr.sin_addr.s_addr = 0;
eaddr.sin_port = 0;
return;
}
TouStunPeer(std::string id_in, const struct sockaddr_in &addr)
:id(id_in), remote(addr), response(false), lastsend(0), failCount(0) { return; }
:id(id_in), remote(addr), response(false), lastsend(0), failCount(0)
{
eaddr.sin_addr.s_addr = 0;
eaddr.sin_port = 0;
return;
}
std::string id;
struct sockaddr_in remote, eaddr;
@ -69,13 +79,20 @@ class UdpSorter: public UdpReceiver
UdpSorter(struct sockaddr_in &local);
virtual ~UdpSorter() { return; }
bool resetAddress(struct sockaddr_in &local);
/* 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);
bool getStunPeer(int idx, std::string &id,
struct sockaddr_in &remote, struct sockaddr_in &eaddr,
uint32_t &failCount, time_t &lastSend);
bool checkStunKeepAlive();
bool needStunPeers();
bool externalAddr(struct sockaddr_in &remote, uint8_t &stable);
@ -109,7 +126,7 @@ bool locked_printStunList();
bool locked_recvdStun(const struct sockaddr_in &remote, const struct sockaddr_in &extaddr);
bool locked_checkExternalAddress();
bool storeStunPeer(const struct sockaddr_in &remote, const char *peerid);
bool storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool sent);
UdpLayer *udpLayer;
@ -120,6 +137,7 @@ bool storeStunPeer(const struct sockaddr_in &remote, const char *peerid);
struct sockaddr_in eaddr; /* external addr */
bool eaddrKnown;
bool eaddrStable; /* if true then usable. if false -> Symmettric NAT */
time_t eaddrTime;
bool mStunKeepAlive;
time_t mStunLastRecv;