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 +}