00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
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
00097 aFile = url.substr(j);
00098 }
00099
00100 if( (k=url.find(':', i)) != string::npos) {
00101
00102 if(k < j)
00103 aPort = (short)Util::toInt(url.substr(k+1, j-k-1));
00104 } else {
00105 k = j;
00106 }
00107
00108
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
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 ) {
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),
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
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
00337
00338
00339
00340
00341
00342
00343
00344 #define N 624
00345 #define M 397
00346 #define MATRIX_A 0x9908b0df
00347 #define UPPER_MASK 0x80000000
00348 #define LOWER_MASK 0x7fffffff
00349
00350
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];
00359 static int mti=N+1;
00360
00361
00362 static void sgenrand(unsigned long seed) {
00363
00364
00365
00366
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
00376
00377 if (mti >= N) {
00378 int kk;
00379
00380 if (mti == N+1)
00381 sgenrand(4357);
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 ||
00414 (haddr & 0xff000000) == 0x7f000000 ||
00415 (haddr & 0xfff00000) == 0xac100000 ||
00416 (haddr & 0xffff0000) == 0xc0a80000);
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 }