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 | |
---|