|
|
|
@ -142,16 +142,19 @@ bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
@@ -142,16 +142,19 @@ bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// get best local address for a particular peer as a CAddress
|
|
|
|
|
// Otherwise, return the unroutable 0.0.0.0 but filled in with
|
|
|
|
|
// the normal parameters, since the IP may be changed to a useful
|
|
|
|
|
// one by discovery.
|
|
|
|
|
CAddress GetLocalAddress(const CNetAddr *paddrPeer) |
|
|
|
|
{ |
|
|
|
|
CAddress ret(CService("0.0.0.0",0),0); |
|
|
|
|
CAddress ret(CService("0.0.0.0",GetListenPort()),0); |
|
|
|
|
CService addr; |
|
|
|
|
if (GetLocal(addr, paddrPeer)) |
|
|
|
|
{ |
|
|
|
|
ret = CAddress(addr); |
|
|
|
|
} |
|
|
|
|
ret.nServices = nLocalServices; |
|
|
|
|
ret.nTime = GetAdjustedTime(); |
|
|
|
|
} |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -205,21 +208,38 @@ bool RecvLine(SOCKET hSocket, string& strLine)
@@ -205,21 +208,38 @@ bool RecvLine(SOCKET hSocket, string& strLine)
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// used when scores of local addresses may have changed
|
|
|
|
|
// pushes better local address to peers
|
|
|
|
|
void static AdvertizeLocal() |
|
|
|
|
int GetnScore(const CService& addr) |
|
|
|
|
{ |
|
|
|
|
LOCK(cs_vNodes); |
|
|
|
|
BOOST_FOREACH(CNode* pnode, vNodes) |
|
|
|
|
{ |
|
|
|
|
if (pnode->fSuccessfullyConnected) |
|
|
|
|
LOCK(cs_mapLocalHost); |
|
|
|
|
if (mapLocalHost.count(addr) == LOCAL_NONE) |
|
|
|
|
return 0; |
|
|
|
|
return mapLocalHost[addr].nScore; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Is our peer's addrLocal potentially useful as an external IP source?
|
|
|
|
|
bool IsPeerAddrLocalGood(CNode *pnode) |
|
|
|
|
{ |
|
|
|
|
return fDiscover && pnode->addr.IsRoutable() && pnode->addrLocal.IsRoutable() && |
|
|
|
|
!IsLimited(pnode->addrLocal.GetNetwork()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// pushes our own address to a peer
|
|
|
|
|
void AdvertizeLocal(CNode *pnode) |
|
|
|
|
{ |
|
|
|
|
if (fListen && pnode->fSuccessfullyConnected) |
|
|
|
|
{ |
|
|
|
|
CAddress addrLocal = GetLocalAddress(&pnode->addr); |
|
|
|
|
if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal) |
|
|
|
|
// If discovery is enabled, sometimes give our peer the address it
|
|
|
|
|
// tells us that it sees us as in case it has a better idea of our
|
|
|
|
|
// address than we do.
|
|
|
|
|
if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() || |
|
|
|
|
GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0)) |
|
|
|
|
{ |
|
|
|
|
pnode->PushAddress(addrLocal); |
|
|
|
|
pnode->addrLocal = addrLocal; |
|
|
|
|
addrLocal.SetIP(pnode->addrLocal); |
|
|
|
|
} |
|
|
|
|
if (addrLocal.IsRoutable()) |
|
|
|
|
{ |
|
|
|
|
pnode->PushAddress(addrLocal); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -257,8 +277,6 @@ bool AddLocal(const CService& addr, int nScore)
@@ -257,8 +277,6 @@ bool AddLocal(const CService& addr, int nScore)
|
|
|
|
|
SetReachable(addr.GetNetwork()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
AdvertizeLocal(); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -296,12 +314,10 @@ bool SeenLocal(const CService& addr)
@@ -296,12 +314,10 @@ bool SeenLocal(const CService& addr)
|
|
|
|
|
return false; |
|
|
|
|
mapLocalHost[addr].nScore++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
AdvertizeLocal(); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** check whether a given address is potentially local */ |
|
|
|
|
bool IsLocal(const CService& addr) |
|
|
|
|
{ |
|
|
|
@ -323,114 +339,12 @@ bool IsReachable(const CNetAddr& addr)
@@ -323,114 +339,12 @@ bool IsReachable(const CNetAddr& addr)
|
|
|
|
|
return IsReachable(net); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet) |
|
|
|
|
{ |
|
|
|
|
SOCKET hSocket; |
|
|
|
|
if (!ConnectSocket(addrConnect, hSocket)) |
|
|
|
|
return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString()); |
|
|
|
|
|
|
|
|
|
send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL); |
|
|
|
|
|
|
|
|
|
string strLine; |
|
|
|
|
while (RecvLine(hSocket, strLine)) |
|
|
|
|
{ |
|
|
|
|
if (strLine.empty()) // HTTP response is separated from headers by blank line
|
|
|
|
|
{ |
|
|
|
|
while (true) |
|
|
|
|
{ |
|
|
|
|
if (!RecvLine(hSocket, strLine)) |
|
|
|
|
{ |
|
|
|
|
CloseSocket(hSocket); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
if (pszKeyword == NULL) |
|
|
|
|
break; |
|
|
|
|
if (strLine.find(pszKeyword) != string::npos) |
|
|
|
|
{ |
|
|
|
|
strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword)); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
CloseSocket(hSocket); |
|
|
|
|
if (strLine.find("<") != string::npos) |
|
|
|
|
strLine = strLine.substr(0, strLine.find("<")); |
|
|
|
|
strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r")); |
|
|
|
|
while (strLine.size() > 0 && isspace(strLine[strLine.size()-1])) |
|
|
|
|
strLine.resize(strLine.size()-1); |
|
|
|
|
CService addr(strLine,0,true); |
|
|
|
|
LogPrintf("GetMyExternalIP() received [%s] %s\n", strLine, addr.ToString()); |
|
|
|
|
if (!addr.IsValid() || !addr.IsRoutable()) |
|
|
|
|
return false; |
|
|
|
|
ipRet.SetIP(addr); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
CloseSocket(hSocket); |
|
|
|
|
return error("GetMyExternalIP() : connection closed"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool GetMyExternalIP(CNetAddr& ipRet) |
|
|
|
|
{ |
|
|
|
|
CService addrConnect; |
|
|
|
|
const char* pszGet; |
|
|
|
|
const char* pszKeyword; |
|
|
|
|
|
|
|
|
|
for (int nLookup = 0; nLookup <= 1; nLookup++) |
|
|
|
|
for (int nHost = 1; nHost <= 1; nHost++) |
|
|
|
|
{ |
|
|
|
|
// We should be phasing out our use of sites like these. If we need
|
|
|
|
|
// replacements, we should ask for volunteers to put this simple
|
|
|
|
|
// php file on their web server that prints the client IP:
|
|
|
|
|
// <?php echo $_SERVER["REMOTE_ADDR"]; ?>
|
|
|
|
|
if (nHost == 1) |
|
|
|
|
{ |
|
|
|
|
addrConnect = CService("91.198.22.70", 80); // checkip.dyndns.org
|
|
|
|
|
|
|
|
|
|
if (nLookup == 1) |
|
|
|
|
{ |
|
|
|
|
CService addrIP("checkip.dyndns.org", 80, true); |
|
|
|
|
if (addrIP.IsValid()) |
|
|
|
|
addrConnect = addrIP; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pszGet = "GET / HTTP/1.1\r\n" |
|
|
|
|
"Host: checkip.dyndns.org\r\n" |
|
|
|
|
"User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n" |
|
|
|
|
"Connection: close\r\n" |
|
|
|
|
"\r\n"; |
|
|
|
|
|
|
|
|
|
pszKeyword = "Address:"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ThreadGetMyExternalIP() |
|
|
|
|
{ |
|
|
|
|
CNetAddr addrLocalHost; |
|
|
|
|
if (GetMyExternalIP(addrLocalHost)) |
|
|
|
|
{ |
|
|
|
|
LogPrintf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP()); |
|
|
|
|
AddLocal(addrLocalHost, LOCAL_HTTP); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void AddressCurrentlyConnected(const CService& addr) |
|
|
|
|
{ |
|
|
|
|
addrman.Connected(addr); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint64_t CNode::nTotalBytesRecv = 0; |
|
|
|
|
uint64_t CNode::nTotalBytesSent = 0; |
|
|
|
|
CCriticalSection CNode::cs_totalBytesRecv; |
|
|
|
@ -1687,9 +1601,6 @@ void static Discover(boost::thread_group& threadGroup)
@@ -1687,9 +1601,6 @@ void static Discover(boost::thread_group& threadGroup)
|
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// Don't use external IPv4 discovery, when -onlynet="IPv6"
|
|
|
|
|
if (!IsLimited(NET_IPV4)) |
|
|
|
|
threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "ext-ip", &ThreadGetMyExternalIP)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void StartNode(boost::thread_group& threadGroup) |
|
|
|
|