@ -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 ( ) ;
}
ret . nServices = nLocalServices ;
ret . nTime = GetAdjustedTime ( ) ;
return ret ;
}
@ -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 )
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 )
{
if ( pnode - > fSuccessfullyConnected )
CAddress addrLocal = GetLocalAddress ( & pnode - > addr ) ;
// 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 ) )
{
CAddress addrLocal = GetLocalAddress ( & pnode - > addr ) ;
if ( addrLocal . IsRoutable ( ) & & ( CService ) addrLocal ! = ( CService ) pnode - > addrLocal )
{
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)
SetReachable ( addr . GetNetwork ( ) ) ;
}
AdvertizeLocal ( ) ;
return true ;
}
@ -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)
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)
}
# 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 )