Browse Source

Rewrite CNetAddr::GetReachabilityFrom()

Add support for Tor/I2P networks, and make code more readable.
miguelfreitas
Pieter Wuille 13 years ago
parent
commit
d077dd2a6e
  1. 103
      src/netbase.cpp
  2. 2
      src/netbase.h

103
src/netbase.cpp

@ -910,39 +910,82 @@ void CNetAddr::print() const
printf("CNetAddr(%s)\n", ToString().c_str()); printf("CNetAddr(%s)\n", ToString().c_str());
} }
// for IPv6 partners: for unknown/Teredo partners: for IPv4 partners: for Tor partners: for I2P partners: // private extensions to enum Network, only returned by GetExtNetwork,
// 0 - unroutable // 0 - unroutable // 0 - unroutable // 0 - unroutable // 0 - unroutable // and only used in GetReachabilityFrom
// 1 - teredo // 1 - teredo // 1 - ipv4 // 1 - the rest // 1 - the rest static const int NET_UNKNOWN = NET_MAX + 0;
// 2 - tunneled ipv6 // 2 - tunneled ipv6 // 2 - ip4 // 2 - I2P static const int NET_TEREDO = NET_MAX + 1;
// 3 - ipv4 // 3 - ipv6 // 3 - tor int static GetExtNetwork(const CNetAddr *addr)
// 4 - ipv6 // 4 - ipv4 {
if (addr == NULL)
return NET_UNKNOWN;
if (addr->IsRFC4380())
return NET_TEREDO;
return addr->GetNetwork();
}
/** Calculates a metric for how reachable (*this) is from a given partner */
int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
{ {
if (!IsValid() || !IsRoutable()) enum Reachability {
return 0; REACH_UNREACHABLE,
if (paddrPartner && paddrPartner->IsIPv4()) REACH_DEFAULT,
return IsIPv4() ? 1 : 0; REACH_TEREDO,
if (paddrPartner && paddrPartner->IsTor()) { REACH_IPV6_WEAK,
if (IsIPv4()) REACH_IPV4,
return 2; REACH_IPV6_STRONG,
if (IsTor()) REACH_PRIVATE
return 3; };
return 1;
} if (!IsRoutable())
if (paddrPartner && paddrPartner->IsI2P()) { return REACH_UNREACHABLE;
if (IsI2P())
return 2; int ourNet = GetExtNetwork(this);
return 1; int theirNet = GetExtNetwork(paddrPartner);
bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145();
switch(theirNet) {
case NET_IPV4:
switch(ourNet) {
default: return REACH_DEFAULT;
case NET_IPV4: return REACH_IPV4;
}
case NET_IPV6:
switch(ourNet) {
default: return REACH_DEFAULT;
case NET_TEREDO: return REACH_TEREDO;
case NET_IPV4: return REACH_IPV4;
case NET_IPV6: return fTunnel ? REACH_IPV6_WEAK : REACH_IPV6_STRONG; // only prefer giving our IPv6 address if it's not tunneled
}
case NET_TOR:
switch(ourNet) {
default: return REACH_DEFAULT;
case NET_IPV4: return REACH_IPV4; // Tor users can connect to IPv4 as well
case NET_TOR: return REACH_PRIVATE;
}
case NET_I2P:
switch(ourNet) {
default: return REACH_DEFAULT;
case NET_I2P: return REACH_PRIVATE;
}
case NET_TEREDO:
switch(ourNet) {
default: return REACH_DEFAULT;
case NET_TEREDO: return REACH_TEREDO;
case NET_IPV6: return REACH_IPV6_WEAK;
case NET_IPV4: return REACH_IPV4;
}
case NET_UNKNOWN:
case NET_UNROUTABLE:
default:
switch(ourNet) {
default: return REACH_DEFAULT;
case NET_TEREDO: return REACH_TEREDO;
case NET_IPV6: return REACH_IPV6_WEAK;
case NET_IPV4: return REACH_IPV4;
case NET_I2P: return REACH_PRIVATE; // assume connections from unroutable addresses are
case NET_TOR: return REACH_PRIVATE; // either from Tor/I2P, or don't care about our address
}
} }
if (IsRFC4380())
return 1;
if (IsRFC3964() || IsRFC6052())
return 2;
bool fRealIPv6 = paddrPartner && !paddrPartner->IsRFC4380() && paddrPartner->IsValid() && paddrPartner->IsRoutable();
if (fRealIPv6)
return IsIPv4() ? 3 : 4;
else
return IsIPv4() ? 4 : 3;
} }
void CService::Init() void CService::Init()

2
src/netbase.h

@ -25,7 +25,7 @@ enum Network
NET_TOR, NET_TOR,
NET_I2P, NET_I2P,
NET_MAX NET_MAX,
}; };
extern int nConnectTimeout; extern int nConnectTimeout;

Loading…
Cancel
Save