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