diff options
Diffstat (limited to '3rdparty/openpgm-svn-r1135/pgm/gsi.c')
-rw-r--r-- | 3rdparty/openpgm-svn-r1135/pgm/gsi.c | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/3rdparty/openpgm-svn-r1135/pgm/gsi.c b/3rdparty/openpgm-svn-r1135/pgm/gsi.c new file mode 100644 index 0000000..c086cb9 --- /dev/null +++ b/3rdparty/openpgm-svn-r1135/pgm/gsi.c @@ -0,0 +1,232 @@ +/* vim:ts=8:sts=8:sw=4:noai:noexpandtab + * + * global session ID helper functions. + * + * Copyright (c) 2006-2010 Miru Limited. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <errno.h> +#include <stdio.h> +#ifndef _WIN32 +# include <netdb.h> +#endif +#include <impl/i18n.h> +#include <impl/framework.h> + + +//#define GSI_DEBUG + + +/* create a GSI based on md5 of a user provided data block. + * + * returns TRUE on success, returns FALSE on error and sets error appropriately, + */ + +bool +pgm_gsi_create_from_data ( + pgm_gsi_t* restrict gsi, + const uint8_t* restrict data, + const size_t length + ) +{ + pgm_return_val_if_fail (NULL != gsi, FALSE); + pgm_return_val_if_fail (NULL != data, FALSE); + pgm_return_val_if_fail (length > 1, FALSE); + +#ifdef CONFIG_HAVE_GLIB_CHECKSUM + GChecksum* checksum = g_checksum_new (G_CHECKSUM_MD5); + pgm_return_val_if_fail (NULL != checksum, FALSE); + g_checksum_update (checksum, data, length); + memcpy (gsi, g_checksum_get_string (checksum) + 10, 6); + g_checksum_free (checksum); +#else + struct pgm_md5_t ctx; + char resblock[16]; + pgm_md5_init_ctx (&ctx); + pgm_md5_process_bytes (&ctx, data, length); + pgm_md5_finish_ctx (&ctx, resblock); + memcpy (gsi, resblock + 10, 6); +#endif + return TRUE; +} + +bool +pgm_gsi_create_from_string ( + pgm_gsi_t* restrict gsi, + const char* restrict str, + ssize_t length /* -1 for NULL terminated */ + ) +{ + pgm_return_val_if_fail (NULL != gsi, FALSE); + pgm_return_val_if_fail (NULL != str, FALSE); + + if (length < 0) + length = strlen (str); + + return pgm_gsi_create_from_data (gsi, (const uint8_t*)str, length); +} + +/* create a global session ID as recommended by the PGM draft specification using + * low order 48 bits of md5 of the hostname. + * + * returns TRUE on success, returns FALSE on error and sets error appropriately, + */ + +bool +pgm_gsi_create_from_hostname ( + pgm_gsi_t* restrict gsi, + pgm_error_t** restrict error + ) +{ + pgm_return_val_if_fail (NULL != gsi, FALSE); + + char hostname[NI_MAXHOST]; + int retval = gethostname (hostname, sizeof(hostname)); + if (0 != retval) { + pgm_set_error (error, + PGM_ERROR_DOMAIN_IF, + pgm_error_from_errno (errno), + _("Resolving hostname: %s"), +#ifndef _WIN32 + strerror (errno) +#else + pgm_wsastrerror (WSAGetLastError()) +#endif + ); + return FALSE; + } + + return pgm_gsi_create_from_string (gsi, hostname, -1); +} + +/* create a global session ID based on the IP address. + * + * returns TRUE on succcess, returns FALSE on error and sets error. + */ + +bool +pgm_gsi_create_from_addr ( + pgm_gsi_t* restrict gsi, + pgm_error_t** restrict error + ) +{ + char hostname[NI_MAXHOST]; + struct addrinfo hints, *res = NULL; + + pgm_return_val_if_fail (NULL != gsi, FALSE); + + int retval = gethostname (hostname, sizeof(hostname)); + if (0 != retval) { + pgm_set_error (error, + PGM_ERROR_DOMAIN_IF, + pgm_error_from_errno (errno), + _("Resolving hostname: %s"), +#ifndef _WIN32 + strerror (errno) +#else + pgm_wsastrerror (WSAGetLastError()) +#endif + ); + return FALSE; + } + memset (&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_flags = AI_ADDRCONFIG; + retval = getaddrinfo (hostname, NULL, &hints, &res); + if (0 != retval) { + pgm_set_error (error, + PGM_ERROR_DOMAIN_IF, + pgm_error_from_eai_errno (retval, errno), + _("Resolving hostname address: %s"), + gai_strerror (retval)); + return FALSE; + } + memcpy (gsi, &((struct sockaddr_in*)(res->ai_addr))->sin_addr, sizeof(struct in_addr)); + freeaddrinfo (res); + const uint16_t random_val = pgm_random_int_range (0, UINT16_MAX); + memcpy ((uint8_t*)gsi + sizeof(struct in_addr), &random_val, sizeof(random_val)); + return TRUE; +} + +/* re-entrant form of pgm_gsi_print() + * + * returns number of bytes written to buffer on success, returns -1 on + * invalid parameters. + */ + +int +pgm_gsi_print_r ( + const pgm_gsi_t* restrict gsi, + char* restrict buf, + const size_t bufsize + ) +{ + const uint8_t* restrict src = (const uint8_t* restrict)gsi; + + pgm_return_val_if_fail (NULL != gsi, -1); + pgm_return_val_if_fail (NULL != buf, -1); + pgm_return_val_if_fail (bufsize > 0, -1); + +#ifdef _MSC_VER + return _snprintf_s (buf, bufsize, _TRUNCATE, "%i.%i.%i.%i.%i.%i", + src[0], src[1], src[2], src[3], src[4], src[5]); +#else + return snprintf (buf, bufsize, "%i.%i.%i.%i.%i.%i", + src[0], src[1], src[2], src[3], src[4], src[5]); +#endif +} + +/* transform GSI to ASCII string form. + * + * on success, returns pointer to ASCII string. on error, returns NULL. + */ + +char* +pgm_gsi_print ( + const pgm_gsi_t* gsi + ) +{ + static char buf[PGM_GSISTRLEN]; + + pgm_return_val_if_fail (NULL != gsi, NULL); + + pgm_gsi_print_r (gsi, buf, sizeof(buf)); + return buf; +} + +/* compare two global session identifier GSI values and return TRUE if they are equal + */ + +bool +pgm_gsi_equal ( + const void* restrict p1, + const void* restrict p2 + ) +{ + const union { + pgm_gsi_t gsi; + uint16_t s[3]; + } *u1 = p1, *u2 = p2; + +/* pre-conditions */ + pgm_assert (NULL != p1); + pgm_assert (NULL != p2); + + return (u1->s[0] == u2->s[0] && u1->s[1] == u2->s[1] && u1->s[2] == u2->s[2]); +} + +/* eof */ |