Logo
~Sockets~
~Examples~
~Contact~


Utility.cpp

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 2004-2007  Anders Hedstrom
00007 
00008 This library is made available under the terms of the GNU GPL.
00009 
00010 If you would like to use this library in a closed-source application,
00011 a separate license agreement is available. For information about 
00012 the closed-source license agreement for the C++ sockets library,
00013 please visit http://www.alhem.net/Sockets/license.html and/or
00014 email license@alhem.net.
00015 
00016 This program is free software; you can redistribute it and/or
00017 modify it under the terms of the GNU General Public License
00018 as published by the Free Software Foundation; either version 2
00019 of the License, or (at your option) any later version.
00020 
00021 This program is distributed in the hope that it will be useful,
00022 but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 GNU General Public License for more details.
00025 
00026 You should have received a copy of the GNU General Public License
00027 along with this program; if not, write to the Free Software
00028 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00029 */
00030 #include "Utility.h"
00031 #include "Parse.h"
00032 #include "Ipv4Address.h"
00033 #include "Ipv6Address.h"
00034 #include "RandomNumber.h"
00035 #include <vector>
00036 #ifdef _WIN32
00037 #include <time.h>
00038 #else
00039 #include <netdb.h>
00040 #include <pthread.h>
00041 #endif
00042 #include <map>
00043 
00044 #ifdef SOCKETS_NAMESPACE
00045 namespace SOCKETS_NAMESPACE {
00046 #endif
00047 
00048 
00049 // statics
00050 std::string Utility::m_host;
00051 bool Utility::m_local_resolved = false;
00052 ipaddr_t Utility::m_ip = 0;
00053 std::string Utility::m_addr;
00054 #ifdef ENABLE_IPV6
00055 #ifdef IPPROTO_IPV6
00056 struct in6_addr Utility::m_local_ip6;
00057 std::string Utility::m_local_addr6;
00058 #endif
00059 #endif
00060 
00061 
00062 std::string Utility::base64(const std::string& str_in)
00063 {
00064         std::string str;
00065         Base64 m_b;
00066         m_b.encode(str_in, str, false); // , false == do not add cr/lf
00067         return str;
00068 }
00069 
00070 
00071 std::string Utility::base64d(const std::string& str_in)
00072 {
00073         std::string str;
00074         Base64 m_b;
00075         m_b.decode(str_in, str);
00076         return str;
00077 }
00078 
00079 
00080 std::string Utility::l2string(long l)
00081 {
00082         std::string str;
00083         char tmp[100];
00084         sprintf(tmp,"%ld",l);
00085         str = tmp;
00086         return str;
00087 }
00088 
00089 
00090 std::string Utility::bigint2string(uint64_t l)
00091 {
00092         std::string str;
00093         uint64_t tmp = l;
00094         while (tmp)
00095         {
00096                 uint64_t a = tmp % 10;
00097                 str = (char)(a + 48) + str;
00098                 tmp /= 10;
00099         }
00100         if (!str.size())
00101         {
00102                 str = "0";
00103         }
00104         return str;
00105 }
00106 
00107 
00108 uint64_t Utility::atoi64(const std::string& str) 
00109 {
00110         uint64_t l = 0;
00111         for (size_t i = 0; i < str.size(); i++)
00112         {
00113                 l = l * 10 + str[i] - 48;
00114         }
00115         return l;
00116 }
00117 
00118 
00119 unsigned int Utility::hex2unsigned(const std::string& str)
00120 {
00121         unsigned int r = 0;
00122         for (size_t i = 0; i < str.size(); i++)
00123         {
00124                 r = r * 16 + str[i] - 48 - ((str[i] >= 'A') ? 7 : 0) - ((str[i] >= 'a') ? 32 : 0);
00125         }
00126         return r;
00127 }
00128 
00129 
00130 /*
00131 * Encode string per RFC1738 URL encoding rules
00132 * tnx rstaveley
00133 */
00134 std::string Utility::rfc1738_encode(const std::string& src)
00135 {
00136 static  char hex[] = "0123456789ABCDEF";
00137         std::string dst;
00138         for (size_t i = 0; i < src.size(); i++)
00139         {
00140                 if (isalnum(src[i]))
00141                 {
00142                         dst += src[i];
00143                 }
00144                 else
00145                 if (src[i] == ' ')
00146                 {
00147                         dst += '+';
00148                 }
00149                 else
00150                 {
00151                         unsigned char c = static_cast<unsigned char>(src[i]);
00152                         dst += '%';
00153                         dst += hex[c / 16];
00154                         dst += hex[c % 16];
00155                 }
00156         }
00157         return dst;
00158 } // rfc1738_encode
00159 
00160 
00161 /*
00162 * Decode string per RFC1738 URL encoding rules
00163 * tnx rstaveley
00164 */
00165 std::string Utility::rfc1738_decode(const std::string& src)
00166 {
00167         std::string dst;
00168         for (size_t i = 0; i < src.size(); i++)
00169         {
00170                 if (src[i] == '%' && isxdigit(src[i + 1]) && isxdigit(src[i + 2]))
00171                 {
00172                         char c1 = src[++i];
00173                         char c2 = src[++i];
00174                         c1 = c1 - 48 - ((c1 >= 'A') ? 7 : 0) - ((c1 >= 'a') ? 32 : 0);
00175                         c2 = c2 - 48 - ((c2 >= 'A') ? 7 : 0) - ((c2 >= 'a') ? 32 : 0);
00176                         dst += (char)(c1 * 16 + c2);
00177                 }
00178                 else
00179                 if (src[i] == '+')
00180                 {
00181                         dst += ' ';
00182                 }
00183                 else
00184                 {
00185                         dst += src[i];
00186                 }
00187         }
00188         return dst;
00189 } // rfc1738_decode
00190 
00191 
00192 bool Utility::isipv4(const std::string& str)
00193 {
00194         int dots = 0;
00195         // %! ignore :port?
00196         for (size_t i = 0; i < str.size(); i++)
00197         {
00198                 if (str[i] == '.')
00199                         dots++;
00200                 else
00201                 if (!isdigit(str[i]))
00202                         return false;
00203         }
00204         if (dots != 3)
00205                 return false;
00206         return true;
00207 }
00208 
00209 
00210 bool Utility::isipv6(const std::string& str)
00211 {
00212         size_t qc = 0;
00213         size_t qd = 0;
00214         for (size_t i = 0; i < str.size(); i++)
00215         {
00216                 qc += (str[i] == ':') ? 1 : 0;
00217                 qd += (str[i] == '.') ? 1 : 0;
00218         }
00219         if (qc > 7)
00220         {
00221                 return false;
00222         }
00223         if (qd && qd != 3)
00224         {
00225                 return false;
00226         }
00227         Parse pa(str,":.");
00228         std::string tmp = pa.getword();
00229         while (tmp.size())
00230         {
00231                 if (tmp.size() > 4)
00232                 {
00233                         return false;
00234                 }
00235                 for (size_t i = 0; i < tmp.size(); i++)
00236                 {
00237                         if (tmp[i] < '0' || (tmp[i] > '9' && tmp[i] < 'A') ||
00238                                 (tmp[i] > 'F' && tmp[i] < 'a') || tmp[i] > 'f')
00239                         {
00240                                 return false;
00241                         }
00242                 }
00243                 //
00244                 tmp = pa.getword();
00245         }
00246         return true;
00247 }
00248 
00249 
00250 bool Utility::u2ip(const std::string& str, ipaddr_t& l)
00251 {
00252         struct sockaddr_in sa;
00253         bool r = Utility::u2ip(str, sa);
00254         memcpy(&l, &sa.sin_addr, sizeof(l));
00255         return r;
00256 }
00257 
00258 
00259 #ifdef ENABLE_IPV6
00260 #ifdef IPPROTO_IPV6
00261 bool Utility::u2ip(const std::string& str, struct in6_addr& l)
00262 {
00263         struct sockaddr_in6 sa;
00264         bool r = Utility::u2ip(str, sa);
00265         l = sa.sin6_addr;
00266         return r;
00267 }
00268 #endif
00269 #endif
00270 
00271 
00272 void Utility::l2ip(const ipaddr_t ip, std::string& str)
00273 {
00274         struct sockaddr_in sa;
00275         memset(&sa, 0, sizeof(sa));
00276         sa.sin_family = AF_INET;
00277         memcpy(&sa.sin_addr, &ip, sizeof(sa.sin_addr));
00278         Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST);
00279 }
00280 
00281 
00282 void Utility::l2ip(const in_addr& ip, std::string& str)
00283 {
00284         struct sockaddr_in sa;
00285         memset(&sa, 0, sizeof(sa));
00286         sa.sin_family = AF_INET;
00287         sa.sin_addr = ip;
00288         Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST);
00289 }
00290 
00291 
00292 #ifdef ENABLE_IPV6
00293 #ifdef IPPROTO_IPV6
00294 void Utility::l2ip(const struct in6_addr& ip, std::string& str,bool mixed)
00295 {
00296         char slask[100]; // l2ip temporary
00297         *slask = 0;
00298         unsigned int prev = 0;
00299         bool skipped = false;
00300         bool ok_to_skip = true;
00301         if (mixed)
00302         {
00303                 unsigned short x;
00304                 unsigned short addr16[8];
00305                 memcpy(addr16, &ip, sizeof(addr16));
00306                 for (size_t i = 0; i < 6; i++)
00307                 {
00308                         x = ntohs(addr16[i]);
00309                         if (*slask && (x || !ok_to_skip || prev))
00310                                 strcat(slask,":");
00311                         if (x || !ok_to_skip)
00312                         {
00313                                 sprintf(slask + strlen(slask),"%x", x);
00314                                 if (x && skipped)
00315                                         ok_to_skip = false;
00316                         }
00317                         else
00318                         {
00319                                 skipped = true;
00320                         }
00321                         prev = x;
00322                 }
00323                 x = ntohs(addr16[6]);
00324                 sprintf(slask + strlen(slask),":%u.%u",x / 256,x & 255);
00325                 x = ntohs(addr16[7]);
00326                 sprintf(slask + strlen(slask),".%u.%u",x / 256,x & 255);
00327         }
00328         else
00329         {
00330                 struct sockaddr_in6 sa;
00331                 memset(&sa, 0, sizeof(sa));
00332                 sa.sin6_family = AF_INET6;
00333                 sa.sin6_addr = ip;
00334                 Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST);
00335                 return;
00336         }
00337         str = slask;
00338 }
00339 
00340 
00341 int Utility::in6_addr_compare(in6_addr a,in6_addr b)
00342 {
00343         for (size_t i = 0; i < 16; i++)
00344         {
00345                 if (a.s6_addr[i] < b.s6_addr[i])
00346                         return -1;
00347                 if (a.s6_addr[i] > b.s6_addr[i])
00348                         return 1;
00349         }
00350         return 0;
00351 }
00352 #endif
00353 #endif
00354 
00355 
00356 void Utility::ResolveLocal()
00357 {
00358         char h[256];
00359 
00360         // get local hostname and translate into ip-address
00361         *h = 0;
00362         gethostname(h,255);
00363         {
00364                 if (Utility::u2ip(h, m_ip))
00365                 {
00366                         Utility::l2ip(m_ip, m_addr);
00367                 }
00368         }
00369 #ifdef ENABLE_IPV6
00370 #ifdef IPPROTO_IPV6
00371         memset(&m_local_ip6, 0, sizeof(m_local_ip6));
00372         {
00373                 if (Utility::u2ip(h, m_local_ip6))
00374                 {
00375                         Utility::l2ip(m_local_ip6, m_local_addr6);
00376                 }
00377         }
00378 #endif
00379 #endif
00380         m_host = h;
00381         m_local_resolved = true;
00382 }
00383 
00384 
00385 const std::string& Utility::GetLocalHostname()
00386 {
00387         if (!m_local_resolved)
00388         {
00389                 ResolveLocal();
00390         }
00391         return m_host;
00392 }
00393 
00394 
00395 ipaddr_t Utility::GetLocalIP()
00396 {
00397         if (!m_local_resolved)
00398         {
00399                 ResolveLocal();
00400         }
00401         return m_ip;
00402 }
00403 
00404 
00405 const std::string& Utility::GetLocalAddress()
00406 {
00407         if (!m_local_resolved)
00408         {
00409                 ResolveLocal();
00410         }
00411         return m_addr;
00412 }
00413 
00414 
00415 #ifdef ENABLE_IPV6
00416 #ifdef IPPROTO_IPV6
00417 const struct in6_addr& Utility::GetLocalIP6()
00418 {
00419         if (!m_local_resolved)
00420         {
00421                 ResolveLocal();
00422         }
00423         return m_local_ip6;
00424 }
00425 
00426 
00427 const std::string& Utility::GetLocalAddress6()
00428 {
00429         if (!m_local_resolved)
00430         {
00431                 ResolveLocal();
00432         }
00433         return m_local_addr6;
00434 }
00435 #endif
00436 #endif
00437 
00438 
00439 void Utility::SetEnv(const std::string& var,const std::string& value)
00440 {
00441 #if (defined(SOLARIS8) || defined(SOLARIS))
00442         {
00443                 static std::map<std::string, char *> vmap;
00444                 if (vmap.find(var) != vmap.end())
00445                 {
00446                         delete[] vmap[var];
00447                 }
00448                 vmap[var] = new char[var.size() + 1 + value.size() + 1];
00449                 sprintf(vmap[var], "%s=%s", var.c_str(), value.c_str());
00450                 putenv( vmap[var] );
00451         }
00452 #elif defined _WIN32
00453         {
00454                 std::string slask = var + "=" + value;
00455                 _putenv( (char *)slask.c_str());
00456         }
00457 #else
00458         setenv(var.c_str(), value.c_str(), 1);
00459 #endif
00460 }
00461 
00462 
00463 std::string Utility::Sa2String(struct sockaddr *sa)
00464 {
00465 #ifdef ENABLE_IPV6
00466 #ifdef IPPROTO_IPV6
00467         if (sa -> sa_family == AF_INET6)
00468         {
00469                 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
00470                 std::string tmp;
00471                 Utility::l2ip(sa6 -> sin6_addr, tmp);
00472                 return tmp + ":" + Utility::l2string(ntohs(sa6 -> sin6_port));
00473         }
00474 #endif
00475 #endif
00476         if (sa -> sa_family == AF_INET)
00477         {
00478                 struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
00479                 ipaddr_t a;
00480                 memcpy(&a, &sa4 -> sin_addr, 4);
00481                 std::string tmp;
00482                 Utility::l2ip(a, tmp);
00483                 return tmp + ":" + Utility::l2string(ntohs(sa4 -> sin_port));
00484         }
00485         return "";
00486 }
00487 
00488 
00489 void Utility::GetTime(struct timeval *p)
00490 {
00491 #ifdef _WIN32
00492         FILETIME ft; // Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).
00493         GetSystemTimeAsFileTime(&ft);
00494         uint64_t tt;
00495         memcpy(&tt, &ft, sizeof(tt));
00496         tt /= 10; // make it usecs
00497         p->tv_sec = (long)tt / 1000000;
00498         p->tv_usec = (long)tt % 1000000;
00499 #else
00500         gettimeofday(p, NULL);
00501 #endif
00502 }
00503 
00504 
00505 std::auto_ptr<SocketAddress> Utility::CreateAddress(struct sockaddr *sa,socklen_t sa_len)
00506 {
00507         switch (sa -> sa_family)
00508         {
00509         case AF_INET:
00510                 if (sa_len == sizeof(struct sockaddr_in))
00511                 {
00512                         struct sockaddr_in *p = (struct sockaddr_in *)sa;
00513                         return std::auto_ptr<SocketAddress>(new Ipv4Address(*p));
00514                 }
00515                 break;
00516 #ifdef ENABLE_IPV6
00517 #ifdef IPPROTO_IPV6
00518         case AF_INET6:
00519                 if (sa_len == sizeof(struct sockaddr_in6))
00520                 {
00521                         struct sockaddr_in6 *p = (struct sockaddr_in6 *)sa;
00522                         return std::auto_ptr<SocketAddress>(new Ipv6Address(*p));
00523                 }
00524                 break;
00525 #endif
00526 #endif
00527         }
00528         return std::auto_ptr<SocketAddress>(NULL);
00529 }
00530 
00531 
00532 bool Utility::u2ip(const std::string& host, struct sockaddr_in& sa, int ai_flags)
00533 {
00534         memset(&sa, 0, sizeof(sa));
00535         sa.sin_family = AF_INET;
00536 #ifdef NO_GETADDRINFO
00537         if ((ai_flags & AI_NUMERICHOST) != 0 || isipv4(host))
00538         {
00539                 Parse pa((char *)host.c_str(), ".");
00540                 union {
00541                         struct {
00542                                 unsigned char b1;
00543                                 unsigned char b2;
00544                                 unsigned char b3;
00545                                 unsigned char b4;
00546                         } a;
00547                         ipaddr_t l;
00548                 } u;
00549                 u.a.b1 = static_cast<unsigned char>(pa.getvalue());
00550                 u.a.b2 = static_cast<unsigned char>(pa.getvalue());
00551                 u.a.b3 = static_cast<unsigned char>(pa.getvalue());
00552                 u.a.b4 = static_cast<unsigned char>(pa.getvalue());
00553                 memcpy(&sa.sin_addr, &u.l, sizeof(sa.sin_addr));
00554                 return true;
00555         }
00556 #ifndef LINUX
00557         struct hostent *he = gethostbyname( host.c_str() );
00558         if (!he)
00559         {
00560                 return false;
00561         }
00562         memcpy(&sa.sin_addr, he -> h_addr, sizeof(sa.sin_addr));
00563 #else
00564         struct hostent he;
00565         struct hostent *result;
00566         int myerrno;
00567         char buf[2000];
00568         int n = gethostbyname_r(host.c_str(), &he, buf, sizeof(buf), &result, &myerrno);
00569         if (n)
00570         {
00571                 return false;
00572         }
00573         memcpy(&sa.sin_addr, he.h_addr, 4);
00574 #endif
00575         return true;
00576 #else
00577         struct addrinfo hints;
00578         memset(&hints, 0, sizeof(hints));
00579         // AI_NUMERICHOST
00580         // AI_CANONNAME
00581         // AI_PASSIVE - server
00582         // AI_ADDRCONFIG
00583         // AI_V4MAPPED
00584         // AI_ALL
00585         // AI_NUMERICSERV
00586         hints.ai_flags = ai_flags;
00587         hints.ai_family = AF_INET;
00588         hints.ai_socktype = 0;
00589         hints.ai_protocol = 0;
00590         struct addrinfo *res;
00591         if (Utility::isipv4(host))
00592                 hints.ai_flags |= AI_NUMERICHOST;
00593         int n = getaddrinfo(host.c_str(), NULL, &hints, &res);
00594         if (!n)
00595         {
00596                 static RandomNumber prng( true );
00597                 std::vector<struct addrinfo *> vec;
00598                 struct addrinfo *ai = res;
00599                 while (ai)
00600                 {
00601                         if (ai -> ai_addrlen == sizeof(sa))
00602                                 vec.push_back( ai );
00603                         prng.next();
00604                         //
00605                         ai = ai -> ai_next;
00606                 }
00607                 if (!vec.size())
00608                         return false;
00609                 ai = vec[prng.next() % vec.size()];
00610                 {
00611                         memcpy(&sa, ai -> ai_addr, ai -> ai_addrlen);
00612                 }
00613                 freeaddrinfo(res);
00614                 return true;
00615         }
00616         std::string error = "Error: ";
00617 #ifndef __CYGWIN__
00618         error += gai_strerror(n);
00619 #endif
00620         return false;
00621 #endif // NO_GETADDRINFO
00622 }
00623 
00624 
00625 #ifdef ENABLE_IPV6
00626 #ifdef IPPROTO_IPV6
00627 bool Utility::u2ip(const std::string& host, struct sockaddr_in6& sa, int ai_flags)
00628 {
00629         memset(&sa, 0, sizeof(sa));
00630         sa.sin6_family = AF_INET6;
00631 #ifdef NO_GETADDRINFO
00632         if ((ai_flags & AI_NUMERICHOST) != 0 || isipv6(host))
00633         {
00634                 std::list<std::string> vec;
00635                 size_t x = 0;
00636                 for (size_t i = 0; i <= host.size(); i++)
00637                 {
00638                         if (i == host.size() || host[i] == ':')
00639                         {
00640                                 std::string s = host.substr(x, i - x);
00641                                 //
00642                                 if (strstr(s.c_str(),".")) // x.x.x.x
00643                                 {
00644                                         Parse pa(s,".");
00645                                         char slask[100]; // u2ip temporary hex2string conversion
00646                                         unsigned long b0 = static_cast<unsigned long>(pa.getvalue());
00647                                         unsigned long b1 = static_cast<unsigned long>(pa.getvalue());
00648                                         unsigned long b2 = static_cast<unsigned long>(pa.getvalue());
00649                                         unsigned long b3 = static_cast<unsigned long>(pa.getvalue());
00650                                         sprintf(slask,"%lx",b0 * 256 + b1);
00651                                         vec.push_back(slask);
00652                                         sprintf(slask,"%lx",b2 * 256 + b3);
00653                                         vec.push_back(slask);
00654                                 }
00655                                 else
00656                                 {
00657                                         vec.push_back(s);
00658                                 }
00659                                 //
00660                                 x = i + 1;
00661                         }
00662                 }
00663                 size_t sz = vec.size(); // number of byte pairs
00664                 size_t i = 0; // index in in6_addr.in6_u.u6_addr16[] ( 0 .. 7 )
00665                 unsigned short addr16[8];
00666                 for (std::list<std::string>::iterator it = vec.begin(); it != vec.end(); it++)
00667                 {
00668                         std::string bytepair = *it;
00669                         if (bytepair.size())
00670                         {
00671                                 addr16[i++] = htons(Utility::hex2unsigned(bytepair));
00672                         }
00673                         else
00674                         {
00675                                 addr16[i++] = 0;
00676                                 while (sz++ < 8)
00677                                 {
00678                                         addr16[i++] = 0;
00679                                 }
00680                         }
00681                 }
00682                 memcpy(&sa.sin6_addr, addr16, sizeof(addr16));
00683                 return true;
00684         }
00685 #ifdef SOLARIS
00686         int errnum = 0;
00687         struct hostent *he = getipnodebyname( host.c_str(), AF_INET6, 0, &errnum );
00688 #else
00689         struct hostent *he = gethostbyname2( host.c_str(), AF_INET6 );
00690 #endif
00691         if (!he)
00692         {
00693                 return false;
00694         }
00695         memcpy(&sa.sin6_addr,he -> h_addr_list[0],he -> h_length);
00696 #ifdef SOLARIS
00697         free(he);
00698 #endif
00699         return true;
00700 #else
00701         struct addrinfo hints;
00702         memset(&hints, 0, sizeof(hints));
00703         hints.ai_flags = ai_flags;
00704         hints.ai_family = AF_INET6;
00705         hints.ai_socktype = 0;
00706         hints.ai_protocol = 0;
00707         struct addrinfo *res;
00708         if (Utility::isipv6(host))
00709                 hints.ai_flags |= AI_NUMERICHOST;
00710         int n = getaddrinfo(host.c_str(), NULL, &hints, &res);
00711         if (!n)
00712         {
00713                 static RandomNumber prng( true );
00714                 std::vector<struct addrinfo *> vec;
00715                 struct addrinfo *ai = res;
00716                 while (ai)
00717                 {
00718                         if (ai -> ai_addrlen == sizeof(sa))
00719                                 vec.push_back( ai );
00720                         prng.next();
00721                         //
00722                         ai = ai -> ai_next;
00723                 }
00724                 if (!vec.size())
00725                         return false;
00726                 ai = vec[prng.next() % vec.size()];
00727                 {
00728                         memcpy(&sa, ai -> ai_addr, ai -> ai_addrlen);
00729                 }
00730                 freeaddrinfo(res);
00731                 return true;
00732         }
00733         std::string error = "Error: ";
00734 #ifndef __CYGWIN__
00735         error += gai_strerror(n);
00736 #endif
00737         return false;
00738 #endif // NO_GETADDRINFO
00739 }
00740 #endif // IPPROTO_IPV6
00741 #endif // ENABLE_IPV6
00742 
00743 
00744 bool Utility::reverse(struct sockaddr *sa, socklen_t sa_len, std::string& hostname, int flags)
00745 {
00746         std::string service;
00747         return Utility::reverse(sa, sa_len, hostname, service, flags);
00748 }
00749 
00750 
00751 bool Utility::reverse(struct sockaddr *sa, socklen_t sa_len, std::string& hostname, std::string& service, int flags)
00752 {
00753         hostname = "";
00754         service = "";
00755 #ifdef NO_GETADDRINFO
00756         switch (sa -> sa_family)
00757         {
00758         case AF_INET:
00759                 if (flags & NI_NUMERICHOST)
00760                 {
00761                         union {
00762                                 struct {
00763                                         unsigned char b1;
00764                                         unsigned char b2;
00765                                         unsigned char b3;
00766                                         unsigned char b4;
00767                                 } a;
00768                                 ipaddr_t l;
00769                         } u;
00770                         struct sockaddr_in *sa_in = (struct sockaddr_in *)sa;
00771                         memcpy(&u.l, &sa_in -> sin_addr, sizeof(u.l));
00772                         char tmp[100];
00773                         sprintf(tmp, "%u.%u.%u.%u", u.a.b1, u.a.b2, u.a.b3, u.a.b4);
00774                         hostname = tmp;
00775                         return true;
00776                 }
00777                 else
00778                 {
00779                         struct sockaddr_in *sa_in = (struct sockaddr_in *)sa;
00780                         struct hostent *h = gethostbyaddr( (const char *)&sa_in -> sin_addr, sizeof(sa_in -> sin_addr), AF_INET);
00781                         if (h)
00782                         {
00783                                 hostname = h -> h_name;
00784                                 return true;
00785                         }
00786                 }
00787                 break;
00788 #ifdef ENABLE_IPV6
00789         case AF_INET6:
00790                 if (flags & NI_NUMERICHOST)
00791                 {
00792                         char slask[100]; // l2ip temporary
00793                         *slask = 0;
00794                         unsigned int prev = 0;
00795                         bool skipped = false;
00796                         bool ok_to_skip = true;
00797                         {
00798                                 unsigned short addr16[8];
00799                                 struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa;
00800                                 memcpy(addr16, &sa_in6 -> sin6_addr, sizeof(addr16));
00801                                 for (size_t i = 0; i < 8; i++)
00802                                 {
00803                                         unsigned short x = ntohs(addr16[i]);
00804                                         if (*slask && (x || !ok_to_skip || prev))
00805                                                 strcat(slask,":");
00806                                         if (x || !ok_to_skip)
00807                                         {
00808                                                 sprintf(slask + strlen(slask),"%x", x);
00809                                                 if (x && skipped)
00810                                                         ok_to_skip = false;
00811                                         }
00812                                         else
00813                                         {
00814                                                 skipped = true;
00815                                         }
00816                                         prev = x;
00817                                 }
00818                         }
00819                         if (!*slask)
00820                                 strcpy(slask, "::");
00821                         hostname = slask;
00822                         return true;
00823                 }
00824                 else
00825                 {
00826                         // %! TODO: ipv6 reverse lookup
00827                         struct sockaddr_in6 *sa_in = (struct sockaddr_in6 *)sa;
00828                         struct hostent *h = gethostbyaddr( (const char *)&sa_in -> sin6_addr, sizeof(sa_in -> sin6_addr), AF_INET6);
00829                         if (h)
00830                         {
00831                                 hostname = h -> h_name;
00832                                 return true;
00833                         }
00834                 }
00835                 break;
00836 #endif
00837         }
00838         return false;
00839 #else
00840         char host[NI_MAXHOST];
00841         char serv[NI_MAXSERV];
00842         // NI_NOFQDN
00843         // NI_NUMERICHOST
00844         // NI_NAMEREQD
00845         // NI_NUMERICSERV
00846         // NI_DGRAM
00847         int n = getnameinfo(sa, sa_len, host, sizeof(host), serv, sizeof(serv), flags);
00848         if (n)
00849         {
00850                 // EAI_AGAIN
00851                 // EAI_BADFLAGS
00852                 // EAI_FAIL
00853                 // EAI_FAMILY
00854                 // EAI_MEMORY
00855                 // EAI_NONAME
00856                 // EAI_OVERFLOW
00857                 // EAI_SYSTEM
00858                 return false;
00859         }
00860         hostname = host;
00861         service = serv;
00862         return true;
00863 #endif // NO_GETADDRINFO
00864 }
00865 
00866 
00867 bool Utility::u2service(const std::string& name, int& service, int ai_flags)
00868 {
00869 #ifdef NO_GETADDRINFO
00870         // %!
00871         return false;
00872 #else
00873         struct addrinfo hints;
00874         service = 0;
00875         memset(&hints, 0, sizeof(hints));
00876         // AI_NUMERICHOST
00877         // AI_CANONNAME
00878         // AI_PASSIVE - server
00879         // AI_ADDRCONFIG
00880         // AI_V4MAPPED
00881         // AI_ALL
00882         // AI_NUMERICSERV
00883         hints.ai_flags = ai_flags;
00884         hints.ai_family = AF_UNSPEC;
00885         hints.ai_socktype = 0;
00886         hints.ai_protocol = 0;
00887         struct addrinfo *res;
00888         int n = getaddrinfo(NULL, name.c_str(), &hints, &res);
00889         if (!n)
00890         {
00891                 service = res -> ai_protocol;
00892                 freeaddrinfo(res);
00893                 return true;
00894         }
00895         return false;
00896 #endif // NO_GETADDRINFO
00897 }
00898 
00899 
00900 unsigned long Utility::ThreadID()
00901 {
00902 #ifdef _WIN32
00903         return GetCurrentThreadId();
00904 #else
00905         return (unsigned long)pthread_self();
00906 #endif
00907 }
00908 
00909 
00910 std::string Utility::ToLower(const std::string& str)
00911 {
00912         std::string r;
00913         for (size_t i = 0; i < str.size(); i++)
00914         {
00915                 if (str[i] >= 'A' && str[i] <= 'Z')
00916                         r += str[i] | 32;
00917                 else
00918                         r += str[i];
00919         }
00920         return r;
00921 }
00922 
00923 
00924 std::string Utility::ToUpper(const std::string& str)
00925 {
00926         std::string r;
00927         for (size_t i = 0; i < str.size(); i++)
00928         {
00929                 if (str[i] >= 'a' && str[i] <= 'z')
00930                         r += (char)(str[i] - 32);
00931                 else
00932                         r += str[i];
00933         }
00934         return r;
00935 }
00936 
00937 
00938 std::string Utility::ToString(double d)
00939 {
00940         char tmp[100];
00941         sprintf(tmp, "%f", d);
00942         return tmp;
00943 }
00944 
00945 
00946 #ifdef SOCKETS_NAMESPACE
00947 }
00948 #endif
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4