| 1 | /** \file Utility.cpp |
|---|
| 2 | ** \date 2004-02-13 |
|---|
| 3 | ** \author grymse@alhem.net |
|---|
| 4 | **/ |
|---|
| 5 | /* |
|---|
| 6 | Copyright (C) 2004-2007 Anders Hedstrom |
|---|
| 7 | |
|---|
| 8 | This library is made available under the terms of the GNU GPL. |
|---|
| 9 | |
|---|
| 10 | If you would like to use this library in a closed-source application, |
|---|
| 11 | a separate license agreement is available. For information about |
|---|
| 12 | the closed-source license agreement for the C++ sockets library, |
|---|
| 13 | please visit http://www.alhem.net/Sockets/license.html and/or |
|---|
| 14 | email license@alhem.net. |
|---|
| 15 | |
|---|
| 16 | This program is free software; you can redistribute it and/or |
|---|
| 17 | modify it under the terms of the GNU General Public License |
|---|
| 18 | as published by the Free Software Foundation; either version 2 |
|---|
| 19 | of the License, or (at your option) any later version. |
|---|
| 20 | |
|---|
| 21 | This program is distributed in the hope that it will be useful, |
|---|
| 22 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 24 | GNU General Public License for more details. |
|---|
| 25 | |
|---|
| 26 | You should have received a copy of the GNU General Public License |
|---|
| 27 | along with this program; if not, write to the Free Software |
|---|
| 28 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|---|
| 29 | */ |
|---|
| 30 | #include "Utility.h" |
|---|
| 31 | #include "Parse.h" |
|---|
| 32 | #include "Ipv4Address.h" |
|---|
| 33 | #include "Ipv6Address.h" |
|---|
| 34 | #include "Base64.h" |
|---|
| 35 | #include <vector> |
|---|
| 36 | #ifdef _WIN32 |
|---|
| 37 | #include <time.h> |
|---|
| 38 | #else |
|---|
| 39 | #include <netdb.h> |
|---|
| 40 | #include <pthread.h> |
|---|
| 41 | #endif |
|---|
| 42 | #include <map> |
|---|
| 43 | |
|---|
| 44 | #ifdef SOCKETS_NAMESPACE |
|---|
| 45 | namespace SOCKETS_NAMESPACE { |
|---|
| 46 | #endif |
|---|
| 47 | |
|---|
| 48 | |
|---|
| 49 | // defines for the random number generator |
|---|
| 50 | #define TWIST_IA 397 |
|---|
| 51 | #define TWIST_IB (TWIST_LEN - TWIST_IA) |
|---|
| 52 | #define UMASK 0x80000000 |
|---|
| 53 | #define LMASK 0x7FFFFFFF |
|---|
| 54 | #define MATRIX_A 0x9908B0DF |
|---|
| 55 | #define TWIST(b,i,j) ((b)[i] & UMASK) | ((b)[j] & LMASK) |
|---|
| 56 | #define MAGIC_TWIST(s) (((s) & 1) * MATRIX_A) |
|---|
| 57 | |
|---|
| 58 | |
|---|
| 59 | // statics |
|---|
| 60 | std::string Utility::m_host; |
|---|
| 61 | bool Utility::m_local_resolved = false; |
|---|
| 62 | ipaddr_t Utility::m_ip = 0; |
|---|
| 63 | std::string Utility::m_addr; |
|---|
| 64 | #ifdef ENABLE_IPV6 |
|---|
| 65 | #ifdef IPPROTO_IPV6 |
|---|
| 66 | struct in6_addr Utility::m_local_ip6; |
|---|
| 67 | std::string Utility::m_local_addr6; |
|---|
| 68 | #endif |
|---|
| 69 | #endif |
|---|
| 70 | |
|---|
| 71 | |
|---|
| 72 | std::string Utility::base64(const std::string& str_in) |
|---|
| 73 | { |
|---|
| 74 | std::string str; |
|---|
| 75 | Base64 m_b; |
|---|
| 76 | m_b.encode(str_in, str, false); // , false == do not add cr/lf |
|---|
| 77 | return str; |
|---|
| 78 | } |
|---|
| 79 | |
|---|
| 80 | |
|---|
| 81 | std::string Utility::base64d(const std::string& str_in) |
|---|
| 82 | { |
|---|
| 83 | std::string str; |
|---|
| 84 | Base64 m_b; |
|---|
| 85 | m_b.decode(str_in, str); |
|---|
| 86 | return str; |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | |
|---|
| 90 | std::string Utility::l2string(long l) |
|---|
| 91 | { |
|---|
| 92 | std::string str; |
|---|
| 93 | char tmp[100]; |
|---|
| 94 | sprintf(tmp,"%ld",l); |
|---|
| 95 | str = tmp; |
|---|
| 96 | return str; |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | |
|---|
| 100 | std::string Utility::bigint2string(uint64_t l) |
|---|
| 101 | { |
|---|
| 102 | std::string str; |
|---|
| 103 | uint64_t tmp = l; |
|---|
| 104 | while (tmp) |
|---|
| 105 | { |
|---|
| 106 | uint64_t a = tmp % 10; |
|---|
| 107 | str = (char)(a + 48) + str; |
|---|
| 108 | tmp /= 10; |
|---|
| 109 | } |
|---|
| 110 | if (str.empty()) |
|---|
| 111 | { |
|---|
| 112 | str = "0"; |
|---|
| 113 | } |
|---|
| 114 | return str; |
|---|
| 115 | } |
|---|
| 116 | |
|---|
| 117 | |
|---|
| 118 | uint64_t Utility::atoi64(const std::string& str) |
|---|
| 119 | { |
|---|
| 120 | uint64_t l = 0; |
|---|
| 121 | for (size_t i = 0; i < str.size(); i++) |
|---|
| 122 | { |
|---|
| 123 | l = l * 10 + str[i] - 48; |
|---|
| 124 | } |
|---|
| 125 | return l; |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | |
|---|
| 129 | unsigned int Utility::hex2unsigned(const std::string& str) |
|---|
| 130 | { |
|---|
| 131 | unsigned int r = 0; |
|---|
| 132 | for (size_t i = 0; i < str.size(); i++) |
|---|
| 133 | { |
|---|
| 134 | r = r * 16 + str[i] - 48 - ((str[i] >= 'A') ? 7 : 0) - ((str[i] >= 'a') ? 32 : 0); |
|---|
| 135 | } |
|---|
| 136 | return r; |
|---|
| 137 | } |
|---|
| 138 | |
|---|
| 139 | |
|---|
| 140 | /* |
|---|
| 141 | * Encode string per RFC1738 URL encoding rules |
|---|
| 142 | * tnx rstaveley |
|---|
| 143 | */ |
|---|
| 144 | std::string Utility::rfc1738_encode(const std::string& src) |
|---|
| 145 | { |
|---|
| 146 | static char hex[] = "0123456789ABCDEF"; |
|---|
| 147 | std::string dst; |
|---|
| 148 | for (size_t i = 0; i < src.size(); i++) |
|---|
| 149 | { |
|---|
| 150 | if (isalnum(src[i])) |
|---|
| 151 | { |
|---|
| 152 | dst += src[i]; |
|---|
| 153 | } |
|---|
| 154 | else |
|---|
| 155 | if (src[i] == ' ') |
|---|
| 156 | { |
|---|
| 157 | dst += '+'; |
|---|
| 158 | } |
|---|
| 159 | else |
|---|
| 160 | { |
|---|
| 161 | unsigned char c = static_cast<unsigned char>(src[i]); |
|---|
| 162 | dst += '%'; |
|---|
| 163 | dst += hex[c / 16]; |
|---|
| 164 | dst += hex[c % 16]; |
|---|
| 165 | } |
|---|
| 166 | } |
|---|
| 167 | return dst; |
|---|
| 168 | } // rfc1738_encode |
|---|
| 169 | |
|---|
| 170 | |
|---|
| 171 | /* |
|---|
| 172 | * Decode string per RFC1738 URL encoding rules |
|---|
| 173 | * tnx rstaveley |
|---|
| 174 | */ |
|---|
| 175 | std::string Utility::rfc1738_decode(const std::string& src) |
|---|
| 176 | { |
|---|
| 177 | std::string dst; |
|---|
| 178 | for (size_t i = 0; i < src.size(); i++) |
|---|
| 179 | { |
|---|
| 180 | if (src[i] == '%' && isxdigit(src[i + 1]) && isxdigit(src[i + 2])) |
|---|
| 181 | { |
|---|
| 182 | char c1 = src[++i]; |
|---|
| 183 | char c2 = src[++i]; |
|---|
| 184 | c1 = c1 - 48 - ((c1 >= 'A') ? 7 : 0) - ((c1 >= 'a') ? 32 : 0); |
|---|
| 185 | c2 = c2 - 48 - ((c2 >= 'A') ? 7 : 0) - ((c2 >= 'a') ? 32 : 0); |
|---|
| 186 | dst += (char)(c1 * 16 + c2); |
|---|
| 187 | } |
|---|
| 188 | else |
|---|
| 189 | if (src[i] == '+') |
|---|
| 190 | { |
|---|
| 191 | dst += ' '; |
|---|
| 192 | } |
|---|
| 193 | else |
|---|
| 194 | { |
|---|
| 195 | dst += src[i]; |
|---|
| 196 | } |
|---|
| 197 | } |
|---|
| 198 | return dst; |
|---|
| 199 | } // rfc1738_decode |
|---|
| 200 | |
|---|
| 201 | |
|---|
| 202 | bool Utility::isipv4(const std::string& str) |
|---|
| 203 | { |
|---|
| 204 | int dots = 0; |
|---|
| 205 | // %! ignore :port? |
|---|
| 206 | for (size_t i = 0; i < str.size(); i++) |
|---|
| 207 | { |
|---|
| 208 | if (str[i] == '.') |
|---|
| 209 | dots++; |
|---|
| 210 | else |
|---|
| 211 | if (!isdigit(str[i])) |
|---|
| 212 | return false; |
|---|
| 213 | } |
|---|
| 214 | if (dots != 3) |
|---|
| 215 | return false; |
|---|
| 216 | return true; |
|---|
| 217 | } |
|---|
| 218 | |
|---|
| 219 | |
|---|
| 220 | bool Utility::isipv6(const std::string& str) |
|---|
| 221 | { |
|---|
| 222 | size_t qc = 0; |
|---|
| 223 | size_t qd = 0; |
|---|
| 224 | for (size_t i = 0; i < str.size(); i++) |
|---|
| 225 | { |
|---|
| 226 | qc += (str[i] == ':') ? 1 : 0; |
|---|
| 227 | qd += (str[i] == '.') ? 1 : 0; |
|---|
| 228 | } |
|---|
| 229 | if (qc > 7) |
|---|
| 230 | { |
|---|
| 231 | return false; |
|---|
| 232 | } |
|---|
| 233 | if (qd && qd != 3) |
|---|
| 234 | { |
|---|
| 235 | return false; |
|---|
| 236 | } |
|---|
| 237 | Parse pa(str,":."); |
|---|
| 238 | std::string tmp = pa.getword(); |
|---|
| 239 | while (!tmp.empty()) |
|---|
| 240 | { |
|---|
| 241 | if (tmp.size() > 4) |
|---|
| 242 | { |
|---|
| 243 | return false; |
|---|
| 244 | } |
|---|
| 245 | for (size_t i = 0; i < tmp.size(); i++) |
|---|
| 246 | { |
|---|
| 247 | if (tmp[i] < '0' || (tmp[i] > '9' && tmp[i] < 'A') || |
|---|
| 248 | (tmp[i] > 'F' && tmp[i] < 'a') || tmp[i] > 'f') |
|---|
| 249 | { |
|---|
| 250 | return false; |
|---|
| 251 | } |
|---|
| 252 | } |
|---|
| 253 | // |
|---|
| 254 | tmp = pa.getword(); |
|---|
| 255 | } |
|---|
| 256 | return true; |
|---|
| 257 | } |
|---|
| 258 | |
|---|
| 259 | |
|---|
| 260 | bool Utility::u2ip(const std::string& str, ipaddr_t& l) |
|---|
| 261 | { |
|---|
| 262 | struct sockaddr_in sa; |
|---|
| 263 | bool r = Utility::u2ip(str, sa); |
|---|
| 264 | memcpy(&l, &sa.sin_addr, sizeof(l)); |
|---|
| 265 | return r; |
|---|
| 266 | } |
|---|
| 267 | |
|---|
| 268 | |
|---|
| 269 | #ifdef ENABLE_IPV6 |
|---|
| 270 | #ifdef IPPROTO_IPV6 |
|---|
| 271 | bool Utility::u2ip(const std::string& str, struct in6_addr& l) |
|---|
| 272 | { |
|---|
| 273 | struct sockaddr_in6 sa; |
|---|
| 274 | bool r = Utility::u2ip(str, sa); |
|---|
| 275 | l = sa.sin6_addr; |
|---|
| 276 | return r; |
|---|
| 277 | } |
|---|
| 278 | #endif |
|---|
| 279 | #endif |
|---|
| 280 | |
|---|
| 281 | |
|---|
| 282 | void Utility::l2ip(const ipaddr_t ip, std::string& str) |
|---|
| 283 | { |
|---|
| 284 | struct sockaddr_in sa; |
|---|
| 285 | memset(&sa, 0, sizeof(sa)); |
|---|
| 286 | sa.sin_family = AF_INET; |
|---|
| 287 | memcpy(&sa.sin_addr, &ip, sizeof(sa.sin_addr)); |
|---|
| 288 | Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST); |
|---|
| 289 | } |
|---|
| 290 | |
|---|
| 291 | |
|---|
| 292 | void Utility::l2ip(const in_addr& ip, std::string& str) |
|---|
| 293 | { |
|---|
| 294 | struct sockaddr_in sa; |
|---|
| 295 | memset(&sa, 0, sizeof(sa)); |
|---|
| 296 | sa.sin_family = AF_INET; |
|---|
| 297 | sa.sin_addr = ip; |
|---|
| 298 | Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST); |
|---|
| 299 | } |
|---|
| 300 | |
|---|
| 301 | |
|---|
| 302 | #ifdef ENABLE_IPV6 |
|---|
| 303 | #ifdef IPPROTO_IPV6 |
|---|
| 304 | void Utility::l2ip(const struct in6_addr& ip, std::string& str,bool mixed) |
|---|
| 305 | { |
|---|
| 306 | char slask[100]; // l2ip temporary |
|---|
| 307 | *slask = 0; |
|---|
| 308 | unsigned int prev = 0; |
|---|
| 309 | bool skipped = false; |
|---|
| 310 | bool ok_to_skip = true; |
|---|
| 311 | if (mixed) |
|---|
| 312 | { |
|---|
| 313 | unsigned short x; |
|---|
| 314 | unsigned short addr16[8]; |
|---|
| 315 | memcpy(addr16, &ip, sizeof(addr16)); |
|---|
| 316 | for (size_t i = 0; i < 6; i++) |
|---|
| 317 | { |
|---|
| 318 | x = ntohs(addr16[i]); |
|---|
| 319 | if (*slask && (x || !ok_to_skip || prev)) |
|---|
| 320 | strcat(slask,":"); |
|---|
| 321 | if (x || !ok_to_skip) |
|---|
| 322 | { |
|---|
| 323 | sprintf(slask + strlen(slask),"%x", x); |
|---|
| 324 | if (x && skipped) |
|---|
| 325 | ok_to_skip = false; |
|---|
| 326 | } |
|---|
| 327 | else |
|---|
| 328 | { |
|---|
| 329 | skipped = true; |
|---|
| 330 | } |
|---|
| 331 | prev = x; |
|---|
| 332 | } |
|---|
| 333 | x = ntohs(addr16[6]); |
|---|
| 334 | sprintf(slask + strlen(slask),":%u.%u",x / 256,x & 255); |
|---|
| 335 | x = ntohs(addr16[7]); |
|---|
| 336 | sprintf(slask + strlen(slask),".%u.%u",x / 256,x & 255); |
|---|
| 337 | } |
|---|
| 338 | else |
|---|
| 339 | { |
|---|
| 340 | struct sockaddr_in6 sa; |
|---|
| 341 | memset(&sa, 0, sizeof(sa)); |
|---|
| 342 | sa.sin6_family = AF_INET6; |
|---|
| 343 | sa.sin6_addr = ip; |
|---|
| 344 | Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST); |
|---|
| 345 | return; |
|---|
| 346 | } |
|---|
| 347 | str = slask; |
|---|
| 348 | } |
|---|
| 349 | |
|---|
| 350 | |
|---|
| 351 | int Utility::in6_addr_compare(in6_addr a,in6_addr b) |
|---|
| 352 | { |
|---|
| 353 | for (size_t i = 0; i < 16; i++) |
|---|
| 354 | { |
|---|
| 355 | if (a.s6_addr[i] < b.s6_addr[i]) |
|---|
| 356 | return -1; |
|---|
| 357 | if (a.s6_addr[i] > b.s6_addr[i]) |
|---|
| 358 | return 1; |
|---|
| 359 | } |
|---|
| 360 | return 0; |
|---|
| 361 | } |
|---|
| 362 | #endif |
|---|
| 363 | #endif |
|---|
| 364 | |
|---|
| 365 | |
|---|
| 366 | void Utility::ResolveLocal() |
|---|
| 367 | { |
|---|
| 368 | char h[256]; |
|---|
| 369 | |
|---|
| 370 | // get local hostname and translate into ip-address |
|---|
| 371 | *h = 0; |
|---|
| 372 | gethostname(h,255); |
|---|
| 373 | { |
|---|
| 374 | if (Utility::u2ip(h, m_ip)) |
|---|
| 375 | { |
|---|
| 376 | Utility::l2ip(m_ip, m_addr); |
|---|
| 377 | } |
|---|
| 378 | } |
|---|
| 379 | #ifdef ENABLE_IPV6 |
|---|
| 380 | #ifdef IPPROTO_IPV6 |
|---|
| 381 | memset(&m_local_ip6, 0, sizeof(m_local_ip6)); |
|---|
| 382 | { |
|---|
| 383 | if (Utility::u2ip(h, m_local_ip6)) |
|---|
| 384 | { |
|---|
| 385 | Utility::l2ip(m_local_ip6, m_local_addr6); |
|---|
| 386 | } |
|---|
| 387 | } |
|---|
| 388 | #endif |
|---|
| 389 | #endif |
|---|
| 390 | m_host = h; |
|---|
| 391 | m_local_resolved = true; |
|---|
| 392 | } |
|---|
| 393 | |
|---|
| 394 | |
|---|
| 395 | const std::string& Utility::GetLocalHostname() |
|---|
| 396 | { |
|---|
| 397 | if (!m_local_resolved) |
|---|
| 398 | { |
|---|
| 399 | ResolveLocal(); |
|---|
| 400 | } |
|---|
| 401 | return m_host; |
|---|
| 402 | } |
|---|
| 403 | |
|---|
| 404 | |
|---|
| 405 | ipaddr_t Utility::GetLocalIP() |
|---|
| 406 | { |
|---|
| 407 | if (!m_local_resolved) |
|---|
| 408 | { |
|---|
| 409 | ResolveLocal(); |
|---|
| 410 | } |
|---|
| 411 | return m_ip; |
|---|
| 412 | } |
|---|
| 413 | |
|---|
| 414 | |
|---|
| 415 | const std::string& Utility::GetLocalAddress() |
|---|
| 416 | { |
|---|
| 417 | if (!m_local_resolved) |
|---|
| 418 | { |
|---|
| 419 | ResolveLocal(); |
|---|
| 420 | } |
|---|
| 421 | return m_addr; |
|---|
| 422 | } |
|---|
| 423 | |
|---|
| 424 | |
|---|
| 425 | #ifdef ENABLE_IPV6 |
|---|
| 426 | #ifdef IPPROTO_IPV6 |
|---|
| 427 | const struct in6_addr& Utility::GetLocalIP6() |
|---|
| 428 | { |
|---|
| 429 | if (!m_local_resolved) |
|---|
| 430 | { |
|---|
| 431 | ResolveLocal(); |
|---|
| 432 | } |
|---|
| 433 | return m_local_ip6; |
|---|
| 434 | } |
|---|
| 435 | |
|---|
| 436 | |
|---|
| 437 | const std::string& Utility::GetLocalAddress6() |
|---|
| 438 | { |
|---|
| 439 | if (!m_local_resolved) |
|---|
| 440 | { |
|---|
| 441 | ResolveLocal(); |
|---|
| 442 | } |
|---|
| 443 | return m_local_addr6; |
|---|
| 444 | } |
|---|
| 445 | #endif |
|---|
| 446 | #endif |
|---|
| 447 | |
|---|
| 448 | |
|---|
| 449 | void Utility::SetEnv(const std::string& var,const std::string& value) |
|---|
| 450 | { |
|---|
| 451 | #if (defined(SOLARIS8) || defined(SOLARIS)) |
|---|
| 452 | { |
|---|
| 453 | static std::map<std::string, char *> vmap; |
|---|
| 454 | if (vmap.find(var) != vmap.end()) |
|---|
| 455 | { |
|---|
| 456 | delete[] vmap[var]; |
|---|
| 457 | } |
|---|
| 458 | vmap[var] = new char[var.size() + 1 + value.size() + 1]; |
|---|
| 459 | sprintf(vmap[var], "%s=%s", var.c_str(), value.c_str()); |
|---|
| 460 | putenv( vmap[var] ); |
|---|
| 461 | } |
|---|
| 462 | #elif defined _WIN32 |
|---|
| 463 | { |
|---|
| 464 | std::string slask = var + "=" + value; |
|---|
| 465 | _putenv( (char *)slask.c_str()); |
|---|
| 466 | } |
|---|
| 467 | #else |
|---|
| 468 | setenv(var.c_str(), value.c_str(), 1); |
|---|
| 469 | #endif |
|---|
| 470 | } |
|---|
| 471 | |
|---|
| 472 | |
|---|
| 473 | std::string Utility::Sa2String(struct sockaddr *sa) |
|---|
| 474 | { |
|---|
| 475 | #ifdef ENABLE_IPV6 |
|---|
| 476 | #ifdef IPPROTO_IPV6 |
|---|
| 477 | if (sa -> sa_family == AF_INET6) |
|---|
| 478 | { |
|---|
| 479 | struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; |
|---|
| 480 | std::string tmp; |
|---|
| 481 | Utility::l2ip(sa6 -> sin6_addr, tmp); |
|---|
| 482 | return tmp + ":" + Utility::l2string(ntohs(sa6 -> sin6_port)); |
|---|
| 483 | } |
|---|
| 484 | #endif |
|---|
| 485 | #endif |
|---|
| 486 | if (sa -> sa_family == AF_INET) |
|---|
| 487 | { |
|---|
| 488 | struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; |
|---|
| 489 | ipaddr_t a; |
|---|
| 490 | memcpy(&a, &sa4 -> sin_addr, 4); |
|---|
| 491 | std::string tmp; |
|---|
| 492 | Utility::l2ip(a, tmp); |
|---|
| 493 | return tmp + ":" + Utility::l2string(ntohs(sa4 -> sin_port)); |
|---|
| 494 | } |
|---|
| 495 | return ""; |
|---|
| 496 | } |
|---|
| 497 | |
|---|
| 498 | |
|---|
| 499 | void Utility::GetTime(struct timeval *p) |
|---|
| 500 | { |
|---|
| 501 | #ifdef _WIN32 |
|---|
| 502 | FILETIME ft; // Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC). |
|---|
| 503 | GetSystemTimeAsFileTime(&ft); |
|---|
| 504 | uint64_t tt; |
|---|
| 505 | memcpy(&tt, &ft, sizeof(tt)); |
|---|
| 506 | tt /= 10; // make it usecs |
|---|
| 507 | p->tv_sec = (long)tt / 1000000; |
|---|
| 508 | p->tv_usec = (long)tt % 1000000; |
|---|
| 509 | #else |
|---|
| 510 | gettimeofday(p, NULL); |
|---|
| 511 | #endif |
|---|
| 512 | } |
|---|
| 513 | |
|---|
| 514 | |
|---|
| 515 | std::auto_ptr<SocketAddress> Utility::CreateAddress(struct sockaddr *sa,socklen_t sa_len) |
|---|
| 516 | { |
|---|
| 517 | switch (sa -> sa_family) |
|---|
| 518 | { |
|---|
| 519 | case AF_INET: |
|---|
| 520 | if (sa_len == sizeof(struct sockaddr_in)) |
|---|
| 521 | { |
|---|
| 522 | struct sockaddr_in *p = (struct sockaddr_in *)sa; |
|---|
| 523 | return std::auto_ptr<SocketAddress>(new Ipv4Address(*p)); |
|---|
| 524 | } |
|---|
| 525 | break; |
|---|
| 526 | #ifdef ENABLE_IPV6 |
|---|
| 527 | #ifdef IPPROTO_IPV6 |
|---|
| 528 | case AF_INET6: |
|---|
| 529 | if (sa_len == sizeof(struct sockaddr_in6)) |
|---|
| 530 | { |
|---|
| 531 | struct sockaddr_in6 *p = (struct sockaddr_in6 *)sa; |
|---|
| 532 | return std::auto_ptr<SocketAddress>(new Ipv6Address(*p)); |
|---|
| 533 | } |
|---|
| 534 | break; |
|---|
| 535 | #endif |
|---|
| 536 | #endif |
|---|
| 537 | } |
|---|
| 538 | return std::auto_ptr<SocketAddress>(NULL); |
|---|
| 539 | } |
|---|
| 540 | |
|---|
| 541 | |
|---|
| 542 | bool Utility::u2ip(const std::string& host, struct sockaddr_in& sa, int ai_flags) |
|---|
| 543 | { |
|---|
| 544 | memset(&sa, 0, sizeof(sa)); |
|---|
| 545 | sa.sin_family = AF_INET; |
|---|
| 546 | #ifdef NO_GETADDRINFO |
|---|
| 547 | if ((ai_flags & AI_NUMERICHOST) != 0 || isipv4(host)) |
|---|
| 548 | { |
|---|
| 549 | Parse pa((char *)host.c_str(), "."); |
|---|
| 550 | union { |
|---|
| 551 | struct { |
|---|
| 552 | unsigned char b1; |
|---|
| 553 | unsigned char b2; |
|---|
| 554 | unsigned char b3; |
|---|
| 555 | unsigned char b4; |
|---|
| 556 | } a; |
|---|
| 557 | ipaddr_t l; |
|---|
| 558 | } u; |
|---|
| 559 | u.a.b1 = static_cast<unsigned char>(pa.getvalue()); |
|---|
| 560 | u.a.b2 = static_cast<unsigned char>(pa.getvalue()); |
|---|
| 561 | u.a.b3 = static_cast<unsigned char>(pa.getvalue()); |
|---|
| 562 | u.a.b4 = static_cast<unsigned char>(pa.getvalue()); |
|---|
| 563 | memcpy(&sa.sin_addr, &u.l, sizeof(sa.sin_addr)); |
|---|
| 564 | return true; |
|---|
| 565 | } |
|---|
| 566 | #ifndef LINUX |
|---|
| 567 | struct hostent *he = gethostbyname( host.c_str() ); |
|---|
| 568 | if (!he) |
|---|
| 569 | { |
|---|
| 570 | return false; |
|---|
| 571 | } |
|---|
| 572 | memcpy(&sa.sin_addr, he -> h_addr, sizeof(sa.sin_addr)); |
|---|
| 573 | #else |
|---|
| 574 | struct hostent he; |
|---|
| 575 | struct hostent *result = NULL; |
|---|
| 576 | int myerrno = 0; |
|---|
| 577 | char buf[2000]; |
|---|
| 578 | int n = gethostbyname_r(host.c_str(), &he, buf, sizeof(buf), &result, &myerrno); |
|---|
| 579 | if (n || !result) |
|---|
| 580 | { |
|---|
| 581 | return false; |
|---|
| 582 | } |
|---|
| 583 | if (he.h_addr_list && he.h_addr_list[0]) |
|---|
| 584 | memcpy(&sa.sin_addr, he.h_addr, 4); |
|---|
| 585 | else |
|---|
| 586 | return false; |
|---|
| 587 | #endif |
|---|
| 588 | return true; |
|---|
| 589 | #else |
|---|
| 590 | struct addrinfo hints; |
|---|
| 591 | memset(&hints, 0, sizeof(hints)); |
|---|
| 592 | // AI_NUMERICHOST |
|---|
| 593 | // AI_CANONNAME |
|---|
| 594 | // AI_PASSIVE - server |
|---|
| 595 | // AI_ADDRCONFIG |
|---|
| 596 | // AI_V4MAPPED |
|---|
| 597 | // AI_ALL |
|---|
| 598 | // AI_NUMERICSERV |
|---|
| 599 | hints.ai_flags = ai_flags; |
|---|
| 600 | hints.ai_family = AF_INET; |
|---|
| 601 | hints.ai_socktype = 0; |
|---|
| 602 | hints.ai_protocol = 0; |
|---|
| 603 | struct addrinfo *res; |
|---|
| 604 | if (Utility::isipv4(host)) |
|---|
| 605 | hints.ai_flags |= AI_NUMERICHOST; |
|---|
| 606 | int n = getaddrinfo(host.c_str(), NULL, &hints, &res); |
|---|
| 607 | if (!n) |
|---|
| 608 | { |
|---|
| 609 | std::vector<struct addrinfo *> vec; |
|---|
| 610 | struct addrinfo *ai = res; |
|---|
| 611 | while (ai) |
|---|
| 612 | { |
|---|
| 613 | if (ai -> ai_addrlen == sizeof(sa)) |
|---|
| 614 | vec.push_back( ai ); |
|---|
| 615 | ai = ai -> ai_next; |
|---|
| 616 | } |
|---|
| 617 | if (vec.empty()) |
|---|
| 618 | return false; |
|---|
| 619 | ai = vec[Utility::Rnd() % vec.size()]; |
|---|
| 620 | { |
|---|
| 621 | memcpy(&sa, ai -> ai_addr, ai -> ai_addrlen); |
|---|
| 622 | } |
|---|
| 623 | freeaddrinfo(res); |
|---|
| 624 | return true; |
|---|
| 625 | } |
|---|
| 626 | std::string error = "Error: "; |
|---|
| 627 | #ifndef __CYGWIN__ |
|---|
| 628 | error += gai_strerror(n); |
|---|
| 629 | #endif |
|---|
| 630 | return false; |
|---|
| 631 | #endif // NO_GETADDRINFO |
|---|
| 632 | } |
|---|
| 633 | |
|---|
| 634 | |
|---|
| 635 | #ifdef ENABLE_IPV6 |
|---|
| 636 | #ifdef IPPROTO_IPV6 |
|---|
| 637 | bool Utility::u2ip(const std::string& host, struct sockaddr_in6& sa, int ai_flags) |
|---|
| 638 | { |
|---|
| 639 | memset(&sa, 0, sizeof(sa)); |
|---|
| 640 | sa.sin6_family = AF_INET6; |
|---|
| 641 | #ifdef NO_GETADDRINFO |
|---|
| 642 | if ((ai_flags & AI_NUMERICHOST) != 0 || isipv6(host)) |
|---|
| 643 | { |
|---|
| 644 | std::list<std::string> vec; |
|---|
| 645 | size_t x = 0; |
|---|
| 646 | for (size_t i = 0; i <= host.size(); i++) |
|---|
| 647 | { |
|---|
| 648 | if (i == host.size() || host[i] == ':') |
|---|
| 649 | { |
|---|
| 650 | std::string s = host.substr(x, i - x); |
|---|
| 651 | // |
|---|
| 652 | if (strstr(s.c_str(),".")) // x.x.x.x |
|---|
| 653 | { |
|---|
| 654 | Parse pa(s,"."); |
|---|
| 655 | char slask[100]; // u2ip temporary hex2string conversion |
|---|
| 656 | unsigned long b0 = static_cast<unsigned long>(pa.getvalue()); |
|---|
| 657 | unsigned long b1 = static_cast<unsigned long>(pa.getvalue()); |
|---|
| 658 | unsigned long b2 = static_cast<unsigned long>(pa.getvalue()); |
|---|
| 659 | unsigned long b3 = static_cast<unsigned long>(pa.getvalue()); |
|---|
| 660 | sprintf(slask,"%lx",b0 * 256 + b1); |
|---|
| 661 | vec.push_back(slask); |
|---|
| 662 | sprintf(slask,"%lx",b2 * 256 + b3); |
|---|
| 663 | vec.push_back(slask); |
|---|
| 664 | } |
|---|
| 665 | else |
|---|
| 666 | { |
|---|
| 667 | vec.push_back(s); |
|---|
| 668 | } |
|---|
| 669 | // |
|---|
| 670 | x = i + 1; |
|---|
| 671 | } |
|---|
| 672 | } |
|---|
| 673 | size_t sz = vec.size(); // number of byte pairs |
|---|
| 674 | size_t i = 0; // index in in6_addr.in6_u.u6_addr16[] ( 0 .. 7 ) |
|---|
| 675 | unsigned short addr16[8]; |
|---|
| 676 | for (std::list<std::string>::iterator it = vec.begin(); it != vec.end(); it++) |
|---|
| 677 | { |
|---|
| 678 | std::string bytepair = *it; |
|---|
| 679 | if (!bytepair.empty()) |
|---|
| 680 | { |
|---|
| 681 | addr16[i++] = htons(Utility::hex2unsigned(bytepair)); |
|---|
| 682 | } |
|---|
| 683 | else |
|---|
| 684 | { |
|---|
| 685 | addr16[i++] = 0; |
|---|
| 686 | while (sz++ < 8) |
|---|
| 687 | { |
|---|
| 688 | addr16[i++] = 0; |
|---|
| 689 | } |
|---|
| 690 | } |
|---|
| 691 | } |
|---|
| 692 | memcpy(&sa.sin6_addr, addr16, sizeof(addr16)); |
|---|
| 693 | return true; |
|---|
| 694 | } |
|---|
| 695 | #ifdef SOLARIS |
|---|
| 696 | int errnum = 0; |
|---|
| 697 | struct hostent *he = getipnodebyname( host.c_str(), AF_INET6, 0, &errnum ); |
|---|
| 698 | #else |
|---|
| 699 | struct hostent *he = gethostbyname2( host.c_str(), AF_INET6 ); |
|---|
| 700 | #endif |
|---|
| 701 | if (!he) |
|---|
| 702 | { |
|---|
| 703 | return false; |
|---|
| 704 | } |
|---|
| 705 | memcpy(&sa.sin6_addr,he -> h_addr_list[0],he -> h_length); |
|---|
| 706 | #ifdef SOLARIS |
|---|
| 707 | free(he); |
|---|
| 708 | #endif |
|---|
| 709 | return true; |
|---|
| 710 | #else |
|---|
| 711 | struct addrinfo hints; |
|---|
| 712 | memset(&hints, 0, sizeof(hints)); |
|---|
| 713 | hints.ai_flags = ai_flags; |
|---|
| 714 | hints.ai_family = AF_INET6; |
|---|
| 715 | hints.ai_socktype = 0; |
|---|
| 716 | hints.ai_protocol = 0; |
|---|
| 717 | struct addrinfo *res; |
|---|
| 718 | if (Utility::isipv6(host)) |
|---|
| 719 | hints.ai_flags |= AI_NUMERICHOST; |
|---|
| 720 | int n = getaddrinfo(host.c_str(), NULL, &hints, &res); |
|---|
| 721 | if (!n) |
|---|
| 722 | { |
|---|
| 723 | std::vector<struct addrinfo *> vec; |
|---|
| 724 | struct addrinfo *ai = res; |
|---|
| 725 | while (ai) |
|---|
| 726 | { |
|---|
| 727 | if (ai -> ai_addrlen == sizeof(sa)) |
|---|
| 728 | vec.push_back( ai ); |
|---|
| 729 | ai = ai -> ai_next; |
|---|
| 730 | } |
|---|
| 731 | if (vec.empty()) |
|---|
| 732 | return false; |
|---|
| 733 | ai = vec[Utility::Rnd() % vec.size()]; |
|---|
| 734 | { |
|---|
| 735 | memcpy(&sa, ai -> ai_addr, ai -> ai_addrlen); |
|---|
| 736 | } |
|---|
| 737 | freeaddrinfo(res); |
|---|
| 738 | return true; |
|---|
| 739 | } |
|---|
| 740 | std::string error = "Error: "; |
|---|
| 741 | #ifndef __CYGWIN__ |
|---|
| 742 | error += gai_strerror(n); |
|---|
| 743 | #endif |
|---|
| 744 | return false; |
|---|
| 745 | #endif // NO_GETADDRINFO |
|---|
| 746 | } |
|---|
| 747 | #endif // IPPROTO_IPV6 |
|---|
| 748 | #endif // ENABLE_IPV6 |
|---|
| 749 | |
|---|
| 750 | |
|---|
| 751 | bool Utility::reverse(struct sockaddr *sa, socklen_t sa_len, std::string& hostname, int flags) |
|---|
| 752 | { |
|---|
| 753 | std::string service; |
|---|
| 754 | return Utility::reverse(sa, sa_len, hostname, service, flags); |
|---|
| 755 | } |
|---|
| 756 | |
|---|
| 757 | |
|---|
| 758 | bool Utility::reverse(struct sockaddr *sa, socklen_t sa_len, std::string& hostname, std::string& service, int flags) |
|---|
| 759 | { |
|---|
| 760 | hostname = ""; |
|---|
| 761 | service = ""; |
|---|
| 762 | #ifdef NO_GETADDRINFO |
|---|
| 763 | switch (sa -> sa_family) |
|---|
| 764 | { |
|---|
| 765 | case AF_INET: |
|---|
| 766 | if (flags & NI_NUMERICHOST) |
|---|
| 767 | { |
|---|
| 768 | union { |
|---|
| 769 | struct { |
|---|
| 770 | unsigned char b1; |
|---|
| 771 | unsigned char b2; |
|---|
| 772 | unsigned char b3; |
|---|
| 773 | unsigned char b4; |
|---|
| 774 | } a; |
|---|
| 775 | ipaddr_t l; |
|---|
| 776 | } u; |
|---|
| 777 | struct sockaddr_in *sa_in = (struct sockaddr_in *)sa; |
|---|
| 778 | memcpy(&u.l, &sa_in -> sin_addr, sizeof(u.l)); |
|---|
| 779 | char tmp[100]; |
|---|
| 780 | sprintf(tmp, "%u.%u.%u.%u", u.a.b1, u.a.b2, u.a.b3, u.a.b4); |
|---|
| 781 | hostname = tmp; |
|---|
| 782 | return true; |
|---|
| 783 | } |
|---|
| 784 | else |
|---|
| 785 | { |
|---|
| 786 | struct sockaddr_in *sa_in = (struct sockaddr_in *)sa; |
|---|
| 787 | struct hostent *h = gethostbyaddr( (const char *)&sa_in -> sin_addr, sizeof(sa_in -> sin_addr), AF_INET); |
|---|
| 788 | if (h) |
|---|
| 789 | { |
|---|
| 790 | hostname = h -> h_name; |
|---|
| 791 | return true; |
|---|
| 792 | } |
|---|
| 793 | } |
|---|
| 794 | break; |
|---|
| 795 | #ifdef ENABLE_IPV6 |
|---|
| 796 | case AF_INET6: |
|---|
| 797 | if (flags & NI_NUMERICHOST) |
|---|
| 798 | { |
|---|
| 799 | char slask[100]; // l2ip temporary |
|---|
| 800 | *slask = 0; |
|---|
| 801 | unsigned int prev = 0; |
|---|
| 802 | bool skipped = false; |
|---|
| 803 | bool ok_to_skip = true; |
|---|
| 804 | { |
|---|
| 805 | unsigned short addr16[8]; |
|---|
| 806 | struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa; |
|---|
| 807 | memcpy(addr16, &sa_in6 -> sin6_addr, sizeof(addr16)); |
|---|
| 808 | for (size_t i = 0; i < 8; i++) |
|---|
| 809 | { |
|---|
| 810 | unsigned short x = ntohs(addr16[i]); |
|---|
| 811 | if (*slask && (x || !ok_to_skip || prev)) |
|---|
| 812 | strcat(slask,":"); |
|---|
| 813 | if (x || !ok_to_skip) |
|---|
| 814 | { |
|---|
| 815 | sprintf(slask + strlen(slask),"%x", x); |
|---|
| 816 | if (x && skipped) |
|---|
| 817 | ok_to_skip = false; |
|---|
| 818 | } |
|---|
| 819 | else |
|---|
| 820 | { |
|---|
| 821 | skipped = true; |
|---|
| 822 | } |
|---|
| 823 | prev = x; |
|---|
| 824 | } |
|---|
| 825 | } |
|---|
| 826 | if (!*slask) |
|---|
| 827 | strcpy(slask, "::"); |
|---|
| 828 | hostname = slask; |
|---|
| 829 | return true; |
|---|
| 830 | } |
|---|
| 831 | else |
|---|
| 832 | { |
|---|
| 833 | // %! TODO: ipv6 reverse lookup |
|---|
| 834 | struct sockaddr_in6 *sa_in = (struct sockaddr_in6 *)sa; |
|---|
| 835 | struct hostent *h = gethostbyaddr( (const char *)&sa_in -> sin6_addr, sizeof(sa_in -> sin6_addr), AF_INET6); |
|---|
| 836 | if (h) |
|---|
| 837 | { |
|---|
| 838 | hostname = h -> h_name; |
|---|
| 839 | return true; |
|---|
| 840 | } |
|---|
| 841 | } |
|---|
| 842 | break; |
|---|
| 843 | #endif |
|---|
| 844 | } |
|---|
| 845 | return false; |
|---|
| 846 | #else |
|---|
| 847 | char host[NI_MAXHOST]; |
|---|
| 848 | char serv[NI_MAXSERV]; |
|---|
| 849 | // NI_NOFQDN |
|---|
| 850 | // NI_NUMERICHOST |
|---|
| 851 | // NI_NAMEREQD |
|---|
| 852 | // NI_NUMERICSERV |
|---|
| 853 | // NI_DGRAM |
|---|
| 854 | int n = getnameinfo(sa, sa_len, host, sizeof(host), serv, sizeof(serv), flags); |
|---|
| 855 | if (n) |
|---|
| 856 | { |
|---|
| 857 | // EAI_AGAIN |
|---|
| 858 | // EAI_BADFLAGS |
|---|
| 859 | // EAI_FAIL |
|---|
| 860 | // EAI_FAMILY |
|---|
| 861 | // EAI_MEMORY |
|---|
| 862 | // EAI_NONAME |
|---|
| 863 | // EAI_OVERFLOW |
|---|
| 864 | // EAI_SYSTEM |
|---|
| 865 | return false; |
|---|
| 866 | } |
|---|
| 867 | hostname = host; |
|---|
| 868 | service = serv; |
|---|
| 869 | return true; |
|---|
| 870 | #endif // NO_GETADDRINFO |
|---|
| 871 | } |
|---|
| 872 | |
|---|
| 873 | |
|---|
| 874 | bool Utility::u2service(const std::string& name, int& service, int ai_flags) |
|---|
| 875 | { |
|---|
| 876 | #ifdef NO_GETADDRINFO |
|---|
| 877 | // %! |
|---|
| 878 | return false; |
|---|
| 879 | #else |
|---|
| 880 | struct addrinfo hints; |
|---|
| 881 | service = 0; |
|---|
| 882 | memset(&hints, 0, sizeof(hints)); |
|---|
| 883 | // AI_NUMERICHOST |
|---|
| 884 | // AI_CANONNAME |
|---|
| 885 | // AI_PASSIVE - server |
|---|
| 886 | // AI_ADDRCONFIG |
|---|
| 887 | // AI_V4MAPPED |
|---|
| 888 | // AI_ALL |
|---|
| 889 | // AI_NUMERICSERV |
|---|
| 890 | hints.ai_flags = ai_flags; |
|---|
| 891 | hints.ai_family = AF_UNSPEC; |
|---|
| 892 | hints.ai_socktype = 0; |
|---|
| 893 | hints.ai_protocol = 0; |
|---|
| 894 | struct addrinfo *res; |
|---|
| 895 | int n = getaddrinfo(NULL, name.c_str(), &hints, &res); |
|---|
| 896 | if (!n) |
|---|
| 897 | { |
|---|
| 898 | service = res -> ai_protocol; |
|---|
| 899 | freeaddrinfo(res); |
|---|
| 900 | return true; |
|---|
| 901 | } |
|---|
| 902 | return false; |
|---|
| 903 | #endif // NO_GETADDRINFO |
|---|
| 904 | } |
|---|
| 905 | |
|---|
| 906 | |
|---|
| 907 | unsigned long Utility::ThreadID() |
|---|
| 908 | { |
|---|
| 909 | #ifdef _WIN32 |
|---|
| 910 | return GetCurrentThreadId(); |
|---|
| 911 | #else |
|---|
| 912 | return (unsigned long)pthread_self(); |
|---|
| 913 | #endif |
|---|
| 914 | } |
|---|
| 915 | |
|---|
| 916 | |
|---|
| 917 | std::string Utility::ToLower(const std::string& str) |
|---|
| 918 | { |
|---|
| 919 | std::string r; |
|---|
| 920 | for (size_t i = 0; i < str.size(); i++) |
|---|
| 921 | { |
|---|
| 922 | if (str[i] >= 'A' && str[i] <= 'Z') |
|---|
| 923 | r += str[i] | 32; |
|---|
| 924 | else |
|---|
| 925 | r += str[i]; |
|---|
| 926 | } |
|---|
| 927 | return r; |
|---|
| 928 | } |
|---|
| 929 | |
|---|
| 930 | |
|---|
| 931 | std::string Utility::ToUpper(const std::string& str) |
|---|
| 932 | { |
|---|
| 933 | std::string r; |
|---|
| 934 | for (size_t i = 0; i < str.size(); i++) |
|---|
| 935 | { |
|---|
| 936 | if (str[i] >= 'a' && str[i] <= 'z') |
|---|
| 937 | r += (char)(str[i] - 32); |
|---|
| 938 | else |
|---|
| 939 | r += str[i]; |
|---|
| 940 | } |
|---|
| 941 | return r; |
|---|
| 942 | } |
|---|
| 943 | |
|---|
| 944 | |
|---|
| 945 | std::string Utility::ToString(double d) |
|---|
| 946 | { |
|---|
| 947 | char tmp[100]; |
|---|
| 948 | sprintf(tmp, "%f", d); |
|---|
| 949 | return tmp; |
|---|
| 950 | } |
|---|
| 951 | |
|---|
| 952 | |
|---|
| 953 | unsigned long Utility::Rnd() |
|---|
| 954 | { |
|---|
| 955 | static Utility::Rng generator( (unsigned long)time(NULL) ); |
|---|
| 956 | return generator.Get(); |
|---|
| 957 | } |
|---|
| 958 | |
|---|
| 959 | |
|---|
| 960 | Utility::Rng::Rng(unsigned long seed) : m_value( 0 ) |
|---|
| 961 | { |
|---|
| 962 | m_tmp[0]= seed & 0xffffffffUL; |
|---|
| 963 | for (int i = 1; i < TWIST_LEN; i++) |
|---|
| 964 | { |
|---|
| 965 | m_tmp[i] = (1812433253UL * (m_tmp[i - 1] ^ (m_tmp[i - 1] >> 30)) + i); |
|---|
| 966 | } |
|---|
| 967 | } |
|---|
| 968 | |
|---|
| 969 | |
|---|
| 970 | unsigned long Utility::Rng::Get() |
|---|
| 971 | { |
|---|
| 972 | unsigned long val = m_tmp[m_value]; |
|---|
| 973 | ++m_value; |
|---|
| 974 | if (m_value == TWIST_LEN) |
|---|
| 975 | { |
|---|
| 976 | for (int i = 0; i < TWIST_IB; ++i) |
|---|
| 977 | { |
|---|
| 978 | unsigned long s = TWIST(m_tmp, i, i + 1); |
|---|
| 979 | m_tmp[i] = m_tmp[i + TWIST_IA] ^ (s >> 1) ^ MAGIC_TWIST(s); |
|---|
| 980 | } |
|---|
| 981 | { |
|---|
| 982 | for (int i = 0; i < TWIST_LEN - 1; ++i) |
|---|
| 983 | { |
|---|
| 984 | unsigned long s = TWIST(m_tmp, i, i + 1); |
|---|
| 985 | m_tmp[i] = m_tmp[i - TWIST_IB] ^ (s >> 1) ^ MAGIC_TWIST(s); |
|---|
| 986 | } |
|---|
| 987 | } |
|---|
| 988 | unsigned long s = TWIST(m_tmp, TWIST_LEN - 1, 0); |
|---|
| 989 | m_tmp[TWIST_LEN - 1] = m_tmp[TWIST_IA - 1] ^ (s >> 1) ^ MAGIC_TWIST(s); |
|---|
| 990 | |
|---|
| 991 | m_value = 0; |
|---|
| 992 | } |
|---|
| 993 | return val; |
|---|
| 994 | } |
|---|
| 995 | |
|---|
| 996 | #ifdef SOCKETS_NAMESPACE |
|---|
| 997 | } |
|---|
| 998 | #endif |
|---|
| 999 | |
|---|