mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-24 14:23:36 -05:00
Merged Changes /branches/v0.5-peernet/libretroshare/:r4237-4358
Major changes are: * Improvements to tcponudp library to allow multiple UdpStacks / ports, with alternative recievers. * Resurrected the UdpStunner code, and improved it. * Added UdpRelay code. * Modified startup code and ssludp code to use the new tcponudp and add a stunner. * fixed buggy rs_inet_ntoa * fixed a bunch of apple gcc warnings. mainly for(;;); => for(;;) ; These changes shouldn't affect libretroshare stability... those changes will follow! git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@4359 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
d58f838269
commit
b683e663d6
@ -688,7 +688,7 @@ bool ftTransferModule::checkCRC()
|
||||
int n = rand()%(mFileSources.size()) ;
|
||||
int p=0 ;
|
||||
std::map<std::string,peerInfo>::const_iterator mit ;
|
||||
for(mit = mFileSources.begin();mit != mFileSources.end() && p<n;++mit,++p);
|
||||
for(mit = mFileSources.begin();mit != mFileSources.end() && p<n;++mit,++p) ;
|
||||
|
||||
#ifdef FT_DEBUG
|
||||
std::cerr << "ftTransferModule::checkCRC(): sending CRC map request to source " << mit->first << std::endl ;
|
||||
|
@ -73,12 +73,16 @@ HEADERS += tcponudp/udppeer.h \
|
||||
tcponudp/tcppacket.h \
|
||||
tcponudp/tcpstream.h \
|
||||
tcponudp/tou.h \
|
||||
tcponudp/udpstunner.h \
|
||||
tcponudp/udprelay.h \
|
||||
|
||||
SOURCES += tcponudp/udppeer.cc \
|
||||
tcponudp/tcppacket.cc \
|
||||
tcponudp/tcpstream.cc \
|
||||
tcponudp/tou.cc \
|
||||
tcponudp/bss_tou.c \
|
||||
tcponudp/udpstunner.cc \
|
||||
tcponudp/udprelay.cc \
|
||||
|
||||
# These two aren't actually used (and don't compile) ....
|
||||
# but could be useful later
|
||||
|
@ -1637,7 +1637,7 @@ bool p3DhtMgr::dhtResultNotify(std::string idhash)
|
||||
time_t now = time(NULL);
|
||||
|
||||
/* if notify - we must match on the second hash */
|
||||
for(it = peers.begin(); (it != peers.end()) && ((it->second).hash2 != idhash); it++);
|
||||
for(it = peers.begin(); (it != peers.end()) && ((it->second).hash2 != idhash); it++) ;
|
||||
|
||||
/* update data */
|
||||
std::string peerid;
|
||||
@ -1697,7 +1697,7 @@ bool p3DhtMgr::dhtResultSearch(std::string idhash,
|
||||
dhtPeerEntry ent;
|
||||
|
||||
/* if search - we must match on the second hash */
|
||||
for(it = peers.begin(); (it != peers.end()) && ((it->second).hash1 != idhash); it++);
|
||||
for(it = peers.begin(); (it != peers.end()) && ((it->second).hash1 != idhash); it++) ;
|
||||
|
||||
/* update data */
|
||||
/* ignore OFF peers */
|
||||
|
@ -99,7 +99,9 @@ int pqissludp::reset()
|
||||
|
||||
int pqissludp::attach()
|
||||
{
|
||||
sockfd = tou_socket(0,0,0);
|
||||
// IN THE IMPROVED TOU LIBRARY, we need to be careful with the tou_socket PARAMETERS.
|
||||
// For now, this should do!
|
||||
sockfd = tou_socket(0,TOU_RECEIVER_TYPE_UDPPEER,0);
|
||||
if (0 > sockfd)
|
||||
{
|
||||
rslog(RSL_WARNING, pqissludpzone,
|
||||
|
@ -585,7 +585,9 @@ X509 *loadX509FromDER(const uint8_t *ptr, uint32_t len)
|
||||
|
||||
X509 *tmp = NULL;
|
||||
#ifdef __APPLE__
|
||||
// This depends on which version you are compiling for... OSX10.5 doesn't have consts (old OpenSSL!)
|
||||
unsigned char **certptr = (unsigned char **) &ptr;
|
||||
//const unsigned char **certptr = (const unsigned char **) &ptr;
|
||||
#else
|
||||
const unsigned char **certptr = (const unsigned char **) &ptr;
|
||||
#endif
|
||||
|
@ -57,6 +57,8 @@
|
||||
#include "pqi/sslfns.h"
|
||||
#include "pqi/authgpg.h"
|
||||
|
||||
#include "tcponudp/udpstunner.h"
|
||||
|
||||
class accountId
|
||||
{
|
||||
public:
|
||||
@ -1739,6 +1741,8 @@ RsTurtle *rsTurtle = NULL ;
|
||||
#ifdef RS_USE_BITDHT
|
||||
#include "dht/p3bitdht.h"
|
||||
#include "udp/udpstack.h"
|
||||
#include "tcponudp/udppeer.h"
|
||||
#include "tcponudp/udprelay.h"
|
||||
#endif
|
||||
|
||||
/****
|
||||
@ -1882,11 +1886,58 @@ int RsServer::StartupRetroShare()
|
||||
}
|
||||
}
|
||||
|
||||
p3BitDht *mBitDht = new p3BitDht(ownId, mConnMgr,
|
||||
mUdpStack, bootstrapfile);
|
||||
/* construct the rest of the stack, important to build them in the correct order! */
|
||||
/* MOST OF THIS IS COMMENTED OUT UNTIL THE REST OF libretroshare IS READY FOR IT! */
|
||||
|
||||
UdpSubReceiver *udpReceivers[3];
|
||||
int udpTypes[3];
|
||||
|
||||
// FIRST DHT STUNNER.
|
||||
UdpStunner *mDhtStunner = new UdpStunner(mUdpStack);
|
||||
mDhtStunner->setTargetStunPeriod(0); /* passive */
|
||||
//mDhtStunner->setTargetStunPeriod(300); /* slow (5mins) */
|
||||
mUdpStack->addReceiver(mDhtStunner);
|
||||
|
||||
// NEXT BITDHT.
|
||||
p3BitDht *mBitDht = new p3BitDht(ownId, mConnMgr, mUdpStack, bootstrapfile);
|
||||
|
||||
// NEXT THE RELAY (NEED to keep a reference for installing RELAYS)
|
||||
//UdpRelayReceiver *mRelayRecver = new UdpRelayReceiver(mUdpStack);
|
||||
//udpReceivers[2] = mRelayRecver; /* RELAY Connections (DHT Port) */
|
||||
//udpTypes[2] = TOU_RECEIVER_TYPE_UDPRELAY;
|
||||
//mUdpStack->addReceiver(udpReceivers[2]);
|
||||
|
||||
// LAST ON THIS STACK IS STANDARD DIRECT TOU
|
||||
udpReceivers[0] = new UdpPeerReceiver(mUdpStack); /* standard DIRECT Connections (DHT Port) */
|
||||
udpTypes[0] = TOU_RECEIVER_TYPE_UDPPEER;
|
||||
mUdpStack->addReceiver(udpReceivers[0]);
|
||||
|
||||
// NOW WE BUILD THE SECOND STACK.
|
||||
// Create the Second UdpStack... Port should be random (but openable!).
|
||||
//struct sockaddr_in sndladdr;
|
||||
//sockaddr_clear(&sndladdr);
|
||||
//sndladdr.sin_port = htons(RsInitConfig::port + 1111);
|
||||
//rsUdpStack *mUdpProxyStack = new rsUdpStack(sndladdr);
|
||||
|
||||
// FIRSTLY THE PROXY STUNNER.
|
||||
//UdpStunner *mProxyStunner = new UdpStunner(mUdpProxyStack);
|
||||
// USE DEFAULT PERIOD... mDhtStunner->setTargetStunPeriod(300); /* slow (5mins) */
|
||||
//mUdpStack->addReceiver(mDhtStunner);
|
||||
|
||||
|
||||
// FINALLY THE PROXY UDP CONNECTIONS
|
||||
//udpReceivers[1] = new UdpPeerReceiver(mUdpProxyStack); /* PROXY Connections (Alt UDP Port) */
|
||||
//udpTypes[1] = TOU_RECEIVER_TYPE_UDPPEER;
|
||||
//mUdpProxyStack->addReceiver(udpReceivers[1]);
|
||||
|
||||
|
||||
// NOW WE CAN PASS THE RECEIVERS TO TOU.
|
||||
// temp initialisation of only the DIRECT TOU.
|
||||
tou_init((void **) udpReceivers, udpTypes, 1);
|
||||
|
||||
// REAL INITIALISATION - WITH THREE MODES - FOR LATER.
|
||||
//tou_init((void **) udpReceivers, udpTypes, 3);
|
||||
|
||||
/* construct the rest of the stack */
|
||||
tou_init(mUdpStack);
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -611,7 +611,7 @@ bool p3GameLauncher::confirmPeer(std::string gameId, std::string peerId,
|
||||
|
||||
int32_t i = 0;
|
||||
for(it = git->second.peerIds.begin(); (i < pos) &&
|
||||
(it != git->second.peerIds.end()); it++, i++);
|
||||
(it != git->second.peerIds.end()); it++, i++) ;
|
||||
|
||||
if ((pos < 0) || (it == git->second.peerIds.end()))
|
||||
{
|
||||
|
@ -829,7 +829,7 @@ bool p3Ranking::getRankings(uint32_t first, uint32_t count, std::list<std::st
|
||||
|
||||
uint32_t i = 0;
|
||||
std::multimap<float, std::string>::reverse_iterator rit;
|
||||
for(rit = mRankings.rbegin(); (i < first) && (rit != mRankings.rend()); rit++, i++);
|
||||
for(rit = mRankings.rbegin(); (i < first) && (rit != mRankings.rend()); rit++, i++) ;
|
||||
|
||||
i = 0;
|
||||
for(; (i < count) && (rit != mRankings.rend()); rit++, i++)
|
||||
|
@ -71,7 +71,7 @@ static const double RTT_ALPHA = 0.875;
|
||||
// platform independent fractional timestamp.
|
||||
static double getCurrentTS();
|
||||
|
||||
TcpStream::TcpStream(UdpPeerReceiver *lyr)
|
||||
TcpStream::TcpStream(UdpSubReceiver *lyr)
|
||||
:inSize(0), outSizeRead(0), outSizeNet(0),
|
||||
state(TCP_CLOSED),
|
||||
inStreamActive(false),
|
||||
|
@ -73,7 +73,7 @@ class TcpStream: public UdpPeer
|
||||
public:
|
||||
/* Top-Level exposed */
|
||||
|
||||
TcpStream(UdpPeerReceiver *udp);
|
||||
TcpStream(UdpSubReceiver *udp);
|
||||
virtual ~TcpStream() { return; }
|
||||
|
||||
/* user interface */
|
||||
@ -230,8 +230,8 @@ uint32 int_rbytes();
|
||||
struct sockaddr_in peeraddr;
|
||||
bool peerKnown;
|
||||
|
||||
/* UdpPeerReceiver (has own Mutex!) */
|
||||
UdpPeerReceiver *udp;
|
||||
/* UdpSubReceiver (has own Mutex!) */
|
||||
UdpSubReceiver *udp;
|
||||
|
||||
};
|
||||
|
||||
|
@ -47,6 +47,8 @@ struct TcpOnUdp_t
|
||||
int tou_fd;
|
||||
int lasterrno;
|
||||
TcpStream *tcp;
|
||||
UdpSubReceiver *udpsr;
|
||||
int udptype;
|
||||
bool idle;
|
||||
};
|
||||
|
||||
@ -57,42 +59,82 @@ static std::vector<TcpOnUdp *> tou_streams;
|
||||
static int tou_inited = 0;
|
||||
|
||||
|
||||
#include "udp/udpstack.h"
|
||||
#include "tcponudp/udppeer.h"
|
||||
#include "tcponudp/udprelay.h"
|
||||
|
||||
static UdpStack *udpstack = NULL;
|
||||
static UdpPeerReceiver *udps = NULL;
|
||||
static UdpSubReceiver *udpSR[MAX_TOU_RECEIVERS] = {NULL};
|
||||
static uint32_t udpType[MAX_TOU_RECEIVERS] = {NULL};
|
||||
static uint32_t noUdpSR = 0;
|
||||
|
||||
static int tou_tick_all();
|
||||
|
||||
/* tou_init
|
||||
*
|
||||
* Modified to accept a number of UdpSubRecievers!
|
||||
* these can be linked to arbitary UdpStacks.
|
||||
* (removed all UdpStack references here!)
|
||||
*
|
||||
* Unfortunately, the UdpSubReceivers have different initialisation for starting a connection.
|
||||
* So the TOU interface has to accomodate this.
|
||||
*
|
||||
*/
|
||||
/* tou_init - opens the udp port (universal bind) */
|
||||
int tou_init(void *in_udpstack)
|
||||
int tou_init(void **in_udpsubrecvs, int *type, int number)
|
||||
{
|
||||
UdpStack *stack = (UdpStack *) in_udpstack;
|
||||
UdpSubReceiver **usrArray = (UdpSubReceiver **) in_udpsubrecvs;
|
||||
if (number > MAX_TOU_RECEIVERS)
|
||||
{
|
||||
std::cerr << "tou_init() Invalid number of receivers";
|
||||
std::cerr << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tou_inited)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
tou_streams.resize(kInitStreamTable);
|
||||
noUdpSR = number;
|
||||
int i;
|
||||
for(i = 0; i < noUdpSR; i++)
|
||||
{
|
||||
udpSR[i] = usrArray[i];
|
||||
udpType[i] = type[i];
|
||||
}
|
||||
|
||||
udpstack = stack;
|
||||
udps = new UdpPeerReceiver(stack);
|
||||
stack->addReceiver(udps);
|
||||
tou_streams.resize(kInitStreamTable);
|
||||
|
||||
tou_inited = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* open - which does nothing */
|
||||
int tou_socket(int /*domain*/, int /*type*/, int /*protocol*/)
|
||||
/* open - allocates a sockfd, and checks that the type is okay */
|
||||
int tou_socket(int recvIdx, int type, int /*protocol*/)
|
||||
{
|
||||
if (!tou_inited)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (recvIdx >= noUdpSR)
|
||||
{
|
||||
std::cerr << "tou_socket() ERROR recvIdx greater than #receivers";
|
||||
std::cerr << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check that the index matches the type */
|
||||
UdpSubReceiver *recver = udpSR[recvIdx];
|
||||
uint32_t recverType = udpType[recvIdx];
|
||||
|
||||
if (recverType != type)
|
||||
{
|
||||
std::cerr << "tou_socket() ERROR type doesn't match expected type";
|
||||
std::cerr << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(unsigned int i = 1; i < tou_streams.size(); i++)
|
||||
{
|
||||
if (tou_streams[i] == NULL)
|
||||
@ -100,6 +142,8 @@ int tou_socket(int /*domain*/, int /*type*/, int /*protocol*/)
|
||||
tou_streams[i] = new TcpOnUdp();
|
||||
tou_streams[i] -> tou_fd = i;
|
||||
tou_streams[i] -> tcp = NULL;
|
||||
tou_streams[i] -> udpsr = recver;
|
||||
tou_streams[i] -> udptype = recverType;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -112,6 +156,8 @@ int tou_socket(int /*domain*/, int /*type*/, int /*protocol*/)
|
||||
{
|
||||
tou -> tou_fd = tou_streams.size() -1;
|
||||
tou -> tcp = NULL;
|
||||
tou -> udpsr = recver;
|
||||
tou -> udptype = recverType;
|
||||
return tou->tou_fd;
|
||||
}
|
||||
|
||||
@ -158,11 +204,35 @@ int tou_connect(int sockfd, const struct sockaddr *serv_addr,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* enforce that the udptype is correct */
|
||||
if (tous -> udptype != TOU_RECEIVER_TYPE_UDPPEER)
|
||||
{
|
||||
std::cerr << "tou_connect() ERROR connect method invalid for udptype";
|
||||
std::cerr << std::endl;
|
||||
tous -> lasterrno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TOU_DYNAMIC_CAST_CHECK
|
||||
/* extra checking -> for testing purposes (dynamic cast) */
|
||||
UdpPeerReceiver *upr = dynamic_cast<UdpPeerReceiver *>(tous->udpsr);
|
||||
if (!upr)
|
||||
{
|
||||
std::cerr << "tou_connect() ERROR cannot convert type to UdpPeerReceiver";
|
||||
std::cerr << std::endl;
|
||||
tous -> lasterrno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr);
|
||||
#endif
|
||||
|
||||
/* create a TCP stream to connect with. */
|
||||
if (!tous->tcp)
|
||||
{
|
||||
tous->tcp = new TcpStream(udps);
|
||||
udps->addUdpPeer(tous->tcp,
|
||||
tous->tcp = new TcpStream(tous->udpsr);
|
||||
upr->addUdpPeer(tous->tcp,
|
||||
*((const struct sockaddr_in *) serv_addr));
|
||||
}
|
||||
|
||||
@ -178,6 +248,7 @@ int tou_connect(int sockfd, const struct sockaddr *serv_addr,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* is this ever used? should it be depreciated? */
|
||||
int tou_listenfor(int sockfd, const struct sockaddr *serv_addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
@ -193,11 +264,34 @@ int tou_listenfor(int sockfd, const struct sockaddr *serv_addr,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* enforce that the udptype is correct */
|
||||
if (tous -> udptype != TOU_RECEIVER_TYPE_UDPPEER)
|
||||
{
|
||||
std::cerr << "tou_connect() ERROR connect method invalid for udptype";
|
||||
std::cerr << std::endl;
|
||||
tous -> lasterrno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef TOU_DYNAMIC_CAST_CHECK
|
||||
/* extra checking -> for testing purposes (dynamic cast) */
|
||||
UdpPeerReceiver *upr = dynamic_cast<UdpPeerReceiver *>(tous->udpsr);
|
||||
if (!upr)
|
||||
{
|
||||
std::cerr << "tou_connect() ERROR cannot convert type to UdpPeerReceiver";
|
||||
std::cerr << std::endl;
|
||||
tous -> lasterrno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr);
|
||||
#endif
|
||||
|
||||
/* create a TCP stream to connect with. */
|
||||
if (!tous->tcp)
|
||||
{
|
||||
tous->tcp = new TcpStream(udps);
|
||||
udps->addUdpPeer(tous->tcp,
|
||||
tous->tcp = new TcpStream(tous->udpsr);
|
||||
upr->addUdpPeer(tous->tcp,
|
||||
*((const struct sockaddr_in *) serv_addr));
|
||||
}
|
||||
|
||||
@ -214,6 +308,84 @@ int tou_listen(int /* sockfd */ , int /* backlog */ )
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the alternative RELAY connection.
|
||||
*
|
||||
* User needs to provide 3 ip addresses.
|
||||
* These addresses should have been provided by the RELAY negogiation
|
||||
* a) own ip:port
|
||||
* b) proxy ip:port
|
||||
* c) dest ip:port
|
||||
*
|
||||
* The reset of the startup is similar to other TOU connections.
|
||||
* As this is likely to be run over an established UDP connection,
|
||||
* there is little need for a big connection period.
|
||||
*
|
||||
* - like a tcp/ip connection, the connect
|
||||
* will return -1 EAGAIN, until connection complete.
|
||||
* - always non blocking.
|
||||
*/
|
||||
#define DEFAULT_RELAY_CONN_PERIOD 1
|
||||
|
||||
int tou_connect_via_relay(int sockfd,
|
||||
const struct sockaddr_in *own_addr,
|
||||
const struct sockaddr_in *proxy_addr,
|
||||
const struct sockaddr_in *dest_addr)
|
||||
|
||||
{
|
||||
if (tou_streams[sockfd] == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
TcpOnUdp *tous = tou_streams[sockfd];
|
||||
|
||||
/* enforce that the udptype is correct */
|
||||
if (tous -> udptype != TOU_RECEIVER_TYPE_UDPRELAY)
|
||||
{
|
||||
std::cerr << "tou_connect() ERROR connect method invalid for udptype";
|
||||
std::cerr << std::endl;
|
||||
tous -> lasterrno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef TOU_DYNAMIC_CAST_CHECK
|
||||
/* extra checking -> for testing purposes (dynamic cast) */
|
||||
UdpRelayReceiver *urr = dynamic_cast<UdpRelayReceiver *>(tous->udpsr);
|
||||
if (!urr)
|
||||
{
|
||||
std::cerr << "tou_connect() ERROR cannot convert type to UdpRelayReceiver";
|
||||
std::cerr << std::endl;
|
||||
tous -> lasterrno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
UdpRelayReceiver *urr = (UdpRelayReceiver *) (tous->udpsr);
|
||||
#endif
|
||||
|
||||
/* create a TCP stream to connect with. */
|
||||
if (!tous->tcp)
|
||||
{
|
||||
tous->tcp = new TcpStream(tous->udpsr);
|
||||
|
||||
UdpRelayAddrSet addrSet(own_addr, dest_addr);
|
||||
urr->addUdpPeer(tous->tcp, &addrSet, proxy_addr);
|
||||
}
|
||||
|
||||
/* We Point it at the Destination Address.
|
||||
* The UdpRelayReceiver wraps and re-directs the packets to the proxy
|
||||
*/
|
||||
tous->tcp->connect(*dest_addr, DEFAULT_RELAY_CONN_PERIOD);
|
||||
tous->tcp->tick();
|
||||
tou_tick_all();
|
||||
if (tous->tcp->isConnected())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
tous -> lasterrno = EINPROGRESS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* slightly different - returns sockfd on connection */
|
||||
int tou_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
|
||||
@ -362,8 +534,50 @@ int tou_close(int sockfd)
|
||||
|
||||
/* shut it down */
|
||||
tous->tcp->close();
|
||||
udps->removeUdpPeer(tous->tcp);
|
||||
|
||||
/* now we need to work out which type of receiver we have */
|
||||
#ifdef TOU_DYNAMIC_CAST_CHECK
|
||||
/* extra checking -> for testing purposes (dynamic cast) */
|
||||
UdpRelayReceiver *urr = dynamic_cast<UdpRelayReceiver *>(tous->udpsr);
|
||||
UdpPeerReceiver *upr = dynamic_cast<UdpPeerReceiver *>(tous->udpsr);
|
||||
if (urr)
|
||||
{
|
||||
urr->removeUdpPeer(tous->tcp);
|
||||
}
|
||||
else if (upr)
|
||||
{
|
||||
upr->removeUdpPeer(tous->tcp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* error */
|
||||
std::cerr << "tou_close() ERROR unknown udptype";
|
||||
std::cerr << std::endl;
|
||||
tous -> lasterrno = EINVAL;
|
||||
}
|
||||
#else
|
||||
if (tous -> udptype == TOU_RECEIVER_TYPE_UDPRELAY)
|
||||
{
|
||||
UdpRelayReceiver *urr = (UdpRelayReceiver *) (tous->udpsr);
|
||||
urr->removeUdpPeer(tous->tcp);
|
||||
}
|
||||
else if (tous -> udptype == TOU_RECEIVER_TYPE_UDPPEER)
|
||||
{
|
||||
UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr);
|
||||
upr->removeUdpPeer(tous->tcp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* error */
|
||||
std::cerr << "tou_close() ERROR unknown udptype";
|
||||
std::cerr << std::endl;
|
||||
tous -> lasterrno = EINVAL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
delete tous->tcp;
|
||||
|
||||
}
|
||||
|
||||
delete tous;
|
||||
@ -374,10 +588,6 @@ int tou_close(int sockfd)
|
||||
/* get an error number */
|
||||
int tou_errno(int sockfd)
|
||||
{
|
||||
if (!udps)
|
||||
{
|
||||
return ENOTSOCK;
|
||||
}
|
||||
if (tou_streams[sockfd] == NULL)
|
||||
{
|
||||
return ENOTSOCK;
|
||||
|
@ -50,22 +50,34 @@
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* standard C interface (as Unix-like as possible)
|
||||
* for the tou (Tcp On Udp) library
|
||||
*/
|
||||
/*
|
||||
* Init:
|
||||
* (1) need UdpStack item, which has our address already.
|
||||
* The TOU library no longer references any UdpStack items.
|
||||
* instead, two arrays should be passed to the init function.
|
||||
* int tou_init( (void **) UdpSubReceiver **udpRecvers, int *udpType, int nUdps);
|
||||
*
|
||||
* The UdpSubReceivers should be derived classes, with corresponding types:
|
||||
* UdpPeerReceiver TOU_RECEIVER_TYPE_UDPPEER
|
||||
* UdpRelayReceiver TOU_RECEIVER_TYPE_UDPRELAY
|
||||
*
|
||||
*/
|
||||
|
||||
#define MAX_TOU_RECEIVERS 16
|
||||
|
||||
#define TOU_RECEIVER_TYPE_NONE 0x0000
|
||||
#define TOU_RECEIVER_TYPE_UDPPEER 0x0001
|
||||
#define TOU_RECEIVER_TYPE_UDPRELAY 0x0002
|
||||
|
||||
// hack to avoid classes in C code. (MacOSX complaining)
|
||||
// will pass as UdpStack * as void *
|
||||
int tou_init(void *udpStack);
|
||||
int tou_init(void **udpSubRecvs, int *udpTypes, int nUdps);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* Connections are as similar to UNIX as possible
|
||||
* (1) create a socket: tou_socket() this reserves a socket id.
|
||||
* (2) connect: active: tou_connect() or passive: tou_listenfor().
|
||||
@ -77,6 +89,18 @@ extern "C" {
|
||||
* tou_bind() is not valid. tou_init performs this role.
|
||||
* tou_listen() is not valid. (must listen for a specific address) use tou_listenfor() instead.
|
||||
* tou_accept() can still be used.
|
||||
*
|
||||
****** THE ABOVE IS BECOMING LESS TRUE ********
|
||||
*
|
||||
* I have now added Multiple type of TOU Connections (Proxy, Relay),
|
||||
* and multiple UDP Receivers (meaning you can use different ports too).
|
||||
*
|
||||
* The UDP receivers must be specified at startup (new tou_init())
|
||||
* and the Receiver, and Type of connection must be specified when you
|
||||
* open the socket.
|
||||
*
|
||||
* The parameters to tou_socket, therefore mean something!
|
||||
* some extra checking has been put in to try and catch bad usage.
|
||||
*/
|
||||
|
||||
/* creation/connections */
|
||||
@ -87,6 +111,12 @@ int tou_connect(int sockfd, const struct sockaddr *serv_addr,
|
||||
socklen_t addrlen, uint32_t conn_period);
|
||||
int tou_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
|
||||
|
||||
/* for relay connections */
|
||||
int tou_connect_via_relay(int sockfd,
|
||||
const struct sockaddr_in *own_addr,
|
||||
const struct sockaddr_in *proxy_addr,
|
||||
const struct sockaddr_in *dest_addr);
|
||||
|
||||
/* non-standard bonuses */
|
||||
int tou_connected(int sockfd);
|
||||
int tou_listenfor(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
|
||||
|
@ -70,4 +70,5 @@ int status(std::ostream &out);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
868
libretroshare/src/tcponudp/udprelay.cc
Normal file
868
libretroshare/src/tcponudp/udprelay.cc
Normal file
@ -0,0 +1,868 @@
|
||||
/*
|
||||
* tcponudp/udprelay.cc
|
||||
*
|
||||
* libretroshare.
|
||||
*
|
||||
* Copyright 2010 by Robert Fernie
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 3 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "udprelay.h"
|
||||
#include <iostream>
|
||||
|
||||
/*
|
||||
* #define DEBUG_UDP_RELAY 1
|
||||
*/
|
||||
|
||||
//#define DEBUG_UDP_RELAY 1
|
||||
|
||||
|
||||
#ifdef DEBUG_UDP_RELAY
|
||||
// DEBUG FUNCTION
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
int displayUdpRelayPacketHeader(const void *data, const int size);
|
||||
#endif
|
||||
|
||||
/****************** UDP RELAY STUFF **********/
|
||||
|
||||
#define MAX_RELAY_UDP_PACKET_SIZE 1024
|
||||
|
||||
UdpRelayReceiver::UdpRelayReceiver(UdpPublisher *pub)
|
||||
:UdpSubReceiver(pub)
|
||||
{
|
||||
mClassLimit.resize(UDP_RELAY_NUM_CLASS);
|
||||
mClassCount.resize(UDP_RELAY_NUM_CLASS);
|
||||
|
||||
setRelayTotal(UDP_RELAY_DEFAULT_COUNT_ALL);
|
||||
|
||||
for(int i = 0; i < UDP_RELAY_NUM_CLASS; i++)
|
||||
{
|
||||
mClassCount[i] = 0;
|
||||
}
|
||||
|
||||
/* only allocate this space once */
|
||||
mTmpSendPkt = malloc(MAX_RELAY_UDP_PACKET_SIZE);
|
||||
mTmpSendSize = MAX_RELAY_UDP_PACKET_SIZE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
UdpRelayReceiver::~UdpRelayReceiver()
|
||||
{
|
||||
free(mTmpSendPkt);
|
||||
}
|
||||
|
||||
|
||||
int UdpRelayReceiver::addUdpPeer(UdpPeer *peer, UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr)
|
||||
{
|
||||
struct sockaddr_in realPeerAddr = endPoints->mDestAddr;
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
/* check for duplicate */
|
||||
std::map<struct sockaddr_in, UdpRelayEnd>::iterator it;
|
||||
it = mStreams.find(realPeerAddr);
|
||||
bool ok = (it == mStreams.end());
|
||||
if (!ok)
|
||||
{
|
||||
#ifdef DEBUG_UDP_RELAY
|
||||
std::cerr << "UdpPeerReceiver::addUdpPeer() ERROR Peer already exists!" << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* setup a peer */
|
||||
UdpRelayEnd ure(endPoints, proxyaddr);
|
||||
|
||||
mStreams[realPeerAddr] = ure;
|
||||
}
|
||||
|
||||
{
|
||||
RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
|
||||
#ifdef DEBUG_UDP_RELAY
|
||||
std::cerr << "UdpPeerReceiver::addUdpPeer() Just installing UdpPeer!" << std::endl;
|
||||
#endif
|
||||
|
||||
/* just overwrite */
|
||||
mPeers[realPeerAddr] = peer;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int UdpRelayReceiver::removeUdpPeer(UdpPeer *peer)
|
||||
{
|
||||
bool found = false;
|
||||
struct sockaddr_in realPeerAddr;
|
||||
|
||||
/* cleanup UdpPeer, and get reference for data */
|
||||
{
|
||||
RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
std::map<struct sockaddr_in, UdpPeer *>::iterator it;
|
||||
for(it = mPeers.begin(); it != mPeers.end(); it++)
|
||||
{
|
||||
if (it->second == peer)
|
||||
{
|
||||
mPeers.erase(it);
|
||||
found = true;
|
||||
realPeerAddr = it->first;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* now we cleanup the associated data */
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
std::map<struct sockaddr_in, UdpRelayEnd>::iterator it;
|
||||
it = mStreams.find(realPeerAddr);
|
||||
if (it != mStreams.end())
|
||||
{
|
||||
mStreams.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ERROR */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int UdpRelayReceiver::getRelayEnds(std::list<UdpRelayEnd> &relayEnds)
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
std::map<struct sockaddr_in, UdpRelayEnd>::iterator rit;
|
||||
|
||||
for(rit = mStreams.begin(); rit != mStreams.end(); rit++)
|
||||
{
|
||||
relayEnds.push_back(rit->second);
|
||||
}
|
||||
return 1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
int UdpRelayReceiver::getRelayProxies(std::list<UdpRelayProxy> &relayProxies)
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
std::map<UdpRelayAddrSet, UdpRelayProxy>::iterator rit;
|
||||
|
||||
for(rit = mRelays.begin(); rit != mRelays.end(); rit++)
|
||||
{
|
||||
relayProxies.push_back(rit->second);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define RELAY_MAX_BANDWIDTH 1000
|
||||
#define RELAY_TIMEOUT 30
|
||||
|
||||
|
||||
int UdpRelayReceiver::checkRelays()
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
/* iterate through the Relays */
|
||||
|
||||
std::cerr << "UdpRelayReceiver::checkRelays()";
|
||||
std::cerr << std::endl;
|
||||
|
||||
std::list<UdpRelayAddrSet> eraseList;
|
||||
std::map<UdpRelayAddrSet, UdpRelayProxy>::iterator rit;
|
||||
time_t now = time(NULL);
|
||||
|
||||
for(rit = mRelays.begin(); rit != mRelays.end(); rit++)
|
||||
{
|
||||
/* calc bandwidth */
|
||||
rit->second.mBandwidth = rit->second.mDataSize / (float) (now - rit->second.mLastBandwidthTS);
|
||||
rit->second.mDataSize = 0;
|
||||
rit->second.mLastBandwidthTS = now;
|
||||
|
||||
std::cerr << "UdpRelayReceiver::checkRelays()";
|
||||
std::cerr << "Relay: " << rit->first;
|
||||
std::cerr << " using bandwidth: " << rit->second.mBandwidth;
|
||||
std::cerr << std::endl;
|
||||
|
||||
if (rit->second.mBandwidth > RELAY_MAX_BANDWIDTH)
|
||||
{
|
||||
std::cerr << "UdpRelayReceiver::checkRelays()";
|
||||
std::cerr << "Dropping Relay due to excessive Bandwidth: " << rit->first;
|
||||
std::cerr << std::endl;
|
||||
|
||||
/* if exceeding bandwidth -> drop */
|
||||
eraseList.push_back(rit->first);
|
||||
}
|
||||
else if (now - rit->second.mLastTS > RELAY_TIMEOUT)
|
||||
{
|
||||
/* if haven't transmitted for ages -> drop */
|
||||
std::cerr << "UdpRelayReceiver::checkRelays()";
|
||||
std::cerr << "Dropping Relay due to Timeout: " << rit->first;
|
||||
std::cerr << std::endl;
|
||||
eraseList.push_back(rit->first);
|
||||
}
|
||||
}
|
||||
|
||||
std::list<UdpRelayAddrSet>::iterator it;
|
||||
for(it = eraseList.begin(); it != eraseList.end(); it++)
|
||||
{
|
||||
removeUdpRelay_relayLocked(&(*it));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int UdpRelayReceiver::removeUdpRelay(UdpRelayAddrSet *addrSet)
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
return removeUdpRelay_relayLocked(addrSet);
|
||||
}
|
||||
|
||||
|
||||
int UdpRelayReceiver::addUdpRelay(UdpRelayAddrSet *addrSet, int relayClass)
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
/* check for duplicate */
|
||||
std::map<UdpRelayAddrSet, UdpRelayProxy>::iterator rit = mRelays.find(*addrSet);
|
||||
int ok = (rit == mRelays.end());
|
||||
if (!ok)
|
||||
{
|
||||
//#ifdef DEBUG_UDP_RELAY
|
||||
std::cerr << "UdpRelayReceiver::addUdpRelay() ERROR Peer already exists!" << std::endl;
|
||||
//#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* will install if there is space! */
|
||||
if (installRelayClass_relayLocked(relayClass))
|
||||
{
|
||||
//#ifdef DEBUG_UDP_RELAY
|
||||
std::cerr << "UdpRelayReceiver::addUdpRelay() adding Relay" << std::endl;
|
||||
//#endif
|
||||
/* create UdpRelay */
|
||||
UdpRelayProxy udpRelay(addrSet, relayClass);
|
||||
UdpRelayAddrSet alt = addrSet->flippedSet();
|
||||
UdpRelayProxy altUdpRelay(&alt, relayClass);
|
||||
|
||||
/* must install two (A, B) & (B, A) */
|
||||
mRelays[*addrSet] = udpRelay;
|
||||
mRelays[alt] = altUdpRelay;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//#ifdef DEBUG_UDP_RELAY
|
||||
std::cerr << "UdpRelayReceiver::addUdpRelay() WARNING Too many Relays!" << std::endl;
|
||||
//#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int UdpRelayReceiver::removeUdpRelay_relayLocked(UdpRelayAddrSet *addrSet)
|
||||
{
|
||||
/* find in Relay list */
|
||||
std::map<UdpRelayAddrSet, UdpRelayProxy>::iterator rit = mRelays.find(*addrSet);
|
||||
if (rit == mRelays.end())
|
||||
{
|
||||
/* ERROR */
|
||||
std::cerr << "UdpRelayReceiver::removeUdpRelay()";
|
||||
std::cerr << "ERROR Finding Relay: " << *addrSet;
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* lets drop the count here too */
|
||||
removeRelayClass_relayLocked(rit->second.mRelayClass);
|
||||
mRelays.erase(rit);
|
||||
}
|
||||
|
||||
/* rotate around and delete matching set */
|
||||
UdpRelayAddrSet alt = addrSet->flippedSet();
|
||||
|
||||
rit = mRelays.find(alt);
|
||||
if (rit == mRelays.end())
|
||||
{
|
||||
std::cerr << "UdpRelayReceiver::removeUdpRelay()";
|
||||
std::cerr << "ERROR Finding Alt Relay: " << alt;
|
||||
std::cerr << std::endl;
|
||||
/* ERROR */
|
||||
}
|
||||
else
|
||||
{
|
||||
mRelays.erase(rit);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Need some stats, to work out how many relays we are supporting */
|
||||
int UdpRelayReceiver::installRelayClass_relayLocked(int classIdx)
|
||||
{
|
||||
/* check for total number of Relays */
|
||||
if (mClassCount[UDP_RELAY_CLASS_ALL] >= mClassLimit[UDP_RELAY_CLASS_ALL])
|
||||
{
|
||||
std::cerr << "UdpRelayReceiver::installRelayClass() WARNING Too many Relays already";
|
||||
std::cerr << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check the idx too */
|
||||
if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS))
|
||||
{
|
||||
std::cerr << "UdpRelayReceiver::installRelayClass() ERROR class Idx invalid";
|
||||
std::cerr << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* now check the specifics of the class */
|
||||
if (mClassCount[classIdx] >= mClassLimit[classIdx])
|
||||
{
|
||||
std::cerr << "UdpRelayReceiver::installRelayClass() WARNING Relay Class Limit Exceeded";
|
||||
std::cerr << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::cerr << "UdpRelayReceiver::installRelayClass() Relay Class Ok, Count incremented";
|
||||
std::cerr << std::endl;
|
||||
|
||||
/* if we get here we can add one */
|
||||
mClassCount[UDP_RELAY_CLASS_ALL]++;
|
||||
mClassCount[classIdx]++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int UdpRelayReceiver::removeRelayClass_relayLocked(int classIdx)
|
||||
{
|
||||
/* check for total number of Relays */
|
||||
if (mClassCount[UDP_RELAY_CLASS_ALL] < 1)
|
||||
{
|
||||
std::cerr << "UdpRelayReceiver::removeRelayClass() ERROR no relays installed";
|
||||
std::cerr << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check the idx too */
|
||||
if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS))
|
||||
{
|
||||
std::cerr << "UdpRelayReceiver::removeRelayClass() ERROR class Idx invalid";
|
||||
std::cerr << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* now check the specifics of the class */
|
||||
if (mClassCount[classIdx] < 1)
|
||||
{
|
||||
std::cerr << "UdpRelayReceiver::removeRelayClass() ERROR no relay of class installed";
|
||||
std::cerr << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::cerr << "UdpRelayReceiver::removeRelayClass() Ok, Count decremented";
|
||||
std::cerr << std::endl;
|
||||
|
||||
/* if we get here we can add one */
|
||||
mClassCount[UDP_RELAY_CLASS_ALL]--;
|
||||
mClassCount[classIdx]--;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int UdpRelayReceiver::setRelayTotal(int count)
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
mClassLimit[UDP_RELAY_CLASS_ALL] = count;
|
||||
mClassLimit[UDP_RELAY_CLASS_GENERAL] = (int) (UDP_RELAY_FRAC_GENERAL * count);
|
||||
mClassLimit[UDP_RELAY_CLASS_FOF] = (int) (UDP_RELAY_FRAC_FOF * count);
|
||||
mClassLimit[UDP_RELAY_CLASS_FRIENDS] = (int) (UDP_RELAY_FRAC_FRIENDS * count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
int UdpRelayReceiver::setRelayClassMax(int classIdx, int count)
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
/* check the idx */
|
||||
if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS))
|
||||
{
|
||||
std::cerr << "UdpRelayReceiver::setRelayMaximum() ERROR class Idx invalid";
|
||||
std::cerr << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mClassLimit[classIdx] = count;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int UdpRelayReceiver::getRelayClassMax(int classIdx)
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
/* check the idx */
|
||||
if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS))
|
||||
{
|
||||
std::cerr << "UdpRelayReceiver::getRelayMaximum() ERROR class Idx invalid";
|
||||
std::cerr << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mClassLimit[classIdx];
|
||||
}
|
||||
|
||||
int UdpRelayReceiver::getRelayCount(int classIdx)
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
/* check the idx */
|
||||
if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS))
|
||||
{
|
||||
std::cerr << "UdpRelayReceiver::getRelayCount() ERROR class Idx invalid";
|
||||
std::cerr << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mClassCount[classIdx];
|
||||
}
|
||||
|
||||
|
||||
int UdpRelayReceiver::RelayStatus(std::ostream &out)
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
/* iterate through the Relays */
|
||||
out << "UdpRelayReceiver::RelayStatus()";
|
||||
out << std::endl;
|
||||
|
||||
std::map<UdpRelayAddrSet, UdpRelayProxy>::iterator rit;
|
||||
for(rit = mRelays.begin(); rit != mRelays.end(); rit++)
|
||||
{
|
||||
out << "Relay for: " << rit->first;
|
||||
out << std::endl;
|
||||
|
||||
out << "\tClass: " << rit->second.mRelayClass;
|
||||
out << "\tBandwidth: " << rit->second.mBandwidth;
|
||||
out << "\tDataSize: " << rit->second.mDataSize;
|
||||
out << "\tLastBandwidthTS: " << rit->second.mLastBandwidthTS;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int UdpRelayReceiver::status(std::ostream &out)
|
||||
{
|
||||
|
||||
out << "UdpRelayReceiver::status()" << std::endl;
|
||||
out << "UdpRelayReceiver::Relayed Connections:" << std::endl;
|
||||
|
||||
RelayStatus(out);
|
||||
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
out << "UdpRelayReceiver::Connections:" << std::endl;
|
||||
|
||||
std::map<struct sockaddr_in, UdpRelayEnd>::iterator pit;
|
||||
for(pit = mStreams.begin(); pit != mStreams.end(); pit++)
|
||||
{
|
||||
out << "\t" << pit->first << " : " << pit->second;
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define UDP_RELAY_HEADER_SIZE 16
|
||||
|
||||
/* higher level interface */
|
||||
int UdpRelayReceiver::recvPkt(void *data, int size, struct sockaddr_in &from)
|
||||
{
|
||||
/* print packet information */
|
||||
#ifdef DEBUG_UDP_RELAY
|
||||
std::cerr << "UdpRelayReceiver::recvPkt(" << size << ") from: " << from;
|
||||
std::cerr << std::endl;
|
||||
displayUdpRelayPacketHeader(data, size);
|
||||
|
||||
#endif
|
||||
|
||||
if (!isUdpRelayPacket(data, size))
|
||||
{
|
||||
#ifdef DEBUG_UDP_RELAY
|
||||
std::cerr << "UdpRelayReceiver::recvPkt() is Not RELAY Pkt";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* decide if we are the relay, or the endpoint */
|
||||
UdpRelayAddrSet addrSet;
|
||||
if (!extractUdpRelayAddrSet(data, size, addrSet))
|
||||
{
|
||||
/* fails most basic test, drop */
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
/* lookup relay first (double entries) */
|
||||
std::map<UdpRelayAddrSet, UdpRelayProxy>::iterator rit = mRelays.find(addrSet);
|
||||
if (rit != mRelays.end())
|
||||
{
|
||||
/* we are the relay */
|
||||
#ifdef DEBUG_UDP_RELAY
|
||||
std::cerr << "UdpRelayReceiver::recvPkt() We are the Relay. Passing onto: ";
|
||||
std::cerr << rit->first.mDestAddr;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
/* do accounting */
|
||||
rit->second.mLastTS = time(NULL);
|
||||
rit->second.mDataSize += size;
|
||||
|
||||
mPublisher->sendPkt(data, size, rit->first.mDestAddr, STD_RELAY_TTL);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* otherwise we are likely to be the endpoint,
|
||||
* use the peers Address from the header
|
||||
*/
|
||||
|
||||
{
|
||||
RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
std::map<struct sockaddr_in, UdpPeer *>::iterator pit = mPeers.find(addrSet.mSrcAddr);
|
||||
if (pit != mPeers.end())
|
||||
{
|
||||
/* we are the end-point */
|
||||
#ifdef DEBUG_UDP_RELAY
|
||||
std::cerr << "UdpRelayReceiver::recvPkt() Sending to UdpPeer: ";
|
||||
std::cerr << pit->first;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
/* remove the header */
|
||||
void *pktdata = (void *) (((uint8_t *) data) + UDP_RELAY_HEADER_SIZE);
|
||||
int pktsize = size - UDP_RELAY_HEADER_SIZE;
|
||||
if (pktsize > 0)
|
||||
{
|
||||
(pit->second)->recvPkt(pktdata, pktsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* packet undersized */
|
||||
#ifdef DEBUG_UDP_RELAY
|
||||
std::cerr << "UdpRelayReceiver::recvPkt() ERROR Packet Undersized";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* done */
|
||||
}
|
||||
|
||||
/* unknown */
|
||||
#ifdef DEBUG_UDP_RELAY
|
||||
std::cerr << "UdpRelayReceiver::recvPkt() Peer Unknown!";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* the address here must be the end point!,
|
||||
* it cannot be proxy, as we could be using the same proxy for multiple connections.
|
||||
*/
|
||||
int UdpRelayReceiver::sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl)
|
||||
{
|
||||
RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
/* work out who the proxy is */
|
||||
std::map<struct sockaddr_in, UdpRelayEnd>::iterator it;
|
||||
it = mStreams.find(to);
|
||||
if (it == mStreams.end())
|
||||
{
|
||||
//#ifdef DEBUG_UDP_RELAY
|
||||
std::cerr << "UdpRelayReceiver::sendPkt() Peer Unknown!";
|
||||
std::cerr << std::endl;
|
||||
//#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* add a header to packet */
|
||||
int finalPktSize = createRelayUdpPacket(data, size, mTmpSendPkt, MAX_RELAY_UDP_PACKET_SIZE, &(it->second));
|
||||
|
||||
/* send the packet on */
|
||||
return mPublisher->sendPkt(mTmpSendPkt, finalPktSize, it->second.mProxyAddr, STD_RELAY_TTL);
|
||||
}
|
||||
|
||||
/***** RELAY PACKET FORMAT ****************************
|
||||
*
|
||||
*
|
||||
* [ 0 | 1 | 2 | 3 ]
|
||||
*
|
||||
* [ 'R' 'L' 'Y' Version ]
|
||||
* [ IP Address 1 ]
|
||||
* [ Port 1 ][ IP Address 2 ....
|
||||
* ... IP Address 2][ Port 2 ]
|
||||
* [.... TUNNELLED DATA ....
|
||||
*
|
||||
*
|
||||
* ... ]
|
||||
*
|
||||
* 16 Bytes: 4 ID, 6 IP:Port 1, 6 IP:Port 2
|
||||
*/
|
||||
|
||||
#define UDP_IDENTITY_STRING_V1 "RLY1"
|
||||
#define UDP_IDENTITY_SIZE_V1 4
|
||||
|
||||
int isUdpRelayPacket(const void *data, const int size)
|
||||
{
|
||||
if (size < UDP_RELAY_HEADER_SIZE)
|
||||
return 0;
|
||||
|
||||
return (0 == strncmp((char *) data, UDP_IDENTITY_STRING_V1, UDP_IDENTITY_SIZE_V1));
|
||||
}
|
||||
|
||||
#ifdef DEBUG_UDP_RELAY
|
||||
|
||||
int displayUdpRelayPacketHeader(const void *data, const int size)
|
||||
{
|
||||
int dsize = UDP_RELAY_HEADER_SIZE + 16;
|
||||
if (size < dsize)
|
||||
{
|
||||
dsize = size;
|
||||
}
|
||||
|
||||
std::ostringstream out;
|
||||
for(int i = 0; i < dsize; i++)
|
||||
{
|
||||
if ((i > 0) && (i % 16 == 0))
|
||||
{
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
out << std::setw(2) << std::setfill('0') << std::hex << (uint32_t) ((uint8_t*) data)[i];
|
||||
}
|
||||
|
||||
std::cerr << "displayUdpRelayPacketHeader()" << std::endl;
|
||||
std::cerr << out.str();
|
||||
std::cerr << std::endl;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int extractUdpRelayAddrSet(const void *data, const int size, UdpRelayAddrSet &addrSet)
|
||||
{
|
||||
if (size < UDP_RELAY_HEADER_SIZE)
|
||||
{
|
||||
std::cerr << "createRelayUdpPacket() ERROR invalid size";
|
||||
std::cerr << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *header = (uint8_t *) data;
|
||||
|
||||
sockaddr_clear(&(addrSet.mSrcAddr));
|
||||
sockaddr_clear(&(addrSet.mDestAddr));
|
||||
|
||||
/* as IP:Port are already in network byte order, we can just write them to the dataspace */
|
||||
uint32_t ipaddr;
|
||||
uint16_t port;
|
||||
|
||||
memcpy(&ipaddr, &(header[4]), 4);
|
||||
memcpy(&port, &(header[8]), 2);
|
||||
|
||||
addrSet.mSrcAddr.sin_addr.s_addr = ipaddr;
|
||||
addrSet.mSrcAddr.sin_port = port;
|
||||
|
||||
memcpy(&ipaddr, &(header[10]), 4);
|
||||
memcpy(&port, &(header[14]), 2);
|
||||
|
||||
addrSet.mDestAddr.sin_addr.s_addr = ipaddr;
|
||||
addrSet.mDestAddr.sin_port = port;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int createRelayUdpPacket(const void *data, const int size, void *newpkt, int newsize, UdpRelayEnd *ure)
|
||||
{
|
||||
int pktsize = size + UDP_RELAY_HEADER_SIZE;
|
||||
if (newsize < pktsize)
|
||||
{
|
||||
std::cerr << "createRelayUdpPacket() ERROR invalid size";
|
||||
std::cerr << std::endl;
|
||||
return 0;
|
||||
}
|
||||
uint8_t *header = (uint8_t *) newpkt;
|
||||
memcpy(header, UDP_IDENTITY_STRING_V1, UDP_IDENTITY_SIZE_V1);
|
||||
|
||||
/* as IP:Port are already in network byte order, we can just write them to the dataspace */
|
||||
uint32_t ipaddr = ure->mLocalAddr.sin_addr.s_addr;
|
||||
uint16_t port = ure->mLocalAddr.sin_port;
|
||||
|
||||
memcpy(&(header[4]), &ipaddr, 4);
|
||||
memcpy(&(header[8]), &port, 2);
|
||||
|
||||
ipaddr = ure->mRemoteAddr.sin_addr.s_addr;
|
||||
port = ure->mRemoteAddr.sin_port;
|
||||
|
||||
memcpy(&(header[10]), &ipaddr, 4);
|
||||
memcpy(&(header[14]), &port, 2);
|
||||
|
||||
memcpy(&(header[16]), data, size);
|
||||
|
||||
return pktsize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******* Small Container Class Helper Functions ****/
|
||||
|
||||
UdpRelayAddrSet::UdpRelayAddrSet()
|
||||
{
|
||||
sockaddr_clear(&mSrcAddr);
|
||||
sockaddr_clear(&mDestAddr);
|
||||
}
|
||||
|
||||
UdpRelayAddrSet::UdpRelayAddrSet(const sockaddr_in *ownAddr, const sockaddr_in *destAddr)
|
||||
{
|
||||
mSrcAddr = *ownAddr;
|
||||
mDestAddr = *destAddr;
|
||||
}
|
||||
|
||||
UdpRelayAddrSet UdpRelayAddrSet::flippedSet()
|
||||
{
|
||||
UdpRelayAddrSet flipped(&mDestAddr, &mSrcAddr);
|
||||
return flipped;
|
||||
}
|
||||
|
||||
|
||||
int operator<(const UdpRelayAddrSet &a, const UdpRelayAddrSet &b)
|
||||
{
|
||||
if (a.mSrcAddr < b.mSrcAddr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (a.mSrcAddr == b.mSrcAddr)
|
||||
{
|
||||
if (a.mDestAddr < b.mDestAddr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
UdpRelayProxy::UdpRelayProxy()
|
||||
{
|
||||
mBandwidth = 0;
|
||||
mDataSize = 0;
|
||||
mLastBandwidthTS = 0;
|
||||
mLastTS = time(NULL); // Must be set here, otherwise Proxy Timesout before anything can happen!
|
||||
mRelayClass = 0;
|
||||
}
|
||||
|
||||
UdpRelayProxy::UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass)
|
||||
{
|
||||
mAddrs = *addrSet;
|
||||
mRelayClass = relayClass;
|
||||
|
||||
mBandwidth = 0;
|
||||
mDataSize = 0;
|
||||
mLastBandwidthTS = 0;
|
||||
mLastTS = time(NULL);
|
||||
}
|
||||
|
||||
UdpRelayEnd::UdpRelayEnd()
|
||||
{
|
||||
sockaddr_clear(&mLocalAddr);
|
||||
sockaddr_clear(&mProxyAddr);
|
||||
sockaddr_clear(&mRemoteAddr);
|
||||
|
||||
}
|
||||
|
||||
UdpRelayEnd::UdpRelayEnd(UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr)
|
||||
{
|
||||
mLocalAddr = endPoints->mSrcAddr;
|
||||
mRemoteAddr = endPoints->mDestAddr;
|
||||
mProxyAddr = *proxyaddr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const UdpRelayAddrSet &uras)
|
||||
{
|
||||
out << "<" << uras.mSrcAddr << "," << uras.mDestAddr << ">";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const UdpRelayProxy &urp)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
out << "UdpRelayProxy for " << urp.mAddrs;
|
||||
out << std::endl;
|
||||
out << "\tRelayClass: " << urp.mRelayClass;
|
||||
out << std::endl;
|
||||
out << "\tBandwidth: " << urp.mBandwidth;
|
||||
out << std::endl;
|
||||
out << "\tDataSize: " << urp.mDataSize;
|
||||
out << std::endl;
|
||||
out << "\tLastBandwidthTS: " << now - urp.mLastBandwidthTS << " secs ago";
|
||||
out << std::endl;
|
||||
out << "\tLastTS: " << now - urp.mLastTS << " secs ago";
|
||||
out << std::endl;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const UdpRelayEnd &ure)
|
||||
{
|
||||
out << "UdpRelayEnd: <" << ure.mLocalAddr << " => " << ure.mProxyAddr << " <= ";
|
||||
out << ure.mRemoteAddr << ">";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
186
libretroshare/src/tcponudp/udprelay.h
Normal file
186
libretroshare/src/tcponudp/udprelay.h
Normal file
@ -0,0 +1,186 @@
|
||||
#ifndef RS_UDP_RELAY_H
|
||||
#define RS_UDP_RELAY_H
|
||||
|
||||
/*
|
||||
* tcponudp/udprelay.h
|
||||
*
|
||||
* libretroshare.
|
||||
*
|
||||
* Copyright 2010 by Robert Fernie
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 3 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tcponudp/udppeer.h"
|
||||
#include <vector>
|
||||
|
||||
class UdpRelayAddrSet;
|
||||
|
||||
class UdpRelayAddrSet
|
||||
{
|
||||
public:
|
||||
UdpRelayAddrSet();
|
||||
UdpRelayAddrSet(const sockaddr_in *ownAddr, const sockaddr_in *destAddr);
|
||||
|
||||
UdpRelayAddrSet flippedSet();
|
||||
|
||||
struct sockaddr_in mSrcAddr; /* msg source */
|
||||
struct sockaddr_in mDestAddr; /* final destination */
|
||||
};
|
||||
|
||||
int operator<(const UdpRelayAddrSet &a, const UdpRelayAddrSet &b);
|
||||
|
||||
class UdpRelayProxy
|
||||
{
|
||||
public:
|
||||
UdpRelayProxy();
|
||||
UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass);
|
||||
|
||||
UdpRelayAddrSet mAddrs;
|
||||
double mBandwidth;
|
||||
uint32_t mDataSize;
|
||||
time_t mLastBandwidthTS;
|
||||
time_t mLastTS;
|
||||
|
||||
int mRelayClass;
|
||||
};
|
||||
|
||||
|
||||
class UdpRelayEnd
|
||||
{
|
||||
public:
|
||||
|
||||
UdpRelayEnd();
|
||||
UdpRelayEnd(UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr);
|
||||
|
||||
struct sockaddr_in mLocalAddr;
|
||||
struct sockaddr_in mProxyAddr;
|
||||
struct sockaddr_in mRemoteAddr;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const UdpRelayAddrSet &uras);
|
||||
std::ostream &operator<<(std::ostream &out, const UdpRelayProxy &urp);
|
||||
std::ostream &operator<<(std::ostream &out, const UdpRelayEnd &ure);
|
||||
|
||||
/* we define a couple of classes (determining which class is done elsewhere)
|
||||
* There will be various maximums for each type.
|
||||
* Ideally you want to allow your friends to use your proxy in preference
|
||||
* to randoms.
|
||||
*
|
||||
* At N x 2 x maxBandwidth.
|
||||
*
|
||||
* 10 x 2 x 1Kb/s => 20Kb/s In and Out. (quite a bit!)
|
||||
* 20 x 2 x 1Kb/s => 40Kb/s Huge.
|
||||
*/
|
||||
|
||||
#define UDP_RELAY_DEFAULT_COUNT_ALL 10
|
||||
#define UDP_RELAY_FRAC_GENERAL (0.2)
|
||||
#define UDP_RELAY_FRAC_FOF (0.5)
|
||||
#define UDP_RELAY_FRAC_FRIENDS (0.8)
|
||||
|
||||
#define UDP_RELAY_NUM_CLASS 4
|
||||
|
||||
#define UDP_RELAY_CLASS_ALL 0
|
||||
#define UDP_RELAY_CLASS_GENERAL 1
|
||||
#define UDP_RELAY_CLASS_FOF 2
|
||||
#define UDP_RELAY_CLASS_FRIENDS 3
|
||||
|
||||
#define STD_RELAY_TTL 64
|
||||
|
||||
class UdpRelayReceiver: public UdpSubReceiver
|
||||
{
|
||||
public:
|
||||
|
||||
UdpRelayReceiver(UdpPublisher *pub);
|
||||
virtual ~UdpRelayReceiver();
|
||||
|
||||
/* add a TCPonUDP stream (ENDs) */
|
||||
int addUdpPeer(UdpPeer *peer, UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr);
|
||||
int removeUdpPeer(UdpPeer *peer);
|
||||
|
||||
/* add a Relay Point (for the Relay).
|
||||
* These don't have to be explicitly removed.
|
||||
* They will be timed out when
|
||||
* the end-points drop the connections
|
||||
*/
|
||||
|
||||
int addUdpRelay(UdpRelayAddrSet *addrs, int classIdx);
|
||||
int removeUdpRelay(UdpRelayAddrSet *addrs);
|
||||
|
||||
/* Need some stats, to work out how many relays we are supporting */
|
||||
int checkRelays();
|
||||
|
||||
int setRelayTotal(int count); /* sets all the Relay Counts (frac based on total) */
|
||||
int setRelayClassMax(int classIdx, int count); /* set a specific class maximum */
|
||||
int getRelayClassMax(int classIdx);
|
||||
int getRelayCount(int classIdx); /* how many relays (of this type) do we have */
|
||||
int RelayStatus(std::ostream &out);
|
||||
|
||||
/* Extract Relay Data */
|
||||
int getRelayEnds(std::list<UdpRelayEnd> &relayEnds);
|
||||
int getRelayProxies(std::list<UdpRelayProxy> &relayProxies);
|
||||
|
||||
/* callback for recved data (overloaded from UdpReceiver) */
|
||||
virtual int recvPkt(void *data, int size, struct sockaddr_in &from);
|
||||
|
||||
/* wrapper function for relay (overloaded from UdpSubReceiver) */
|
||||
virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl);
|
||||
|
||||
int status(std::ostream &out);
|
||||
|
||||
private:
|
||||
|
||||
int removeUdpRelay_relayLocked(UdpRelayAddrSet *addrs);
|
||||
int installRelayClass_relayLocked(int classIdx);
|
||||
int removeRelayClass_relayLocked(int classIdx);
|
||||
|
||||
/* Unfortunately, Due the reentrant nature of this classes activities...
|
||||
* the SendPkt() must be callable from inside RecvPkt().
|
||||
* This means we need two seperate mutexes.
|
||||
* - one for UdpPeer's, and one for Relay Data.
|
||||
*
|
||||
* care must be taken to lock these mutex's in a consistent manner to avoid deadlock.
|
||||
* - You are not allowed to hold both at the same time!
|
||||
*/
|
||||
|
||||
RsMutex udppeerMtx; /* for all class data (below) */
|
||||
|
||||
std::map<struct sockaddr_in, UdpPeer *> mPeers; /* indexed by <dest> */
|
||||
|
||||
RsMutex relayMtx; /* for all class data (below) */
|
||||
|
||||
std::vector<int> mClassLimit, mClassCount;
|
||||
std::map<struct sockaddr_in, UdpRelayEnd> mStreams; /* indexed by <dest> */
|
||||
std::map<UdpRelayAddrSet, UdpRelayProxy> mRelays; /* indexed by <src,dest> */
|
||||
|
||||
void *mTmpSendPkt;
|
||||
uint32_t mTmpSendSize;
|
||||
|
||||
};
|
||||
|
||||
/* utility functions for creating / extracting UdpRelayPackets */
|
||||
int isUdpRelayPacket(const void *data, const int size);
|
||||
int getPacketFromUdpRelayPacket(const void *data, const int size, void **realdata, int *realsize);
|
||||
|
||||
int createRelayUdpPacket(const void *data, const int size, void *newpkt, int newsize, UdpRelayEnd *ure);
|
||||
int extractUdpRelayAddrSet(const void *data, const int size, UdpRelayAddrSet &addrSet);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -27,27 +27,73 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "util/rsprint.h"
|
||||
|
||||
static const int STUN_TTL = 64;
|
||||
|
||||
#define TOU_STUN_MIN_PEERS 5
|
||||
|
||||
/*
|
||||
* #define DEBUG_UDP_STUN 1
|
||||
* #define DEBUG_UDP_STUNNER 1
|
||||
*/
|
||||
//#define DEBUG_UDP_STUNNER 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 */
|
||||
// TIMEOUT is now tied to STUN RATE ... const int32_t TOU_STUN_ADDR_MAX_AGE = 120; /* 2 minutes */
|
||||
|
||||
const int32_t TOU_STUN_DEFAULT_TARGET_RATE = 15; /* 20 secs is minimum to keep a NAT UDP port open */
|
||||
const double TOU_SUCCESS_LPF_FACTOR = 0.90;
|
||||
|
||||
|
||||
UdpStunner::UdpStunner(UdpPublisher *pub)
|
||||
:UdpSubReceiver(pub), eaddrKnown(false), eaddrStable(false),
|
||||
mStunKeepAlive(false), mStunLastRecv(0), mStunLastSend(0)
|
||||
mStunLastRecvResp(0), mStunLastRecvAny(0),
|
||||
mStunLastSendStun(0), mStunLastSendAny(0)
|
||||
{
|
||||
#ifdef UDPSTUN_ALLOW_LOCALNET
|
||||
mAcceptLocalNet = false;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* these parameters determine the rate we attempt stuns */
|
||||
mPassiveStunMode = false;
|
||||
mSuccessRate = 0.0;
|
||||
mTargetStunPeriod = TOU_STUN_DEFAULT_TARGET_RATE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef UDPSTUN_ALLOW_LOCALNET
|
||||
|
||||
// For Local Testing Only (Releases should have the #define disabled)
|
||||
void UdpStunner::SetAcceptLocalNet()
|
||||
{
|
||||
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
mAcceptLocalNet = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void UdpStunner::setTargetStunPeriod(uint32_t sec_per_stun)
|
||||
{
|
||||
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
if (sec_per_stun == 0)
|
||||
{
|
||||
mPassiveStunMode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mPassiveStunMode = false;
|
||||
}
|
||||
mTargetStunPeriod = sec_per_stun;
|
||||
|
||||
}
|
||||
|
||||
/* higher level interface */
|
||||
int UdpStunner::recvPkt(void *data, int size, struct sockaddr_in &from)
|
||||
{
|
||||
@ -62,7 +108,7 @@ int UdpStunner::recvPkt(void *data, int size, struct sockaddr_in &from)
|
||||
/* check for STUN packet */
|
||||
if (UdpStun_isStunPacket(data, size))
|
||||
{
|
||||
mStunLastRecv = time(NULL);
|
||||
mStunLastRecvAny = time(NULL);
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::recvPkt() is Stun Packet";
|
||||
std::cerr << std::endl;
|
||||
@ -76,10 +122,15 @@ int UdpStunner::recvPkt(void *data, int size, struct sockaddr_in &from)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int UdpStunner::status(std::ostream &out)
|
||||
{
|
||||
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
out << "UdpStunner::status() TargetStunPeriod: " << mTargetStunPeriod;
|
||||
out << " SuccessRate: " << mSuccessRate;
|
||||
out << std::endl;
|
||||
|
||||
out << "UdpStunner::status()" << std::endl;
|
||||
out << "UdpStunner::potentialpeers:" << std::endl;
|
||||
std::list<TouStunPeer>::iterator it;
|
||||
@ -94,10 +145,15 @@ int UdpStunner::status(std::ostream &out)
|
||||
|
||||
int UdpStunner::tick()
|
||||
{
|
||||
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::tick()" << std::endl;
|
||||
#endif
|
||||
checkStunKeepAlive();
|
||||
|
||||
if (checkStunDesired())
|
||||
{
|
||||
attemptStun();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -120,6 +176,8 @@ bool UdpStunner::locked_handleStunPkt(void *data, int size, struct sockaddr_in &
|
||||
if (!pkt)
|
||||
return false;
|
||||
|
||||
time_t now = time(NULL);
|
||||
mStunLastSendAny = now;
|
||||
int sentlen = sendPkt(pkt, len, from, STUN_TTL);
|
||||
free(pkt);
|
||||
|
||||
@ -144,7 +202,7 @@ bool UdpStunner::locked_handleStunPkt(void *data, int size, struct sockaddr_in &
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::handleStunPkt() got Ext Addr: ";
|
||||
std::cerr << inet_ntoa(eAddr.sin_addr) << ":" << ntohs(eAddr.sin_port);
|
||||
out << " from: " << from;
|
||||
std::cerr << " from: " << from;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
locked_recvdStun(from, eAddr);
|
||||
@ -168,7 +226,7 @@ bool UdpStunner::externalAddr(struct sockaddr_in &external, uint8_t &stable)
|
||||
if (eaddrKnown)
|
||||
{
|
||||
/* address timeout */
|
||||
if (time(NULL) - eaddrTime > TOU_STUN_ADDR_MAX_AGE)
|
||||
if (time(NULL) - eaddrTime > (mTargetStunPeriod * 2))
|
||||
{
|
||||
std::cerr << "UdpStunner::externalAddr() eaddr expired";
|
||||
std::cerr << std::endl;
|
||||
@ -228,13 +286,14 @@ int UdpStunner::doStun(struct sockaddr_in stun_addr)
|
||||
|
||||
{
|
||||
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
|
||||
mStunLastSend = time(NULL);
|
||||
time_t now = time(NULL);
|
||||
mStunLastSendStun = now;
|
||||
mStunLastSendAny = now;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::ostringstream out;
|
||||
out << "UdpStunner::doStun() Sent Stun Packet(" << sentlen << ") from:";
|
||||
out << inet_ntoa(laddr.sin_addr) << ":" << ntohs(laddr.sin_port);
|
||||
out << "UdpStunner::doStun() Sent Stun Packet(" << sentlen << ") ";
|
||||
out << " to:";
|
||||
out << inet_ntoa(stun_addr.sin_addr) << ":" << ntohs(stun_addr.sin_port);
|
||||
|
||||
@ -380,24 +439,11 @@ bool UdpStun_isStunPacket(void *data, int size)
|
||||
|
||||
|
||||
/******************************* STUN Handling ********************************
|
||||
* The KeepAlive part - slightly more complicated
|
||||
* KeepAlive has been replaced by a targetStunRate. Set this to zero to disable.
|
||||
*/
|
||||
|
||||
/******************************* STUN Handling ********************************/
|
||||
|
||||
bool UdpStunner::setStunKeepAlive(uint32_t required)
|
||||
{
|
||||
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
mStunKeepAlive = (required != 0);
|
||||
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::setStunKeepAlive() to: " << mStunKeepAlive;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool UdpStunner::addStunPeer(const struct sockaddr_in &remote, const char *peerid)
|
||||
{
|
||||
@ -407,20 +453,18 @@ bool UdpStunner::addStunPeer(const struct sockaddr_in &remote, const char *pe
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
bool needStun;
|
||||
bool toStore = true;
|
||||
{
|
||||
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
|
||||
needStun = (!eaddrKnown);
|
||||
}
|
||||
|
||||
storeStunPeer(remote, peerid, needStun);
|
||||
|
||||
|
||||
if (needStun)
|
||||
{
|
||||
doStun(remote);
|
||||
/* only store if we're active */
|
||||
toStore = !mPassiveStunMode;
|
||||
}
|
||||
|
||||
if (toStore)
|
||||
{
|
||||
storeStunPeer(remote, peerid, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -472,88 +516,154 @@ bool UdpStunner::storeStunPeer(const struct sockaddr_in &remote, const char *
|
||||
}
|
||||
|
||||
|
||||
bool UdpStunner::checkStunKeepAlive()
|
||||
bool UdpStunner::checkStunDesired()
|
||||
{
|
||||
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::checkStunKeepAlive()";
|
||||
std::cerr << "UdpStunner::checkStunDesired()";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
TouStunPeer peer;
|
||||
time_t now;
|
||||
{
|
||||
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
if (!mStunKeepAlive)
|
||||
if (mPassiveStunMode)
|
||||
{
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::checkStunKeepAlive() FALSE";
|
||||
std::cerr << "UdpStunner::checkStunDesired() In Passive Mode";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return false; /* all good */
|
||||
}
|
||||
|
||||
if (!eaddrKnown)
|
||||
{
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::checkStunDesired() YES, we don't have extAddr Yet";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return true; /* want our external address */
|
||||
}
|
||||
|
||||
/* check if we need to send one now */
|
||||
now = time(NULL);
|
||||
|
||||
if ((now - mStunLastSend < TOU_STUN_MAX_SEND_RATE) ||
|
||||
(now - mStunLastRecv < TOU_STUN_MAX_RECV_RATE))
|
||||
{
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::checkStunKeepAlive() To Fast ... delaying";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
/* too fast */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mStunList.size() < 1)
|
||||
{
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::checkStunKeepAlive() No Peers in List!";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/* extract entry */
|
||||
peer = mStunList.front();
|
||||
mStunList.pop_front();
|
||||
}
|
||||
|
||||
doStun(peer.remote);
|
||||
|
||||
{
|
||||
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
|
||||
if (peer.failCount < TOU_STUN_MAX_FAIL_COUNT)
|
||||
{
|
||||
peer.failCount++;
|
||||
peer.lastsend = now;
|
||||
mStunList.push_back(peer);
|
||||
/* based on SuccessRate & TargetStunRate, we work out if we should send one
|
||||
*
|
||||
* if we have 100% success rate, then we can delay until exactly TARGET RATE.
|
||||
* if we have 0% success rate, then try at double TARGET RATE.
|
||||
*
|
||||
*/
|
||||
double stunPeriod = (mTargetStunPeriod / 2.0) * (1.0 + mSuccessRate);
|
||||
time_t nextStun = mStunLastRecvResp + (int) stunPeriod;
|
||||
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::checkStunKeepAlive() pushing Stun peer to back of list";
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "UdpStunner::checkStunDesired() TargetStunPeriod: " << mTargetStunPeriod;
|
||||
std::cerr << " SuccessRate: " << mSuccessRate;
|
||||
std::cerr << " DesiredStunPeriod: " << stunPeriod;
|
||||
std::cerr << " NextStun: " << nextStun - now << " secs";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
if (now >= nextStun)
|
||||
{
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::checkStunDesired() Stun is Desired";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::checkStunKeepAlive() Discarding bad stun peer";
|
||||
std::cerr << "UdpStunner::checkStunDesired() Stun is Not Needed";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool UdpStunner::attemptStun()
|
||||
{
|
||||
bool found = false;
|
||||
TouStunPeer peer;
|
||||
time_t now = time(NULL);
|
||||
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::attemptStun()";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
{
|
||||
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
|
||||
|
||||
int i;
|
||||
for(i = 0; ((i < mStunList.size()) && (mStunList.size() > 0) && (!found)); i++)
|
||||
{
|
||||
/* extract entry */
|
||||
peer = mStunList.front();
|
||||
mStunList.pop_front();
|
||||
|
||||
/* check if expired */
|
||||
if (peer.failCount > TOU_STUN_MAX_FAIL_COUNT)
|
||||
{
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::attemptStun() Peer has expired, dropping";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Peer Okay, check last send time.
|
||||
if (now - peer.lastsend < TOU_STUN_MAX_SEND_RATE)
|
||||
{
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::attemptStun() Peer was sent to Too Recently, pushing back";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
mStunList.push_back(peer);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we have found a peer! */
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::attemptStun() Found Peer to Stun.";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
peer.failCount++;
|
||||
peer.lastsend = now;
|
||||
mStunList.push_back(peer);
|
||||
mSuccessRate *= TOU_SUCCESS_LPF_FACTOR;
|
||||
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
} // END OF WHILE LOOP.
|
||||
|
||||
if (mStunList.size() < 1)
|
||||
{
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
std::cerr << "UdpStunner::attemptStun() No Peers in List. FAILED";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
locked_printStunList();
|
||||
#endif
|
||||
|
||||
} // END OF MUTEX LOCKING.
|
||||
|
||||
if (found)
|
||||
{
|
||||
doStun(peer.remote);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -585,6 +695,29 @@ bool UdpStunner::locked_recvdStun(const struct sockaddr_in &remote, const str
|
||||
}
|
||||
}
|
||||
|
||||
/* if not found.. should we add it back in? */
|
||||
|
||||
/* How do we calculate the success rate?
|
||||
* Don't want to count all the stuns?
|
||||
* Low Pass filter won't work either...
|
||||
* at send...
|
||||
* mSuccessRate = 0.95 * mSuccessRate.
|
||||
* at recv...
|
||||
* mSuccessRate = 0.95 * mSuccessRate + 0.05;
|
||||
*
|
||||
* But if we split into a two stage eqn. it'll work!
|
||||
* a
|
||||
* mSuccessRate = 0.95 * mSuccessRate.
|
||||
* at recv...
|
||||
* mSuccessRate += 0.05;
|
||||
*/
|
||||
|
||||
mSuccessRate += (1.0-TOU_SUCCESS_LPF_FACTOR);
|
||||
|
||||
time_t now = time(NULL);
|
||||
mStunLastRecvResp = now;
|
||||
mStunLastRecvAny = now;
|
||||
|
||||
#ifdef DEBUG_UDP_STUNNER
|
||||
locked_printStunList();
|
||||
#endif
|
||||
@ -619,8 +752,13 @@ bool UdpStunner::locked_checkExternalAddress()
|
||||
*/
|
||||
|
||||
time_t age = (now - it->lastsend);
|
||||
if (it->response && isExternalNet(&(it->eaddr.sin_addr)) &&
|
||||
(it->failCount == 0) && (age < TOU_STUN_ADDR_MAX_AGE))
|
||||
if (it->response &&
|
||||
#ifdef UDPSTUN_ALLOW_LOCALNET
|
||||
( mAcceptLocalNet || isExternalNet(&(it->eaddr.sin_addr))) &&
|
||||
#else
|
||||
(isExternalNet(&(it->eaddr.sin_addr))) &&
|
||||
#endif
|
||||
(it->failCount == 0) && (age < (mTargetStunPeriod * 2)))
|
||||
{
|
||||
if (!found1)
|
||||
{
|
||||
@ -675,8 +813,10 @@ bool UdpStunner::locked_printStunList()
|
||||
|
||||
time_t now = time(NULL);
|
||||
out << "locked_printStunList()" << std::endl;
|
||||
out << "\tLastSend: " << now - mStunLastSend << std::endl;
|
||||
out << "\tLastRecv: " << now - mStunLastRecv << std::endl;
|
||||
out << "\tLastSendStun: " << now - mStunLastSendStun << std::endl;
|
||||
out << "\tLastSendAny: " << now - mStunLastSendAny << std::endl;
|
||||
out << "\tLastRecvResp: " << now - mStunLastRecvResp << std::endl;
|
||||
out << "\tLastRecvAny: " << now - mStunLastRecvAny << std::endl;
|
||||
|
||||
std::list<TouStunPeer>::iterator it;
|
||||
for(it = mStunList.begin(); it != mStunList.end(); it++)
|
||||
@ -705,7 +845,7 @@ bool UdpStunner::getStunPeer(int idx, std::string &id,
|
||||
|
||||
std::list<TouStunPeer>::iterator it;
|
||||
int i;
|
||||
for(i=0, it=mStunList.begin(); (i<idx) && (it!=mStunList.end()); it++, i++);
|
||||
for(i=0, it=mStunList.begin(); (i<idx) && (it!=mStunList.end()); it++, i++) ;
|
||||
|
||||
if (it != mStunList.end())
|
||||
{
|
||||
|
@ -25,7 +25,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
#include "util/rswin.h"
|
||||
#endif
|
||||
|
||||
#ifndef WINDOWS_SYS
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "tcponudp/rsudpstack.h"
|
||||
#include "util/rsthreads.h"
|
||||
@ -60,7 +66,10 @@ class TouStunPeer
|
||||
time_t lastsend;
|
||||
uint32_t failCount;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* #define UDPSTUN_ALLOW_LOCALNET 1
|
||||
*/
|
||||
|
||||
class UdpStunner: public UdpSubReceiver
|
||||
{
|
||||
@ -69,13 +78,17 @@ class UdpStunner: public UdpSubReceiver
|
||||
UdpStunner(UdpPublisher *pub);
|
||||
virtual ~UdpStunner() { return; }
|
||||
|
||||
bool setStunKeepAlive(uint32_t required);
|
||||
#ifdef UDPSTUN_ALLOW_LOCALNET
|
||||
// For Local Testing Mode.
|
||||
void SetAcceptLocalNet();
|
||||
#endif
|
||||
|
||||
void setTargetStunPeriod(uint32_t sec_per_stun);
|
||||
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);
|
||||
@ -89,17 +102,20 @@ virtual int status(std::ostream &out);
|
||||
|
||||
private:
|
||||
|
||||
bool checkStunDesired();
|
||||
bool attemptStun();
|
||||
|
||||
int doStun(struct sockaddr_in stun_addr);
|
||||
bool storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool sent);
|
||||
|
||||
|
||||
/* STUN handling */
|
||||
bool locked_handleStunPkt(void *data, int size, struct sockaddr_in &from);
|
||||
|
||||
int doStun(struct sockaddr_in stun_addr);
|
||||
|
||||
/* stun keepAlive */
|
||||
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 sent);
|
||||
|
||||
RsMutex stunMtx; /* for all class data (below) */
|
||||
|
||||
@ -109,12 +125,22 @@ bool storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool
|
||||
bool eaddrStable; /* if true then usable. if false -> Symmettric NAT */
|
||||
time_t eaddrTime;
|
||||
|
||||
bool mStunKeepAlive;
|
||||
time_t mStunLastRecv;
|
||||
time_t mStunLastSend;
|
||||
time_t mStunLastRecvResp;
|
||||
time_t mStunLastRecvAny;
|
||||
time_t mStunLastSendStun;
|
||||
time_t mStunLastSendAny;
|
||||
|
||||
std::list<TouStunPeer> mStunList; /* potentials */
|
||||
|
||||
#ifdef UDPSTUN_ALLOW_LOCALNET
|
||||
// For Local Testing Mode.
|
||||
bool mAcceptLocalNet;
|
||||
#endif
|
||||
|
||||
bool mPassiveStunMode;
|
||||
uint32_t mTargetStunPeriod;
|
||||
double mSuccessRate;
|
||||
|
||||
};
|
||||
|
||||
/* generic stun functions */
|
||||
|
@ -64,8 +64,8 @@ std::string RsDirUtil::getTopDir(const std::string& dir)
|
||||
*/
|
||||
int i,j;
|
||||
int len = dir.length();
|
||||
for(j = len - 1; (j > 0) && (dir[j] == '/'); j--);
|
||||
for(i = j; (i > 0) && (dir[i] != '/'); i--);
|
||||
for(j = len - 1; (j > 0) && (dir[j] == '/'); j--) ;
|
||||
for(i = j; (i > 0) && (dir[i] != '/'); i--) ;
|
||||
|
||||
if (dir[i] == '/')
|
||||
i++;
|
||||
@ -165,11 +165,11 @@ std::string RsDirUtil::removeTopDir(const std::string& dir)
|
||||
*/
|
||||
int i,j;
|
||||
int len = dir.length();
|
||||
for(j = len - 1; (j > 0) && (dir[j] == '/'); j--);
|
||||
for(i = j; (i >= 0) && (dir[i] != '/'); i--);
|
||||
for(j = len - 1; (j > 0) && (dir[j] == '/'); j--) ;
|
||||
for(i = j; (i >= 0) && (dir[i] != '/'); i--) ;
|
||||
|
||||
/* remove any more slashes */
|
||||
for(; (i >= 0) && (dir[i] == '/'); i--);
|
||||
for(; (i >= 0) && (dir[i] == '/'); i--) ;
|
||||
|
||||
for(j = 0; j <= i; j++)
|
||||
{
|
||||
@ -187,8 +187,8 @@ std::string RsDirUtil::getRootDir(const std::string& dir)
|
||||
*/
|
||||
int i,j;
|
||||
int len = dir.length();
|
||||
for(i = 0; (i < len) && (dir[i] == '/'); i++);
|
||||
for(j = i; (j < len) && (dir[j] != '/'); j++);
|
||||
for(i = 0; (i < len) && (dir[i] == '/'); i++) ;
|
||||
for(j = i; (j < len) && (dir[j] != '/'); j++) ;
|
||||
if (i == j)
|
||||
return root; /* empty */
|
||||
for(; i < j; i++)
|
||||
@ -205,12 +205,12 @@ std::string RsDirUtil::removeRootDir(const std::string& path)
|
||||
std::string output;
|
||||
|
||||
/* chew leading '/'s */
|
||||
for(i = 0; (i < len) && (path[i] == '/'); i++);
|
||||
for(i = 0; (i < len) && (path[i] == '/'); i++) ;
|
||||
if (i == len)
|
||||
return output; /* empty string */
|
||||
|
||||
for(j = i; (j < len) && (path[j] != '/'); j++); /* run to next '/' */
|
||||
for(; (j < len) && (path[j] == '/'); j++); /* chew leading '/'s */
|
||||
for(j = i; (j < len) && (path[j] != '/'); j++) ; /* run to next '/' */
|
||||
for(; (j < len) && (path[j] == '/'); j++) ; /* chew leading '/'s */
|
||||
|
||||
for(; j < len; j++)
|
||||
{
|
||||
@ -236,7 +236,7 @@ std::string RsDirUtil::removeRootDirs(const std::string& path, const std::string
|
||||
i++;
|
||||
}
|
||||
|
||||
for(; (i < path.length()) && (j < root.length()) && (path[i] == root[j]); i++, j++);
|
||||
for(; (i < path.length()) && (j < root.length()) && (path[i] == root[j]); i++, j++) ;
|
||||
|
||||
/* should have consumed root. */
|
||||
if (j == root.length())
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "util/rsnet.h"
|
||||
#include "util/rsthreads.h"
|
||||
#include <string.h>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
#else
|
||||
@ -137,14 +138,21 @@ std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr)
|
||||
}
|
||||
|
||||
/* thread-safe version of inet_ntoa */
|
||||
|
||||
static RsMutex inetMtx;
|
||||
/*** XXX, PROBLEM this function is not Thread-Safe.
|
||||
* because it can be called in lots of other parts of the program.
|
||||
* which could still collide with this one!
|
||||
*
|
||||
* Must rewrite to make truely thread-safe.
|
||||
*/
|
||||
|
||||
std::string rs_inet_ntoa(struct in_addr in)
|
||||
{
|
||||
RsStackMutex stack(inetMtx);
|
||||
|
||||
std::string addr(inet_ntoa(in));
|
||||
return addr;
|
||||
std::ostringstream str;
|
||||
uint8_t *bytes = (uint8_t *) &(in.s_addr);
|
||||
str << (int) bytes[0] << ".";
|
||||
str << (int) bytes[1] << ".";
|
||||
str << (int) bytes[2] << ".";
|
||||
str << (int) bytes[3];
|
||||
return str.str();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user