/* * Modification History * * 2004-January-1 Jason Rohrer * Created. * * 2004-January-2 Jason Rohrer * Fixed a memory leak. * * 2004-January-20 Jason Rohrer * Changed to send client version to make compatible with GWC2 caches. * Fixed bugs in parameter order. * * 2004-March-28 Jason Rohrer * Changed postLocalAddress to post to all caches instead of to a random cache. * * 2004-March-30 Jason Rohrer * Changed to avoid re-seeding the random number generator for each query. */ #include "SimpleWebHostCache.h" #include "minorGems/util/SettingsManager.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/random/StdRandomSource.h" #include "minorGems/network/web/WebClient.h" #include "minorGems/network/web/URLUtils.h" StdRandomSource SimpleWebHostCache::mRandSource; int SimpleWebHostCache::getSeedNodes( char ***outNodeAddresses, int **outNodePorts ) { const char *clientName = "MUTE"; char *muteVersion = SettingsManager::getStringSetting( "muteVersion" ); if( muteVersion == NULL ) { muteVersion = stringDuplicate( "unknown" ); } if( strcmp( muteVersion, "" ) == 0 ) { delete [] muteVersion; muteVersion = stringDuplicate( "unknown" ); } SimpleVector *webCacheURLs = SettingsManager::getSetting( "webHostCaches" ); int numCaches = webCacheURLs->size(); char seedsFound = false; int numSeedsFound = -1; char **seedAddresses; int *seedPorts; // pick a web cache at random from the list and fetch // seed hosts from it. // keep trying if we fail to fetch from a cache, // but try at most _numCaches_ times // (thus, if there is only one cache, we will try only once) int tryCount = 0; int maxTries = numCaches; while( !seedsFound && tryCount < maxTries ) { int cachePick = mRandSource.getRandomBoundedInt( 0, numCaches - 1 ); // compose a URL that asks for a hostfile char *urlToGet = autoSprintf( "%s?client=%s&version=%s&hostfile=1", *( webCacheURLs->getElement( cachePick ) ), clientName, muteVersion ); // request the URL int dataLength; char *dataFromWebCache = WebClient::getWebPage( urlToGet, &dataLength ); if( dataFromWebCache != NULL ) { if( strstr( dataFromWebCache, ":" ) != NULL ) { // at least one host in cache // spilt up seed nodes into separate strings SimpleVector *hostsAndPorts = tokenizeString( dataFromWebCache ); SimpleVector *hostAddresses = new SimpleVector(); SimpleVector *hostPorts = new SimpleVector(); numSeedsFound = hostsAndPorts->size(); for( int i=0; igetElement( i ) ); char *pointerToColon = strstr( hostAndPort, ":" ); if( pointerToColon != NULL ) { // remove colon pointerToColon[0] = ' '; // read the port int port; int numRead = sscanf( pointerToColon, "%d", &port ); if( numRead == 1 ) { // terminate the string where the colon used // to be pointerToColon[0] = '\0'; // now extract the host address char *address = stringDuplicate( hostAndPort ); // add it to the list of extracted addresses hostAddresses->push_back( address ); hostPorts->push_back( (long)port ); } } // else no colon found --- bad format delete [] hostAndPort; } delete hostsAndPorts; // if we got some addresses from this web cache, save them numSeedsFound = hostAddresses->size(); if( numSeedsFound > 0 ) { seedAddresses = new char*[ numSeedsFound ]; seedPorts = new int[ numSeedsFound ]; for( int i=0; igetElement( i ) ); seedPorts[i] = (int)( *( hostPorts->getElement( i ) ) ); } seedsFound = true; *outNodeAddresses = seedAddresses; *outNodePorts = seedPorts; } else { for( int i=0; igetElement( i ) ); } } delete hostAddresses; delete hostPorts; } delete [] dataFromWebCache; } delete [] urlToGet; tryCount++; } for( int i=0; igetElement( i ) ); } delete webCacheURLs; delete [] muteVersion; if( seedsFound ) { return numSeedsFound; } else { return -1; } } void SimpleWebHostCache::postLocalAddress( char *inLocalAddress, int inLocalPort ) { char *addressToPost = autoSprintf( "%s:%d", inLocalAddress, inLocalPort ); // we must URL-safe encode our address char *encodedAddress = URLUtils::hexEncode( addressToPost ); delete [] addressToPost; const char *clientName = "MUTE"; char *muteVersion = SettingsManager::getStringSetting( "muteVersion" ); if( muteVersion == NULL ) { muteVersion = stringDuplicate( "unknown" ); } if( strcmp( muteVersion, "" ) == 0 ) { delete [] muteVersion; muteVersion = stringDuplicate( "unknown" ); } SimpleVector *webCacheURLs = SettingsManager::getSetting( "webHostCaches" ); int numCaches = webCacheURLs->size(); // post to all of the caches for( int i=0; igetElement( i ) ), clientName, muteVersion, encodedAddress ); // request the URL int dataLength; char *dataFromWebCache = WebClient::getWebPage( urlToGet, &dataLength ); if( dataFromWebCache != NULL ) { if( strstr( dataFromWebCache, "OK" ) != NULL ) { // got OK response // don't do anything special for now } delete [] dataFromWebCache; } delete [] urlToGet; } for( int i=0; igetElement( i ) ); } delete webCacheURLs; delete [] encodedAddress; delete [] muteVersion; }