Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
diff src/gt_guid.c @ 0:d39e1d0d75b6
initial add
author | paulo@hit-nxdomain.opendns.com |
---|---|
date | Sat, 20 Feb 2010 21:18:28 -0800 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/gt_guid.c Sat Feb 20 21:18:28 2010 -0800 1.3 @@ -0,0 +1,309 @@ 1.4 +/* 1.5 + * $Id: gt_guid.c,v 1.18 2006/01/28 16:57:56 mkern Exp $ 1.6 + * 1.7 + * Copyright (C) 2001-2003 giFT project (gift.sourceforge.net) 1.8 + * 1.9 + * This program is free software; you can redistribute it and/or modify it 1.10 + * under the terms of the GNU General Public License as published by the 1.11 + * Free Software Foundation; either version 2, or (at your option) any 1.12 + * later version. 1.13 + * 1.14 + * This program is distributed in the hope that it will be useful, but 1.15 + * WITHOUT ANY WARRANTY; without even the implied warranty of 1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.17 + * General Public License for more details. 1.18 + */ 1.19 + 1.20 +#include "gt_gnutella.h" 1.21 +#include "sha1.h" 1.22 + 1.23 +/*****************************************************************************/ 1.24 + 1.25 +/* global guid identifying this client */ 1.26 +gt_guid_t *GT_SELF_GUID; 1.27 + 1.28 +/*****************************************************************************/ 1.29 + 1.30 +/* seed for generating unique numbers */ 1.31 +static unsigned int seed = 0; 1.32 + 1.33 +/* map binary numbers to hexadecimal */ 1.34 +static char bin_to_hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 1.35 + 'a', 'b', 'c', 'd', 'e', 'f' }; 1.36 + 1.37 +/* guid filled with all zeroes */ 1.38 +static gt_guid_t zero_guid[GT_GUID_LEN] = { 0 }; 1.39 + 1.40 +/*****************************************************************************/ 1.41 + 1.42 +/* TODO: use /dev/urandom when available */ 1.43 +static unsigned int rng_seed (void) 1.44 +{ 1.45 + sha1_state_t sha1; 1.46 + struct timeval tv; 1.47 + unsigned int seed; 1.48 + int i; 1.49 + unsigned char hash[SHA1_BINSIZE]; 1.50 + 1.51 + gt_sha1_init (&sha1); 1.52 + platform_gettimeofday (&tv, NULL); 1.53 + 1.54 + gt_sha1_append (&sha1, &tv.tv_usec, sizeof (tv.tv_usec)); 1.55 + gt_sha1_append (&sha1, &tv.tv_sec, sizeof (tv.tv_sec)); 1.56 + 1.57 +#ifdef HAVE_GETPID 1.58 + { 1.59 + pid_t pid = getpid(); 1.60 + gt_sha1_append (&sha1, &pid, sizeof (pid)); 1.61 + } 1.62 +#endif 1.63 + 1.64 +#ifdef WIN32 1.65 + { 1.66 + DWORD process_id = GetCurrentProcessId(); 1.67 + gt_sha1_append (&sha1, &process_id, sizeof (process_id)); 1.68 + } 1.69 +#endif 1.70 + 1.71 +#ifdef HAVE_GETPPID 1.72 + { 1.73 + pid_t ppid = getppid(); 1.74 + gt_sha1_append (&sha1, &ppid, sizeof (ppid)); 1.75 + } 1.76 +#endif /* WIN32 */ 1.77 + 1.78 + memset (hash, 0, sizeof (hash)); 1.79 + gt_sha1_finish (&sha1, hash); 1.80 + 1.81 + seed = 0; 1.82 + i = 0; 1.83 + 1.84 + /* crush the hash into an unsigned int */ 1.85 + while (i < SHA1_BINSIZE) 1.86 + { 1.87 + unsigned int t; 1.88 + size_t len; 1.89 + 1.90 + t = 0; 1.91 + len = MIN (sizeof (unsigned int), SHA1_BINSIZE - i); 1.92 + 1.93 + memcpy (&t, &hash[i], len); 1.94 + 1.95 + seed ^= t; 1.96 + i += len; 1.97 + } 1.98 + 1.99 + return seed; 1.100 +} 1.101 + 1.102 +void gt_guid_init (gt_guid_t *guid) 1.103 +{ 1.104 + int i; 1.105 + 1.106 + if (!seed) 1.107 + { 1.108 + seed = rng_seed(); 1.109 + srand (seed); 1.110 + } 1.111 + 1.112 + for (i = GT_GUID_LEN - 1; i >= 0; i--) 1.113 + guid[i] = 256.0 * rand() / (RAND_MAX + 1.0); 1.114 + 1.115 + /* mark this GUID as coming from a "new" client */ 1.116 + guid[8] = 0xff; 1.117 + guid[15] = 0x01; 1.118 +} 1.119 + 1.120 +gt_guid_t *gt_guid_new (void) 1.121 +{ 1.122 + gt_guid_t *guid; 1.123 + 1.124 + if (!(guid = malloc (GT_GUID_LEN))) 1.125 + return NULL; 1.126 + 1.127 + gt_guid_init (guid); 1.128 + 1.129 + return guid; 1.130 +} 1.131 + 1.132 +int gt_guid_cmp (const gt_guid_t *a, const gt_guid_t *b) 1.133 +{ 1.134 + if (!a) 1.135 + return (b == NULL ? 0 : -1); 1.136 + else if (!b) 1.137 + return (a == NULL ? 0 : +1); 1.138 + 1.139 + return memcmp (a, b, GT_GUID_LEN); 1.140 +} 1.141 + 1.142 +char *gt_guid_str (const gt_guid_t *guid) 1.143 +{ 1.144 + static char buf[128]; 1.145 + unsigned char c; 1.146 + int pos; 1.147 + int len; 1.148 + 1.149 + if (!guid) 1.150 + return NULL; 1.151 + 1.152 + pos = 0; 1.153 + len = GT_GUID_LEN; 1.154 + 1.155 + while (len-- > 0) 1.156 + { 1.157 + c = *guid++; 1.158 + 1.159 + buf[pos++] = bin_to_hex[(c & 0xf0) >> 4]; 1.160 + buf[pos++] = bin_to_hex[(c & 0x0f)]; 1.161 + } 1.162 + 1.163 + buf[pos] = 0; 1.164 + 1.165 + return buf; 1.166 +} 1.167 + 1.168 +gt_guid_t *gt_guid_dup (const gt_guid_t *guid) 1.169 +{ 1.170 + gt_guid_t *new_guid; 1.171 + 1.172 + if (!(new_guid = malloc (GT_GUID_LEN))) 1.173 + return NULL; 1.174 + 1.175 + memcpy (new_guid, guid, GT_GUID_LEN); 1.176 + 1.177 + return new_guid; 1.178 +} 1.179 + 1.180 +static unsigned char hex_char_to_bin (char x) 1.181 +{ 1.182 + if (x >= '0' && x <= '9') 1.183 + return (x - '0'); 1.184 + 1.185 + x = toupper (x); 1.186 + 1.187 + return ((x - 'A') + 10); 1.188 +} 1.189 + 1.190 +static int hex_to_bin (const char *hex, unsigned char *bin, int len) 1.191 +{ 1.192 + unsigned char value; 1.193 + 1.194 + while (isxdigit (hex[0]) && isxdigit (hex[1]) && len-- > 0) 1.195 + { 1.196 + value = (hex_char_to_bin (*hex++) << 4) & 0xf0; 1.197 + value |= (hex_char_to_bin (*hex++) & 0x0f); 1.198 + *bin++ = value; 1.199 + } 1.200 + 1.201 + return (len <= 0) ? TRUE : FALSE; 1.202 +} 1.203 + 1.204 +gt_guid_t *gt_guid_bin (const char *guid_ascii) 1.205 +{ 1.206 + gt_guid_t *guid; 1.207 + 1.208 + if (!guid_ascii) 1.209 + return NULL; 1.210 + 1.211 + if (!(guid = malloc (GT_GUID_LEN))) 1.212 + return NULL; 1.213 + 1.214 + if (!hex_to_bin (guid_ascii, guid, GT_GUID_LEN)) 1.215 + { 1.216 + free (guid); 1.217 + return NULL; 1.218 + } 1.219 + 1.220 + return guid; 1.221 +} 1.222 + 1.223 +/*****************************************************************************/ 1.224 + 1.225 +BOOL gt_guid_is_empty (const gt_guid_t *guid) 1.226 +{ 1.227 + if (!guid) 1.228 + return TRUE; 1.229 + 1.230 + return memcmp (guid, zero_guid, GT_GUID_LEN) == 0; 1.231 +} 1.232 + 1.233 +/*****************************************************************************/ 1.234 + 1.235 +/* 1.236 + * Load the client GUID for this node. 1.237 + */ 1.238 +static gt_guid_t *get_client_id (char *conf_path) 1.239 +{ 1.240 + FILE *f; 1.241 + gt_guid_t *client_id = NULL; 1.242 + char *buf = NULL; 1.243 + 1.244 + /* 1.245 + * There are people who distribute giFT packages which include the 1.246 + * developer's client-id file. These packages (mainly KCeasy derivatives, 1.247 + * I think) are widely enough distributed that other gnutella developers 1.248 + * have noticed the problem and notified me. To prevent this problem in 1.249 + * future versions I have forced randomization of the GUID on each startup 1.250 + * below. --mkern 1.251 + */ 1.252 +#if 0 1.253 + if ((f = fopen (gift_conf_path (conf_path), "r"))) 1.254 + { 1.255 + while (file_read_line (f, &buf)) 1.256 + { 1.257 + char *id; 1.258 + char *line; 1.259 + 1.260 + free (client_id); 1.261 + client_id = NULL; 1.262 + 1.263 + line = buf; 1.264 + id = string_sep_set (&line, "\r\n"); 1.265 + 1.266 + if (string_isempty (id)) 1.267 + continue; 1.268 + 1.269 + client_id = gt_guid_bin (id); 1.270 + } 1.271 + 1.272 + fclose (f); 1.273 + } 1.274 +#endif 1.275 + 1.276 + /* TODO: regenerate when client guid is pretty old */ 1.277 + if (client_id != NULL) 1.278 + return client_id; 1.279 + 1.280 + /* 1.281 + * Create a new client identifier 1.282 + */ 1.283 + client_id = gt_guid_new (); 1.284 + assert (client_id != NULL); 1.285 + 1.286 + /* store the id in ~/.giFT/Gnutella/clientid */ 1.287 + if (!(f = fopen (gift_conf_path (conf_path), "w"))) 1.288 + { 1.289 + GIFT_ERROR (("clientid storage file: %s", GIFT_STRERROR ())); 1.290 + return client_id; 1.291 + } 1.292 + 1.293 + fprintf (f, "%s\n", gt_guid_str (client_id)); 1.294 + fclose (f); 1.295 + 1.296 + return client_id; 1.297 +} 1.298 + 1.299 +void gt_guid_self_init (void) 1.300 +{ 1.301 + GT_SELF_GUID = get_client_id ("Gnutella/client-id"); 1.302 + 1.303 + /* remove the old clientid file which used an inferior random number 1.304 + * generator */ 1.305 + remove (gift_conf_path ("Gnutella/clientid")); 1.306 +} 1.307 + 1.308 +void gt_guid_self_cleanup (void) 1.309 +{ 1.310 + free (GT_SELF_GUID); 1.311 + GT_SELF_GUID = NULL; 1.312 +}