Mercurial > hg > index.fcgi > gift-gnutella > gift-gnutella-0.0.11-1pba
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:49980d5cc34f |
---|---|
1 /* | |
2 * $Id: gt_guid.c,v 1.18 2006/01/28 16:57:56 mkern Exp $ | |
3 * | |
4 * Copyright (C) 2001-2003 giFT project (gift.sourceforge.net) | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify it | |
7 * under the terms of the GNU General Public License as published by the | |
8 * Free Software Foundation; either version 2, or (at your option) any | |
9 * later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, but | |
12 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * General Public License for more details. | |
15 */ | |
16 | |
17 #include "gt_gnutella.h" | |
18 #include "sha1.h" | |
19 | |
20 /*****************************************************************************/ | |
21 | |
22 /* global guid identifying this client */ | |
23 gt_guid_t *GT_SELF_GUID; | |
24 | |
25 /*****************************************************************************/ | |
26 | |
27 /* seed for generating unique numbers */ | |
28 static unsigned int seed = 0; | |
29 | |
30 /* map binary numbers to hexadecimal */ | |
31 static char bin_to_hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | |
32 'a', 'b', 'c', 'd', 'e', 'f' }; | |
33 | |
34 /* guid filled with all zeroes */ | |
35 static gt_guid_t zero_guid[GT_GUID_LEN] = { 0 }; | |
36 | |
37 /*****************************************************************************/ | |
38 | |
39 /* TODO: use /dev/urandom when available */ | |
40 static unsigned int rng_seed (void) | |
41 { | |
42 sha1_state_t sha1; | |
43 struct timeval tv; | |
44 unsigned int seed; | |
45 int i; | |
46 unsigned char hash[SHA1_BINSIZE]; | |
47 | |
48 gt_sha1_init (&sha1); | |
49 platform_gettimeofday (&tv, NULL); | |
50 | |
51 gt_sha1_append (&sha1, &tv.tv_usec, sizeof (tv.tv_usec)); | |
52 gt_sha1_append (&sha1, &tv.tv_sec, sizeof (tv.tv_sec)); | |
53 | |
54 #ifdef HAVE_GETPID | |
55 { | |
56 pid_t pid = getpid(); | |
57 gt_sha1_append (&sha1, &pid, sizeof (pid)); | |
58 } | |
59 #endif | |
60 | |
61 #ifdef WIN32 | |
62 { | |
63 DWORD process_id = GetCurrentProcessId(); | |
64 gt_sha1_append (&sha1, &process_id, sizeof (process_id)); | |
65 } | |
66 #endif | |
67 | |
68 #ifdef HAVE_GETPPID | |
69 { | |
70 pid_t ppid = getppid(); | |
71 gt_sha1_append (&sha1, &ppid, sizeof (ppid)); | |
72 } | |
73 #endif /* WIN32 */ | |
74 | |
75 memset (hash, 0, sizeof (hash)); | |
76 gt_sha1_finish (&sha1, hash); | |
77 | |
78 seed = 0; | |
79 i = 0; | |
80 | |
81 /* crush the hash into an unsigned int */ | |
82 while (i < SHA1_BINSIZE) | |
83 { | |
84 unsigned int t; | |
85 size_t len; | |
86 | |
87 t = 0; | |
88 len = MIN (sizeof (unsigned int), SHA1_BINSIZE - i); | |
89 | |
90 memcpy (&t, &hash[i], len); | |
91 | |
92 seed ^= t; | |
93 i += len; | |
94 } | |
95 | |
96 return seed; | |
97 } | |
98 | |
99 void gt_guid_init (gt_guid_t *guid) | |
100 { | |
101 int i; | |
102 | |
103 if (!seed) | |
104 { | |
105 seed = rng_seed(); | |
106 srand (seed); | |
107 } | |
108 | |
109 for (i = GT_GUID_LEN - 1; i >= 0; i--) | |
110 guid[i] = 256.0 * rand() / (RAND_MAX + 1.0); | |
111 | |
112 /* mark this GUID as coming from a "new" client */ | |
113 guid[8] = 0xff; | |
114 guid[15] = 0x01; | |
115 } | |
116 | |
117 gt_guid_t *gt_guid_new (void) | |
118 { | |
119 gt_guid_t *guid; | |
120 | |
121 if (!(guid = malloc (GT_GUID_LEN))) | |
122 return NULL; | |
123 | |
124 gt_guid_init (guid); | |
125 | |
126 return guid; | |
127 } | |
128 | |
129 int gt_guid_cmp (const gt_guid_t *a, const gt_guid_t *b) | |
130 { | |
131 if (!a) | |
132 return (b == NULL ? 0 : -1); | |
133 else if (!b) | |
134 return (a == NULL ? 0 : +1); | |
135 | |
136 return memcmp (a, b, GT_GUID_LEN); | |
137 } | |
138 | |
139 char *gt_guid_str (const gt_guid_t *guid) | |
140 { | |
141 static char buf[128]; | |
142 unsigned char c; | |
143 int pos; | |
144 int len; | |
145 | |
146 if (!guid) | |
147 return NULL; | |
148 | |
149 pos = 0; | |
150 len = GT_GUID_LEN; | |
151 | |
152 while (len-- > 0) | |
153 { | |
154 c = *guid++; | |
155 | |
156 buf[pos++] = bin_to_hex[(c & 0xf0) >> 4]; | |
157 buf[pos++] = bin_to_hex[(c & 0x0f)]; | |
158 } | |
159 | |
160 buf[pos] = 0; | |
161 | |
162 return buf; | |
163 } | |
164 | |
165 gt_guid_t *gt_guid_dup (const gt_guid_t *guid) | |
166 { | |
167 gt_guid_t *new_guid; | |
168 | |
169 if (!(new_guid = malloc (GT_GUID_LEN))) | |
170 return NULL; | |
171 | |
172 memcpy (new_guid, guid, GT_GUID_LEN); | |
173 | |
174 return new_guid; | |
175 } | |
176 | |
177 static unsigned char hex_char_to_bin (char x) | |
178 { | |
179 if (x >= '0' && x <= '9') | |
180 return (x - '0'); | |
181 | |
182 x = toupper (x); | |
183 | |
184 return ((x - 'A') + 10); | |
185 } | |
186 | |
187 static int hex_to_bin (const char *hex, unsigned char *bin, int len) | |
188 { | |
189 unsigned char value; | |
190 | |
191 while (isxdigit (hex[0]) && isxdigit (hex[1]) && len-- > 0) | |
192 { | |
193 value = (hex_char_to_bin (*hex++) << 4) & 0xf0; | |
194 value |= (hex_char_to_bin (*hex++) & 0x0f); | |
195 *bin++ = value; | |
196 } | |
197 | |
198 return (len <= 0) ? TRUE : FALSE; | |
199 } | |
200 | |
201 gt_guid_t *gt_guid_bin (const char *guid_ascii) | |
202 { | |
203 gt_guid_t *guid; | |
204 | |
205 if (!guid_ascii) | |
206 return NULL; | |
207 | |
208 if (!(guid = malloc (GT_GUID_LEN))) | |
209 return NULL; | |
210 | |
211 if (!hex_to_bin (guid_ascii, guid, GT_GUID_LEN)) | |
212 { | |
213 free (guid); | |
214 return NULL; | |
215 } | |
216 | |
217 return guid; | |
218 } | |
219 | |
220 /*****************************************************************************/ | |
221 | |
222 BOOL gt_guid_is_empty (const gt_guid_t *guid) | |
223 { | |
224 if (!guid) | |
225 return TRUE; | |
226 | |
227 return memcmp (guid, zero_guid, GT_GUID_LEN) == 0; | |
228 } | |
229 | |
230 /*****************************************************************************/ | |
231 | |
232 /* | |
233 * Load the client GUID for this node. | |
234 */ | |
235 static gt_guid_t *get_client_id (char *conf_path) | |
236 { | |
237 FILE *f; | |
238 gt_guid_t *client_id = NULL; | |
239 char *buf = NULL; | |
240 | |
241 /* | |
242 * There are people who distribute giFT packages which include the | |
243 * developer's client-id file. These packages (mainly KCeasy derivatives, | |
244 * I think) are widely enough distributed that other gnutella developers | |
245 * have noticed the problem and notified me. To prevent this problem in | |
246 * future versions I have forced randomization of the GUID on each startup | |
247 * below. --mkern | |
248 */ | |
249 #if 0 | |
250 if ((f = fopen (gift_conf_path (conf_path), "r"))) | |
251 { | |
252 while (file_read_line (f, &buf)) | |
253 { | |
254 char *id; | |
255 char *line; | |
256 | |
257 free (client_id); | |
258 client_id = NULL; | |
259 | |
260 line = buf; | |
261 id = string_sep_set (&line, "\r\n"); | |
262 | |
263 if (string_isempty (id)) | |
264 continue; | |
265 | |
266 client_id = gt_guid_bin (id); | |
267 } | |
268 | |
269 fclose (f); | |
270 } | |
271 #endif | |
272 | |
273 /* TODO: regenerate when client guid is pretty old */ | |
274 if (client_id != NULL) | |
275 return client_id; | |
276 | |
277 /* | |
278 * Create a new client identifier | |
279 */ | |
280 client_id = gt_guid_new (); | |
281 assert (client_id != NULL); | |
282 | |
283 /* store the id in ~/.giFT/Gnutella/clientid */ | |
284 if (!(f = fopen (gift_conf_path (conf_path), "w"))) | |
285 { | |
286 GIFT_ERROR (("clientid storage file: %s", GIFT_STRERROR ())); | |
287 return client_id; | |
288 } | |
289 | |
290 fprintf (f, "%s\n", gt_guid_str (client_id)); | |
291 fclose (f); | |
292 | |
293 return client_id; | |
294 } | |
295 | |
296 void gt_guid_self_init (void) | |
297 { | |
298 GT_SELF_GUID = get_client_id ("Gnutella/client-id"); | |
299 | |
300 /* remove the old clientid file which used an inferior random number | |
301 * generator */ | |
302 remove (gift_conf_path ("Gnutella/clientid")); | |
303 } | |
304 | |
305 void gt_guid_self_cleanup (void) | |
306 { | |
307 free (GT_SELF_GUID); | |
308 GT_SELF_GUID = NULL; | |
309 } |