Util.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006-2010 Jacek Sieka, arnetheduck on gmail point com
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #include "adchpp.h"
00020 
00021 #include "Util.h"
00022 #include "FastAlloc.h"
00023 
00024 #include <locale.h>
00025 #ifndef _WIN32
00026 #include <sys/socket.h>
00027 #include <netinet/in.h>
00028 #include <arpa/inet.h>
00029 #include <netdb.h>
00030 #include <sys/utsname.h>
00031 #include <ctype.h>
00032 
00033 #endif
00034 
00035 namespace adchpp {
00036 
00037 using namespace std;
00038 
00039 #ifdef NDEBUG
00040 FastMutex FastAllocBase::mtx;
00041 #endif
00042 
00043 #ifndef _WIN32
00044 string Util::appName;
00045 string Util::appPath;
00046 #endif
00047 
00048 size_t Stats::queueCalls = 0;
00049 int64_t Stats::queueBytes = 0;
00050 size_t Stats::sendCalls = 0;
00051 int64_t Stats::sendBytes = 0;
00052 int64_t Stats::recvCalls = 0;
00053 int64_t Stats::recvBytes = 0;
00054 time_t Stats::startTime = 0;
00055 
00056 string Util::emptyString;
00057 wstring Util::emptyStringW;
00058 string Util::cfgPath;
00059 size_t Util::reasons[REASON_LAST];
00060 
00061 static void sgenrand(unsigned long seed);
00062 
00063 void Util::initialize(const string& configPath) {
00064     setlocale(LC_ALL, "");
00065     sgenrand((unsigned long)time(NULL));
00066 
00067     setCfgPath(configPath);
00068 }
00069 
00076 void Util::decodeUrl(const string& url, string& aServer, short& aPort, string& aFile) {
00077     // First, check for a protocol: xxxx://
00078     string::size_type i = 0, j, k;
00079 
00080     aServer.clear();
00081     aFile.clear();
00082 
00083     if( (j=url.find("://", i)) != string::npos) {
00084         // Protocol found
00085         string protocol = url.substr(0, j);
00086         i = j + 3;
00087 
00088         if(protocol == "http") {
00089             aPort = 80;
00090         } else if(protocol == "dchub") {
00091             aPort = 411;
00092         }
00093     }
00094 
00095     if( (j=url.find('/', i)) != string::npos) {
00096         // We have a filename...
00097         aFile = url.substr(j);
00098     }
00099 
00100     if( (k=url.find(':', i)) != string::npos) {
00101         // Port
00102         if(k < j)
00103             aPort = (short)Util::toInt(url.substr(k+1, j-k-1));
00104     } else {
00105         k = j;
00106     }
00107 
00108     // Only the server should be left now...
00109     aServer = url.substr(i, k-i);
00110 }
00111 
00112 
00113 void Util::tokenize(StringList& lst, const string& str, char sep, string::size_type j) {
00114     string::size_type i = 0;
00115     while( (i=str.find_first_of(sep, j)) != string::npos ) {
00116         lst.push_back(str.substr(j, i-j));
00117         j = i + 1;
00118     }
00119     if(j <= str.size())
00120         lst.push_back(str.substr(j, str.size()-j));
00121 }
00122 
00123 #ifdef _WIN32
00124 string Util::getAppPath() {
00125     string tmp = getAppName();
00126     string::size_type i = tmp.rfind('\\');
00127     if(i != string::npos)
00128         tmp.erase(i+1);
00129     return tmp;
00130 }
00131 
00132 string Util::getAppName() {
00133     string tmp(MAX_PATH + 1, '\0');
00134     tmp.resize(::GetModuleFileNameA(NULL, &tmp[0], MAX_PATH));
00135     return tmp;
00136 }
00137 
00138 #else // WIN32
00139 
00140 void Util::setApp(const string& app) {
00141     string::size_type i = app.rfind('/');
00142     if(i != string::npos) {
00143         appPath = app.substr(0, i+1);
00144         appName = app;
00145     }
00146 }
00147 string Util::getAppPath() {
00148     return appPath;
00149 }
00150 string Util::getAppName() {
00151     return appName;
00152 }
00153 #endif // WIN32
00154 
00155 string Util::getLocalIp() {
00156     string tmp;
00157 
00158     char buf[256];
00159     gethostname(buf, 255);
00160     hostent* he = gethostbyname(buf);
00161     if(he == NULL || he->h_addr_list[0] == 0)
00162         return Util::emptyString;
00163     sockaddr_in dest;
00164     int i = 0;
00165 
00166     // We take the first ip as default, but if we can find a better one, use it instead...
00167     memcpy(&(dest.sin_addr), he->h_addr_list[i++], he->h_length);
00168     tmp = inet_ntoa(dest.sin_addr);
00169     if( strncmp(tmp.c_str(), "192", 3) == 0 ||
00170         strncmp(tmp.c_str(), "169", 3) == 0 ||
00171         strncmp(tmp.c_str(), "127", 3) == 0 ||
00172         strncmp(tmp.c_str(), "10", 2) == 0 ) {
00173 
00174         while(he->h_addr_list[i]) {
00175             memcpy(&(dest.sin_addr), he->h_addr_list[i], he->h_length);
00176             string tmp2 = inet_ntoa(dest.sin_addr);
00177             if( strncmp(tmp2.c_str(), "192", 3) != 0 &&
00178                 strncmp(tmp2.c_str(), "169", 3) != 0 &&
00179                 strncmp(tmp2.c_str(), "127", 3) != 0 &&
00180                 strncmp(tmp2.c_str(), "10", 2) != 0) {
00181 
00182                 tmp = tmp2;
00183             }
00184             i++;
00185         }
00186     }
00187     return tmp;
00188 }
00189 
00190 string Util::formatBytes(int64_t aBytes) {
00191     char buf[64];
00192     if(aBytes < 1024) {
00193         sprintf(buf, "%d B", (int)(aBytes&0xffffffff));
00194     } else if(aBytes < 1024*1024) {
00195         sprintf(buf, "%.02f KiB", (double)aBytes/(1024.0));
00196     } else if(aBytes < 1024*1024*1024) {
00197         sprintf(buf, "%.02f MiB", (double)aBytes/(1024.0*1024.0));
00198     } else if(aBytes < (int64_t)1024*1024*1024*1024) {
00199         sprintf(buf, "%.02f GiB", (double)aBytes/(1024.0*1024.0*1024.0));
00200     } else {
00201         sprintf(buf, "%.02f TiB", (double)aBytes/(1024.0*1024.0*1024.0*1024.0));
00202     }
00203 
00204     return buf;
00205 }
00206 
00207 string Util::getShortTimeString() {
00208     char buf[8];
00209     time_t _tt;
00210     time(&_tt);
00211     tm* _tm = localtime(&_tt);
00212     strftime(buf, 8, "%H:%M", _tm);
00213     return buf;
00214 }
00215 
00216 string Util::getTimeString() {
00217     char buf[64];
00218     time_t _tt;
00219     time(&_tt);
00220     tm* _tm = localtime(&_tt);
00221     if(_tm == NULL) {
00222         strcpy(buf, "xx:xx:xx");
00223     } else {
00224         strftime(buf, 64, "%X", _tm);
00225     }
00226     return buf;
00227 }
00228 
00229 string Util::formatTime(const string& msg, time_t t /* = time(NULL) */) {
00230     size_t bufsize = msg.size() + 64;
00231 
00232     char* buf = new char[bufsize];
00233 
00234     while(!strftime(buf, bufsize-1, msg.c_str(), localtime(&t))) {
00235         delete buf;
00236         bufsize+=64;
00237         buf = new char[bufsize];
00238     }
00239 
00240     string result = buf;
00241     delete[] buf;
00242     return result;
00243 }
00244 
00245 string Util::translateError(int aError) {
00246 #ifdef _WIN32
00247     LPVOID lpMsgBuf;
00248     ::FormatMessage(
00249         FORMAT_MESSAGE_ALLOCATE_BUFFER |
00250         FORMAT_MESSAGE_FROM_SYSTEM |
00251         FORMAT_MESSAGE_IGNORE_INSERTS,
00252         NULL,
00253         aError,
00254         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
00255         (LPTSTR) &lpMsgBuf,
00256         0,
00257         NULL
00258     );
00259 
00260 #ifdef _UNICODE
00261     string tmp = Util::toAcp((LPCTSTR)lpMsgBuf);
00262 #else
00263     string tmp = (LPCTSTR)lpMsgBuf;
00264 #endif
00265         // Free the buffer.
00266     LocalFree( lpMsgBuf );
00267 #else // WIN32
00268     string tmp = strerror(aError);
00269 #endif // WIN32
00270     string::size_type i = 0;
00271 
00272     while( (i = tmp.find_first_of("\r\n", i)) != string::npos) {
00273         tmp.erase(i, 1);
00274     }
00275     return tmp;
00276 }
00277 
00278 string Util::getOsVersion() {
00279 #ifdef _WIN32
00280     string os;
00281 
00282     OSVERSIONINFOEX ver;
00283     memset(&ver, 0, sizeof(OSVERSIONINFOEX));
00284     ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
00285 
00286     if(!GetVersionEx((OSVERSIONINFO*)&ver)) {
00287         ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00288         if(!GetVersionEx((OSVERSIONINFO*)&ver)) {
00289             os = "Windows (version unknown)";
00290         }
00291     }
00292 
00293     if(os.empty()) {
00294         if(ver.dwPlatformId != VER_PLATFORM_WIN32_NT) {
00295             os = "Win9x/ME/Junk";
00296         } else if(ver.dwMajorVersion == 4) {
00297             os = "WinNT4";
00298         } else if(ver.dwMajorVersion == 5) {
00299             if(ver.dwMinorVersion == 0) {
00300                 os = "Win2000";
00301             } else if(ver.dwMinorVersion == 1) {
00302                 os = "WinXP";
00303             } else if(ver.dwMinorVersion == 2) {
00304                 os = "Win2003";
00305             } else {
00306                 os = "WinUnknown";
00307             }
00308 
00309             if(ver.wProductType == VER_NT_WORKSTATION)
00310                 os += " Pro";
00311             else if(ver.wProductType == VER_NT_SERVER)
00312                 os += " Server";
00313             else if(ver.wProductType == VER_NT_DOMAIN_CONTROLLER)
00314                 os += " DC";
00315         }
00316 
00317         if(ver.wServicePackMajor > 0) {
00318             os += " SP" + Util::toString(ver.wServicePackMajor);
00319         }
00320     }
00321 
00322     return os;
00323 
00324 #else // WIN32
00325     utsname n;
00326 
00327     if(uname(&n) != 0) {
00328         return "unix (unknown version)";
00329     }
00330 
00331     return string(n.sysname) + " " + string(n.release) + " (" + string(n.machine) + ")";
00332 
00333 #endif // WIN32
00334 }
00335 
00336 /* Below is a high-speed random number generator with much
00337 better granularity than the CRT one in msvc...(no, I didn't
00338 write it...see copyright) */
00339 /* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura.
00340 Any feedback is very welcome. For any question, comments,
00341 see http://www.math.keio.ac.jp/matumoto/emt.html or email
00342 matumoto@math.keio.ac.jp */
00343 /* Period parameters */
00344 #define N 624
00345 #define M 397
00346 #define MATRIX_A 0x9908b0df   /* constant vector a */
00347 #define UPPER_MASK 0x80000000 /* most significant w-r bits */
00348 #define LOWER_MASK 0x7fffffff /* least significant r bits */
00349 
00350 /* Tempering parameters */
00351 #define TEMPERING_MASK_B 0x9d2c5680
00352 #define TEMPERING_MASK_C 0xefc60000
00353 #define TEMPERING_SHIFT_U(y)  (y >> 11)
00354 #define TEMPERING_SHIFT_S(y)  (y << 7)
00355 #define TEMPERING_SHIFT_T(y)  (y << 15)
00356 #define TEMPERING_SHIFT_L(y)  (y >> 18)
00357 
00358 static unsigned long mt[N]; /* the array for the state vector  */
00359 static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
00360 
00361 /* initializing the array with a NONZERO seed */
00362 static void sgenrand(unsigned long seed) {
00363     /* setting initial seeds to mt[N] using         */
00364     /* the generator Line 25 of Table 1 in          */
00365     /* [KNUTH 1981, The Art of Computer Programming */
00366     /*    Vol. 2 (2nd Ed.), pp102]                  */
00367     mt[0]= seed & 0xffffffff;
00368     for (mti=1; mti<N; mti++)
00369         mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
00370 }
00371 
00372 uint32_t Util::rand() {
00373     unsigned long y;
00374     static unsigned long mag01[2]={0x0, MATRIX_A};
00375     /* mag01[x] = x * MATRIX_A  for x=0,1 */
00376 
00377     if (mti >= N) { /* generate N words at one time */
00378         int kk;
00379 
00380         if (mti == N+1)   /* if sgenrand() has not been called, */
00381             sgenrand(4357); /* a default initial seed is used   */
00382 
00383         for (kk=0;kk<N-M;kk++) {
00384             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
00385             mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
00386         }
00387         for (;kk<N-1;kk++) {
00388             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
00389             mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
00390         }
00391         y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
00392         mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
00393 
00394         mti = 0;
00395     }
00396 
00397     y = mt[mti++];
00398     y ^= TEMPERING_SHIFT_U(y);
00399     y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
00400     y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
00401     y ^= TEMPERING_SHIFT_L(y);
00402 
00403     return y;
00404 }
00405 
00406 bool Util::isPrivateIp(std::string const& ip) {
00407     struct in_addr addr;
00408 
00409     addr.s_addr = inet_addr(ip.c_str());
00410 
00411     if (addr.s_addr != INADDR_NONE) {
00412         unsigned long haddr = ntohl(addr.s_addr);
00413         return ((haddr & 0xff000000) == 0x0a000000 || // 10.0.0.0/8
00414                 (haddr & 0xff000000) == 0x7f000000 || // 127.0.0.0/8
00415                 (haddr & 0xfff00000) == 0xac100000 || // 172.16.0.0/12
00416                 (haddr & 0xffff0000) == 0xc0a80000);  // 192.168.0.0/16
00417     }
00418     return false;
00419 }
00420 bool Util::validateCharset(std::string const& field, int p) {
00421     for(string::size_type i = 0; i < field.length(); ++i) {
00422         if((uint8_t) field[i] < p) {
00423             return false;
00424         }
00425     }
00426     return true;
00427 }
00428 
00429  
00430 }
Generated on Sat Nov 27 23:37:53 2010 for adchpp by  doxygen 1.6.3