root/trunk/dep/src/sockets/Utility.cpp @ 2

Revision 2, 19.7 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/** \file Utility.cpp
2 **     \date  2004-02-13
3 **     \author grymse@alhem.net
4**/
5/*
6Copyright (C) 2004-2007  Anders Hedstrom
7
8This library is made available under the terms of the GNU GPL.
9
10If you would like to use this library in a closed-source application,
11a separate license agreement is available. For information about
12the closed-source license agreement for the C++ sockets library,
13please visit http://www.alhem.net/Sockets/license.html and/or
14email license@alhem.net.
15
16This program is free software; you can redistribute it and/or
17modify it under the terms of the GNU General Public License
18as published by the Free Software Foundation; either version 2
19of the License, or (at your option) any later version.
20
21This program is distributed in the hope that it will be useful,
22but WITHOUT ANY WARRANTY; without even the implied warranty of
23MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24GNU General Public License for more details.
25
26You should have received a copy of the GNU General Public License
27along with this program; if not, write to the Free Software
28Foundation, 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
45namespace 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
60std::string Utility::m_host;
61bool Utility::m_local_resolved = false;
62ipaddr_t Utility::m_ip = 0;
63std::string Utility::m_addr;
64#ifdef ENABLE_IPV6
65#ifdef IPPROTO_IPV6
66struct in6_addr Utility::m_local_ip6;
67std::string Utility::m_local_addr6;
68#endif
69#endif
70
71
72std::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
81std::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
90std::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
100std::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
118uint64_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
129unsigned 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*/
144std::string Utility::rfc1738_encode(const std::string& src)
145{
146static  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*/
175std::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
202bool 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
220bool 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
260bool 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
271bool 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
282void 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
292void 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
304void 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
351int 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
366void 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
395const std::string& Utility::GetLocalHostname()
396{
397        if (!m_local_resolved)
398        {
399                ResolveLocal();
400        }
401        return m_host;
402}
403
404
405ipaddr_t Utility::GetLocalIP()
406{
407        if (!m_local_resolved)
408        {
409                ResolveLocal();
410        }
411        return m_ip;
412}
413
414
415const 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
427const struct in6_addr& Utility::GetLocalIP6()
428{
429        if (!m_local_resolved)
430        {
431                ResolveLocal();
432        }
433        return m_local_ip6;
434}
435
436
437const 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
449void 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
473std::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
499void 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
515std::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
542bool 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
637bool 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
751bool 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
758bool 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
874bool 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
907unsigned long Utility::ThreadID()
908{
909#ifdef _WIN32
910        return GetCurrentThreadId();
911#else
912        return (unsigned long)pthread_self();
913#endif
914}
915
916
917std::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
931std::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
945std::string Utility::ToString(double d)
946{
947        char tmp[100];
948        sprintf(tmp, "%f", d);
949        return tmp;
950}
951
952
953unsigned long Utility::Rnd()
954{
955static  Utility::Rng generator( (unsigned long)time(NULL) );
956        return generator.Get();
957}
958
959
960Utility::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
970unsigned 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
Note: See TracBrowser for help on using the browser.