Back to index

nordugrid-arc-nox  1.1.0~rc6
GUID.cpp
Go to the documentation of this file.
00001 // -*- indent-tabs-mode: nil -*-
00002 
00003 #ifdef HAVE_CONFIG_H
00004 #include "config.h"
00005 #endif
00006 
00007 #ifdef WIN32
00008 #define NOGDI
00009 #include <objbase.h>
00010 #include <cstdio>
00011 #else
00012 #include <sys/time.h>
00013 #include <netinet/in.h>
00014 #include <netdb.h>
00015 #include <unistd.h>
00016 #include <cstdlib>
00017 #include <cstdio>
00018 #endif
00019 
00020 #include "GUID.h"
00021 
00022 #ifdef WIN32
00023 void Arc::GUID(std::string& guid) {
00024   ::GUID g;
00025   HRESULT r;
00026   r = CoCreateGuid(&g);
00027   if (r != S_OK) {
00028     printf("There is an error during GUID generation!\n");
00029     return;
00030   }
00031   char s[32];
00032   snprintf(s, 32, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", g.Data1, g.Data2, g.Data3, g.Data4[0], g.Data4[1], g.Data4[2], g.Data4[3], g.Data4[4], g.Data4[5], g.Data4[6], g.Data4[7]);
00033   guid = s;
00034 }
00035 
00036 std::string Arc::UUID(void) {
00037   std::string ret;
00038   GUID(ret);
00039   return ret;
00040 }
00041 #else
00042 static bool initialized = false;
00043 
00044 static char guid_chars[] = {
00045   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
00046   'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
00047   'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
00048   'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
00049   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
00050 };
00051 
00052 static uint32_t guid_counter;
00053 
00054 static void guid_add_string(std::string& guid, uint32_t n) {
00055   uint32_t max = 0xFFFFFFFF;
00056   for (; max;) {
00057     uint32_t i = n % sizeof(guid_chars);
00058     guid += guid_chars[i];
00059     n /= sizeof(guid_chars);
00060     max /= sizeof(guid_chars);
00061     n += 0x55555555;
00062   }
00063 }
00064 
00065 void Arc::GUID(std::string& guid) {
00066   if (!initialized) {
00067     srandom(time(NULL));
00068     initialized = true;
00069   }
00070   struct timeval tv;
00071   struct timezone tz;
00072   gettimeofday(&tv, &tz);
00073   // Use up to 4 IP addresses
00074   uint32_t hostid[4] = {
00075     INADDR_ANY, INADDR_ANY, INADDR_ANY, INADDR_ANY
00076   };
00077   hostid[0] = gethostid();
00078   if (htonl(INADDR_LOOPBACK) == hostid[0])
00079     hostid[0] = INADDR_ANY;
00080   char hostname[1024];
00081   // Local addresses
00082   if (gethostname(hostname, sizeof(hostname) - 1) == 0) {
00083     hostname[sizeof(hostname) - 1] = 0;
00084     struct addrinfo* res = NULL; 
00085     if(getaddrinfo(hostname,NULL,NULL,&res) == 0) {
00086       for(struct addrinfo* r=res;r;r=r->ai_next) {
00087         if(!(r->ai_addr)) continue;
00088         uint32_t s_address = INADDR_ANY;
00089         if(r->ai_addr->sa_family == AF_INET) {
00090           struct sockaddr_in* addr = (struct sockaddr_in*)(r->ai_addr);
00091           s_address = addr->sin_addr.s_addr;
00092           if(s_address == htonl(INADDR_LOOPBACK)) continue;
00093         } else if(r->ai_addr->sa_family == AF_INET6) {
00094           struct sockaddr_in6* addr = (struct sockaddr_in6*)(r->ai_addr);
00095           s_address = 0;
00096           for(int i=0;i<16;++i) {
00097             s_address ^= addr->sin6_addr.s6_addr[i];
00098             s_address <<= 2;
00099           }
00100         }
00101         if(s_address == INADDR_ANY) continue;
00102         int i;
00103         for (i = 0; i < 3; i++) {
00104           if (hostid[i] == INADDR_ANY) break;
00105           if (s_address == hostid[i]) break;
00106         }
00107         if (i >= 3) continue;
00108         if (hostid[i] != INADDR_ANY) continue;
00109         hostid[i] = s_address;
00110       }
00111       freeaddrinfo(res);  
00112     }
00113   }
00114   // External address (TODO)
00115 
00116   // Use collected information
00117   guid_add_string(guid, tv.tv_usec);
00118   guid_add_string(guid, tv.tv_sec);
00119   guid_add_string(guid, hostid[0]);
00120   guid_add_string(guid, hostid[1]);
00121   guid_add_string(guid, hostid[2]);
00122   guid_add_string(guid, hostid[3]);
00123   guid_add_string(guid, getpid());
00124   guid_add_string(guid, guid_counter++);
00125   guid_add_string(guid, random());
00126 }
00127 
00128 #if HAVE_UUID_UUID_H
00129 #include <uuid/uuid.h>
00130 std::string Arc::UUID(void) {
00131   uuid_t uu;
00132   uuid_generate(uu);
00133   char uustr[37];
00134   uuid_unparse(uu, uustr);
00135   return uustr;
00136 }
00137 #else
00138 std::string Arc::UUID(void) {
00139   if (!initialized) {
00140     srandom(time(NULL));
00141     initialized = true;
00142   }
00143   std::string uuid_str("");
00144   int rnd[10];
00145   char buffer[20];
00146   unsigned long uuid_part;
00147   for (int j = 0; j < 4; j++) {
00148     for (int i = 0; i < 16; i++)
00149       rnd[i] = random() % 256;
00150     rnd[6] = (rnd[6] & 0x4F) | 0x40;
00151     rnd[8] = (rnd[8] & 0xBF) | 0x80;
00152     uuid_part = 0L;
00153     for (int i = 0; i < 16; i++)
00154       uuid_part = (uuid_part << 8) + rnd[i];
00155     snprintf(buffer, sizeof(buffer), "%08lx", uuid_part);
00156     uuid_str.append(buffer, 8);
00157   }
00158 
00159   uuid_str.insert(8, "-");
00160   uuid_str.insert(13, "-");
00161   uuid_str.insert(18, "-");
00162   uuid_str.insert(23, "-");
00163   return uuid_str;
00164 }
00165 #endif
00166 #endif  // non WIN32