From 2dc2954f4033c0660eeebb1117e8202acb509c74 Mon Sep 17 00:00:00 2001 From: drbob Date: Thu, 28 Feb 2008 15:58:54 +0000 Subject: [PATCH] Added Code to detect Symmetric NAT (BAD!) Firewalls. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@361 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/pqi/p3connmgr.cc | 77 +++++++++++-- libretroshare/src/pqi/p3connmgr.h | 14 +-- libretroshare/src/pqi/p3dhtmgr.cc | 11 +- libretroshare/src/pqi/pqimonitor.h | 1 + libretroshare/src/rsiface/rspeers.h | 2 + libretroshare/src/rsserver/p3peers.cc | 21 +++- libretroshare/src/services/p3disc.cc | 26 ++++- libretroshare/src/tcponudp/tou.cc | 4 +- libretroshare/src/tcponudp/tou.h | 2 +- libretroshare/src/tcponudp/udpsorter.cc | 101 ++++++++++++++++-- libretroshare/src/tcponudp/udpsorter.h | 15 ++- retroshare-gui/src/gui/PeersDialog.cpp | 9 ++ .../src/gui/Preferences/ServerDialog.cpp | 15 ++- retroshare-gui/src/rsiface/rspeers.h | 2 + 14 files changed, 257 insertions(+), 43 deletions(-) diff --git a/libretroshare/src/pqi/p3connmgr.cc b/libretroshare/src/pqi/p3connmgr.cc index bc2e4ed8d..e88236326 100644 --- a/libretroshare/src/pqi/p3connmgr.cc +++ b/libretroshare/src/pqi/p3connmgr.cc @@ -91,6 +91,7 @@ p3ConnectMgr::p3ConnectMgr(p3AuthMgr *am) { mUpnpAddrValid = false; mStunAddrValid = false; + mStunAddrStable = false; /* setup basics of own state */ if (am) @@ -446,6 +447,7 @@ void p3ConnectMgr::netUdpCheck() if (stunCheck() || (mUpnpAddrValid)) { bool extValid = false; + bool extAddrStable = false; struct sockaddr_in extAddr; uint32_t mode = 0; @@ -462,21 +464,42 @@ void p3ConnectMgr::netUdpCheck() { extValid = true; extAddr = mUpnpExtAddr; + extAddrStable = true; } else if (mStunAddrValid) { extValid = true; extAddr = mStunExtAddr; + extAddrStable = mStunAddrStable; } if (extValid) { ownState.serveraddr = extAddr; - mode = RS_NET_CONN_TCP_LOCAL | RS_NET_CONN_UDP_DHT_SYNC; + mode = RS_NET_CONN_TCP_LOCAL; + if (mUpnpAddrValid || (ownState.netMode == RS_NET_MODE_EXT)) { mode |= RS_NET_CONN_TCP_EXTERNAL; } + else if (extAddrStable) + { + mode |= RS_NET_CONN_UDP_DHT_SYNC; + } + else // if (!extAddrStable) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netUdpCheck() UDP Unstable :( "; + std::cerr << std::endl; + std::cerr << "p3ConnectMgr::netUdpCheck() We are unreachable"; + std::cerr << std::endl; + std::cerr << "netMode => RS_NET_MODE_UNREACHABLE"; + std::cerr << std::endl; +#endif + ownState.netMode = RS_NET_MODE_UNREACHABLE; + tou_stunkeepalive(0); + } + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ } @@ -514,24 +537,26 @@ bool p3ConnectMgr::udpExtAddressCheck() */ struct sockaddr_in addr; socklen_t len = sizeof(addr); + uint8_t stable; #ifdef CONN_DEBUG std::cerr << "p3ConnectMgr::udpExtAddressCheck()" << std::endl; #endif - if (0 < tou_extaddr((struct sockaddr *) &addr, &len)) + if (0 < tou_extaddr((struct sockaddr *) &addr, &len, &stable)) { /* update UDP information */ connMtx.lock(); /* LOCK MUTEX */ mStunExtAddr = addr; mStunAddrValid = true; - + mStunAddrStable = (stable != 0); #ifdef CONN_DEBUG std::cerr << "p3ConnectMgr::udpExtAddressCheck() Got "; std::cerr << " addr: " << inet_ntoa(mStunExtAddr.sin_addr); - std::cerr << " port: " << ntohs(mStunExtAddr.sin_port); + std::cerr << ":" << ntohs(mStunExtAddr.sin_port); + std::cerr << " stable: " << mStunAddrStable; std::cerr << std::endl; #endif @@ -1217,10 +1242,15 @@ void p3ConnectMgr::peerStatus(std::string id, { it->second.netMode = RS_NET_MODE_EXT; } - else + else if (flags & RS_NET_FLAGS_STABLE_UDP) { it->second.netMode = RS_NET_MODE_UDP; } + else + { + it->second.netMode = RS_NET_MODE_UNREACHABLE; + } + /* always update VIS status */ if (flags & RS_NET_FLAGS_USE_DISC) @@ -1243,6 +1273,39 @@ void p3ConnectMgr::peerStatus(std::string id, IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ } + /* Determine Reachability (only advisory) */ + if (ownState.netMode == RS_NET_MODE_UDP) + { + if ((details.type & RS_NET_CONN_UDP_DHT_SYNC) || + (details.type & RS_NET_CONN_TCP_EXTERNAL)) + { + /* reachable! */ + it->second.state &= (~RS_PEER_S_UNREACHABLE); + } + else + { + /* unreachable */ + it->second.state |= RS_PEER_S_UNREACHABLE; + } + } + else if (ownState.netMode == RS_NET_MODE_UNREACHABLE) + { + if (details.type & RS_NET_CONN_TCP_EXTERNAL) + { + /* reachable! */ + it->second.state &= (~RS_PEER_S_UNREACHABLE); + } + else + { + /* unreachable */ + it->second.state |= RS_PEER_S_UNREACHABLE; + } + } + else + { + it->second.state &= (~RS_PEER_S_UNREACHABLE); + } + if (!isFriend) { std::cerr << "p3ConnectMgr::peerStatus() NOT FRIEND "; @@ -1896,7 +1959,7 @@ bool p3ConnectMgr::retryConnect(std::string id) } #endif - if (it->second.netMode != RS_NET_MODE_EXT) + if (it->second.netMode == RS_NET_MODE_UDP) { std::cerr << "p3ConnectMgr::retryConnect() trying UDP connection!"; std::cerr << " id: " << id; @@ -1907,7 +1970,7 @@ bool p3ConnectMgr::retryConnect(std::string id) } else { - std::cerr << "p3ConnectMgr::retryConnect() EXT so not trying UDP connection!"; + std::cerr << "p3ConnectMgr::retryConnect() EXT/UNREACHABLE so not trying UDP connection!"; std::cerr << " id: " << id; std::cerr << std::endl; } diff --git a/libretroshare/src/pqi/p3connmgr.h b/libretroshare/src/pqi/p3connmgr.h index e3fb821fb..e8f786388 100644 --- a/libretroshare/src/pqi/p3connmgr.h +++ b/libretroshare/src/pqi/p3connmgr.h @@ -63,13 +63,13 @@ const uint32_t RS_NET_MODE_TRY_UPNP = 0x0020; const uint32_t RS_NET_MODE_TRY_UDP = 0x0040; /* Actual State */ -const uint32_t RS_NET_MODE_ACTUAL = 0x000f; +const uint32_t RS_NET_MODE_ACTUAL = 0x000f; -const uint32_t RS_NET_MODE_UNKNOWN = 0x0000; -const uint32_t RS_NET_MODE_EXT = 0x0001; -const uint32_t RS_NET_MODE_UPNP = 0x0002; -const uint32_t RS_NET_MODE_UDP = 0x0004; -const uint32_t RS_NET_MODE_ERROR = 0x0008; +const uint32_t RS_NET_MODE_UNKNOWN = 0x0000; +const uint32_t RS_NET_MODE_EXT = 0x0001; +const uint32_t RS_NET_MODE_UPNP = 0x0002; +const uint32_t RS_NET_MODE_UDP = 0x0004; +const uint32_t RS_NET_MODE_UNREACHABLE = 0x0008; /* order of attempts ... */ @@ -86,6 +86,7 @@ const uint32_t RS_NET_FLAGS_USE_DISC = 0x0001; const uint32_t RS_NET_FLAGS_USE_DHT = 0x0002; const uint32_t RS_NET_FLAGS_ONLINE = 0x0004; const uint32_t RS_NET_FLAGS_EXTERNAL_ADDR = 0x0008; +const uint32_t RS_NET_FLAGS_STABLE_UDP = 0x0010; class peerAddrInfo { @@ -287,6 +288,7 @@ private: /* external Address determination */ bool mUpnpAddrValid, mStunAddrValid; + bool mStunAddrStable; struct sockaddr_in mUpnpExtAddr; struct sockaddr_in mStunExtAddr; diff --git a/libretroshare/src/pqi/p3dhtmgr.cc b/libretroshare/src/pqi/p3dhtmgr.cc index fc2d3180c..2b935f17e 100644 --- a/libretroshare/src/pqi/p3dhtmgr.cc +++ b/libretroshare/src/pqi/p3dhtmgr.cc @@ -36,8 +36,6 @@ * #define P3DHTMGR_USE_LOCAL_UDP_CONN 1 // For Testing only ****/ -#define P3DHTMGR_USE_LOCAL_UDP_CONN 1 // For Testing only - /**** DHT State Variables **** * TODO: * (1) notify call in. @@ -57,8 +55,8 @@ /* TIMEOUTS */ #define DHT_SEARCH_PERIOD 1800 /* PeerKeys: if we haven't found them: 30 min */ -#define DHT_CHECK_PERIOD 3600 /* PeerKeys: re-lookup peer: 60 min */ -#define DHT_PUBLISH_PERIOD 1800 /* OwnKey 30 min */ +#define DHT_CHECK_PERIOD 1800 /* PeerKeys: re-lookup peer: 30 min */ +#define DHT_PUBLISH_PERIOD 900 /* OwnKey 30 min (15 minutes for now) */ #define DHT_NOTIFY_PERIOD 300 /* 5 min - Notify Check period */ #define DHT_RESTART_PERIOD 300 /* 5 min */ @@ -547,8 +545,9 @@ int p3DhtMgr::checkOwnDHTKeys() /* check for connect requests */ - if ((peer.state == DHT_PEER_PUBLISHED) && - (!(peer.type & RS_NET_CONN_TCP_EXTERNAL))) + //if ((peer.state == DHT_PEER_PUBLISHED) && + // (!(peer.type & RS_NET_CONN_TCP_EXTERNAL))) + if (peer.state == DHT_PEER_PUBLISHED) { if (now - peer.notifyTS >= DHT_NOTIFY_PERIOD) { diff --git a/libretroshare/src/pqi/pqimonitor.h b/libretroshare/src/pqi/pqimonitor.h index e63b6db2d..55c8e0cab 100644 --- a/libretroshare/src/pqi/pqimonitor.h +++ b/libretroshare/src/pqi/pqimonitor.h @@ -46,6 +46,7 @@ const uint32_t RS_PEER_ACTION_MASK = 0xff00; const uint32_t RS_PEER_S_FRIEND = 0x0001; const uint32_t RS_PEER_S_ONLINE = 0x0002; /* heard from recently..*/ const uint32_t RS_PEER_S_CONNECTED = 0x0004; +const uint32_t RS_PEER_S_UNREACHABLE = 0x0008; /* ACTIONS */ const uint32_t RS_PEER_NEW = 0x0001; /* new Peer */ diff --git a/libretroshare/src/rsiface/rspeers.h b/libretroshare/src/rsiface/rspeers.h index a3b10eacd..f831dabac 100644 --- a/libretroshare/src/rsiface/rspeers.h +++ b/libretroshare/src/rsiface/rspeers.h @@ -44,6 +44,7 @@ const uint32_t RS_TRUST_LVL_GOOD = 0x0003; const uint32_t RS_NETMODE_UDP = 0x0001; const uint32_t RS_NETMODE_UPNP = 0x0002; const uint32_t RS_NETMODE_EXT = 0x0003; +const uint32_t RS_NETMODE_UNREACHABLE = 0x0004; /* Visibility */ const uint32_t RS_VS_DHT_ON = 0x0001; @@ -53,6 +54,7 @@ const uint32_t RS_VS_DISC_ON = 0x0002; const uint32_t RS_PEER_STATE_FRIEND = 0x0001; const uint32_t RS_PEER_STATE_ONLINE = 0x0002; const uint32_t RS_PEER_STATE_CONNECTED = 0x0004; +const uint32_t RS_PEER_STATE_UNREACHABLE= 0x0008; /* A couple of helper functions for translating the numbers games */ diff --git a/libretroshare/src/rsserver/p3peers.cc b/libretroshare/src/rsserver/p3peers.cc index f001007a1..7bb5d4ac1 100644 --- a/libretroshare/src/rsserver/p3peers.cc +++ b/libretroshare/src/rsserver/p3peers.cc @@ -62,6 +62,10 @@ std::string RsPeerStateString(uint32_t state) { str = "Connected"; } + else if (state & RS_PEER_STATE_UNREACHABLE) + { + str = "Unreachable"; + } else if (state & RS_PEER_STATE_ONLINE) { str = "Available"; @@ -92,6 +96,10 @@ std::string RsPeerNetModeString(uint32_t netModel) { str = "UDP Mode"; } + else if (netModel == RS_NETMODE_UNREACHABLE) + { + str = "UDP Mode (Unreachable)"; + } else { str = "Unknown NetMode"; @@ -272,6 +280,8 @@ bool p3Peers::getPeerDetails(std::string id, RsPeerDetails &d) d.state |= RS_PEER_STATE_ONLINE; if (pcs.state & RS_PEER_S_CONNECTED) d.state |= RS_PEER_STATE_CONNECTED; + if (pcs.state & RS_PEER_S_UNREACHABLE) + d.state |= RS_PEER_STATE_UNREACHABLE; switch(pcs.netMode & RS_NET_MODE_ACTUAL) { @@ -282,11 +292,13 @@ bool p3Peers::getPeerDetails(std::string id, RsPeerDetails &d) d.netMode = RS_NETMODE_UPNP; break; case RS_NET_MODE_UDP: - case RS_NET_MODE_UNKNOWN: - case RS_NET_MODE_ERROR: - default: d.netMode = RS_NETMODE_UDP; break; + case RS_NET_MODE_UNREACHABLE: + case RS_NET_MODE_UNKNOWN: + default: + d.netMode = RS_NETMODE_UNREACHABLE; + break; } if (pcs.netMode & RS_NET_MODE_TRY_EXT) @@ -433,6 +445,9 @@ bool p3Peers::setNetworkMode(std::string id, uint32_t extNetMode) case RS_NETMODE_UDP: netMode = RS_NET_MODE_UDP; break; + case RS_NETMODE_UNREACHABLE: + netMode = RS_NET_MODE_UNREACHABLE; + break; default: break; } diff --git a/libretroshare/src/services/p3disc.cc b/libretroshare/src/services/p3disc.cc index a4a37c3d3..6ad4685aa 100644 --- a/libretroshare/src/services/p3disc.cc +++ b/libretroshare/src/services/p3disc.cc @@ -54,8 +54,9 @@ static int convertTRangeToTDelta(int trange); const uint32_t P3DISC_FLAGS_USE_DISC = 0x0001; const uint32_t P3DISC_FLAGS_USE_DHT = 0x0002; const uint32_t P3DISC_FLAGS_EXTERNAL_ADDR = 0x0004; -const uint32_t P3DISC_FLAGS_PEER_ONLINE = 0x0008; -const uint32_t P3DISC_FLAGS_OWN_DETAILS = 0x0010; +const uint32_t P3DISC_FLAGS_STABLE_UDP = 0x0008; +const uint32_t P3DISC_FLAGS_PEER_ONLINE = 0x0010; +const uint32_t P3DISC_FLAGS_OWN_DETAILS = 0x0020; #define P3DISC_DEBUG 1 @@ -342,6 +343,11 @@ void p3disc::sendOwnDetails(std::string to) { di->discFlags |= P3DISC_FLAGS_EXTERNAL_ADDR; } + else if (detail.netMode & RS_NET_MODE_UDP) + { + di->discFlags |= P3DISC_FLAGS_STABLE_UDP; + } + di->discFlags |= P3DISC_FLAGS_OWN_DETAILS; /* send msg */ @@ -415,6 +421,10 @@ void p3disc::sendPeerDetails(std::string to, std::string about) { di->discFlags |= P3DISC_FLAGS_EXTERNAL_ADDR; } + else if (detail.netMode & RS_NET_MODE_UDP) + { + di->discFlags |= P3DISC_FLAGS_STABLE_UDP; + } if (detail.state & RS_PEER_S_CONNECTED) { @@ -484,6 +494,12 @@ void p3disc::recvPeerOwnMsg(RsDiscItem *item) flags |= RS_NET_FLAGS_EXTERNAL_ADDR; } + if (item->discFlags & P3DISC_FLAGS_STABLE_UDP) + { + type |= RS_NET_CONN_UDP_DHT_SYNC; + flags |= RS_NET_FLAGS_STABLE_UDP; + } + mConnMgr->peerStatus(item->PeerId(), item->laddr, item->saddr, type, flags, RS_CB_PERSON); @@ -546,6 +562,12 @@ void p3disc::recvPeerFriendMsg(RsDiscReply *item) flags |= RS_NET_FLAGS_EXTERNAL_ADDR; } + if (item->discFlags & P3DISC_FLAGS_STABLE_UDP) + { + type |= RS_NET_CONN_UDP_DHT_SYNC; + flags |= RS_NET_FLAGS_STABLE_UDP; + } + /* only valid certs, and not ourselves */ if ((loaded) && (peerId != mConnMgr->getOwnId())) { diff --git a/libretroshare/src/tcponudp/tou.cc b/libretroshare/src/tcponudp/tou.cc index 7152eb91d..7e24ce64e 100644 --- a/libretroshare/src/tcponudp/tou.cc +++ b/libretroshare/src/tcponudp/tou.cc @@ -107,12 +107,12 @@ int tou_tick_stunkeepalive() return 1; } -int tou_extaddr(struct sockaddr *ext_addr, socklen_t *addrlen) +int tou_extaddr(struct sockaddr *ext_addr, socklen_t *addrlen, uint8_t *stable) { if (!tou_inited) return -1; - if (udps->externalAddr(*(struct sockaddr_in *) ext_addr)) + if (udps->externalAddr(*(struct sockaddr_in *) ext_addr, *stable)) { return 1; } diff --git a/libretroshare/src/tcponudp/tou.h b/libretroshare/src/tcponudp/tou.h index 6bf72ff70..49a797d35 100644 --- a/libretroshare/src/tcponudp/tou.h +++ b/libretroshare/src/tcponudp/tou.h @@ -72,7 +72,7 @@ extern "C" { */ int tou_init(const struct sockaddr *my_addr, socklen_t addrlen); -int tou_extaddr(struct sockaddr *ext_addr, socklen_t *addrlen); +int tou_extaddr(struct sockaddr *ext_addr, socklen_t *addrlen, uint8_t *stable); int tou_stunpeer(const struct sockaddr *ext_addr, socklen_t addrlen, const char *id); int tou_stunkeepalive(int required); int tou_tick_stunkeepalive(); diff --git a/libretroshare/src/tcponudp/udpsorter.cc b/libretroshare/src/tcponudp/udpsorter.cc index 8610ee516..edc229b23 100644 --- a/libretroshare/src/tcponudp/udpsorter.cc +++ b/libretroshare/src/tcponudp/udpsorter.cc @@ -39,7 +39,7 @@ static const int STUN_TTL = 64; #define DEBUG_UDP_SORTER 1 UdpSorter::UdpSorter(struct sockaddr_in &local) - :udpLayer(NULL), laddr(local), eaddrKnown(false), + :udpLayer(NULL), laddr(local), eaddrKnown(false), eaddrStable(false), mStunKeepAlive(false), mStunLastRecv(0), mStunLastSend(0) @@ -234,10 +234,7 @@ bool UdpSorter::locked_handleStunPkt(void *data, int size, struct sockaddr_in &f std::cerr << inet_ntoa(eAddr.sin_addr) << ":" << ntohs(eAddr.sin_port); std::cerr << std::endl; #endif - eaddrKnown = true; - eaddr = eAddr; - - locked_recvdStun(from); + locked_recvdStun(from, eAddr); return true; } @@ -251,11 +248,17 @@ bool UdpSorter::locked_handleStunPkt(void *data, int size, struct sockaddr_in &f } -bool UdpSorter::externalAddr(struct sockaddr_in &external) +bool UdpSorter::externalAddr(struct sockaddr_in &external, uint8_t &stable) { if (eaddrKnown) { external = eaddr; + + if (eaddrStable) + stable = 1; + else + stable = 0; + return true; } return false; @@ -612,15 +615,21 @@ bool UdpSorter::checkStunKeepAlive() } -bool UdpSorter::locked_recvdStun(const struct sockaddr_in &remote) +bool UdpSorter::locked_recvdStun(const struct sockaddr_in &remote, const struct sockaddr_in &extaddr) { #ifdef DEBUG_UDP_SORTER - std::cerr << "UdpSorter::recvdStun()"; - std::cerr << std::endl; + std::ostringstream out; + out << "UdpSorter::locked_recvdStun() from:"; + out << inet_ntoa(remote.sin_addr) << ":" << ntohs(remote.sin_port); + out << " claiming ExtAddr is:"; + out << inet_ntoa(extaddr.sin_addr) << ":" << ntohs(extaddr.sin_port); + + std::cerr << out.str() << std::endl; #endif locked_printStunList(); + bool found = true; std::list::iterator it; for(it = mStunList.begin(); it != mStunList.end(); it++) { @@ -628,13 +637,85 @@ bool UdpSorter::locked_recvdStun(const struct sockaddr_in &remote) (remote.sin_port == it->remote.sin_port)) { it->failCount = 0; - return true; + it->eaddr = extaddr; + it->response = true; + + found = true; + break; } } + if (!eaddrKnown) + { + locked_checkExternalAddress(); + } + + return found; +} + +bool UdpSorter::locked_checkExternalAddress() +{ +#ifdef DEBUG_UDP_SORTER + std::ostringstream out; + out << "UdpSorter::locked_checkExternalAddress()"; + std::cerr << out.str() << std::endl; +#endif + + bool found1 = false; + bool found2 = false; + + std::list::iterator it; + std::list::iterator p1; + std::list::iterator p2; + for(it = mStunList.begin(); it != mStunList.end(); it++) + { + if (it->response) + { + if (!found1) + { + p1 = it; + found1 = true; + } + else + { + p2 = it; + found2 = true; + break; + } + } + } + + if (found1 && found2) + { + if ((p1->eaddr.sin_addr.s_addr == p2->eaddr.sin_addr.s_addr) && + (p1->eaddr.sin_port == p2->eaddr.sin_port)) + { + eaddrStable = true; + } + else + { + eaddrStable = false; + } + eaddrKnown = true; + eaddr = p1->eaddr; + +#ifdef DEBUG_UDP_SORTER + std::cerr << "UdpSorter::locked_checkExternalAddress() Found State:"; + if (eaddrStable) + std::cerr << " Stable NAT translation (GOOD!) "; + else + std::cerr << " unStable (symmetric NAT translation (BAD!) "; + std::cerr << std::endl; +#endif + + return true; + } + return false; } + + bool UdpSorter::locked_printStunList() { std::ostringstream out; diff --git a/libretroshare/src/tcponudp/udpsorter.h b/libretroshare/src/tcponudp/udpsorter.h index 937068426..6c5834ac5 100644 --- a/libretroshare/src/tcponudp/udpsorter.h +++ b/libretroshare/src/tcponudp/udpsorter.h @@ -49,13 +49,14 @@ class TouStunPeer { public: TouStunPeer() - :lastsend(0), failCount(0) { return; } + :response(false), lastsend(0), failCount(0) { return; } TouStunPeer(std::string id_in, const struct sockaddr_in &addr) - :id(id_in), remote(addr), lastsend(0), failCount(0) { return; } + :id(id_in), remote(addr), response(false), lastsend(0), failCount(0) { return; } std::string id; - struct sockaddr_in remote; + struct sockaddr_in remote, eaddr; + bool response; time_t lastsend; uint32_t failCount; }; @@ -75,7 +76,7 @@ bool setStunKeepAlive(uint32_t required); bool addStunPeer(const struct sockaddr_in &remote, const char *peerid); bool checkStunKeepAlive(); -bool externalAddr(struct sockaddr_in &remote); +bool externalAddr(struct sockaddr_in &remote, uint8_t &stable); /* Packet IO */ /* pass-through send packets */ @@ -108,7 +109,9 @@ bool generate_stun_pkt(void *stun_pkt, int *len); /* stun keepAlive */ bool locked_printStunList(); -bool locked_recvdStun(const struct sockaddr_in &remote); +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); UdpLayer *udpLayer; @@ -116,8 +119,10 @@ bool storeStunPeer(const struct sockaddr_in &remote, const char *peerid); RsMutex sortMtx; /* for all class data (below) */ struct sockaddr_in laddr; /* local addr */ + struct sockaddr_in eaddr; /* external addr */ bool eaddrKnown; + bool eaddrStable; /* if true then usable. if false -> Symmettric NAT */ bool mStunKeepAlive; time_t mStunLastRecv; diff --git a/retroshare-gui/src/gui/PeersDialog.cpp b/retroshare-gui/src/gui/PeersDialog.cpp index d52e6343e..4c6dd01eb 100644 --- a/retroshare-gui/src/gui/PeersDialog.cpp +++ b/retroshare-gui/src/gui/PeersDialog.cpp @@ -251,6 +251,15 @@ void PeersDialog::insertPeers() item -> setIcon(0,(QIcon(IMAGE_ONLINE))); } } + else if (detail.state & RS_PEER_STATE_UNREACHABLE) + { + /* bright green */ + for(i = 1; i < 12; i++) + { + item -> setBackground(i,QBrush(Qt::red)); + item -> setIcon(0,(QIcon(IMAGE_OFFLINE))); + } + } else if (detail.state & RS_PEER_STATE_ONLINE) { /* bright green */ diff --git a/retroshare-gui/src/gui/Preferences/ServerDialog.cpp b/retroshare-gui/src/gui/Preferences/ServerDialog.cpp index 92445199a..838eb1905 100644 --- a/retroshare-gui/src/gui/Preferences/ServerDialog.cpp +++ b/retroshare-gui/src/gui/Preferences/ServerDialog.cpp @@ -144,10 +144,13 @@ void ServerDialog::load() case RS_NETMODE_UDP: out << "Firewalled"; break; - default: case RS_NETMODE_UPNP: out << "Automatic: UPnP Forwarded Port"; break; + default: + case RS_NETMODE_UNREACHABLE: + out << "Unreachable: Firewalled by Symmetric NAT"; + break; } out << std::endl; out << "\tLocal Address: " << detail.localAddr; @@ -175,6 +178,16 @@ void ServerDialog::load() out << std::endl; + + if (detail.netMode == RS_NETMODE_UNREACHABLE) + { + ui.netStatusBox->setTextColor( Qt::red ); + } + else + { + ui.netStatusBox->setTextColor( Qt::black ); + } + ui.netStatusBox->setText(QString::fromStdString(out.str())); ui.netStatusBox ->setReadOnly(true); diff --git a/retroshare-gui/src/rsiface/rspeers.h b/retroshare-gui/src/rsiface/rspeers.h index a3b10eacd..f831dabac 100644 --- a/retroshare-gui/src/rsiface/rspeers.h +++ b/retroshare-gui/src/rsiface/rspeers.h @@ -44,6 +44,7 @@ const uint32_t RS_TRUST_LVL_GOOD = 0x0003; const uint32_t RS_NETMODE_UDP = 0x0001; const uint32_t RS_NETMODE_UPNP = 0x0002; const uint32_t RS_NETMODE_EXT = 0x0003; +const uint32_t RS_NETMODE_UNREACHABLE = 0x0004; /* Visibility */ const uint32_t RS_VS_DHT_ON = 0x0001; @@ -53,6 +54,7 @@ const uint32_t RS_VS_DISC_ON = 0x0002; const uint32_t RS_PEER_STATE_FRIEND = 0x0001; const uint32_t RS_PEER_STATE_ONLINE = 0x0002; const uint32_t RS_PEER_STATE_CONNECTED = 0x0004; +const uint32_t RS_PEER_STATE_UNREACHABLE= 0x0008; /* A couple of helper functions for translating the numbers games */