X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fpeerinfo-tool%2Fgnunet-peerinfo.c;h=0cb434d8913ff16be8f516ff120fc9d99df2b0e9;hb=82e8f0e1cd800fe8de0251aa06463af88435637f;hp=22df4f7a1dbd6466700b5ce115bf1ba45061b03d;hpb=d95cb5451bf787605502ee416f0bfb6b006083ad;p=oweals%2Fgnunet.git diff --git a/src/peerinfo-tool/gnunet-peerinfo.c b/src/peerinfo-tool/gnunet-peerinfo.c index 22df4f7a1..0cb434d89 100644 --- a/src/peerinfo-tool/gnunet-peerinfo.c +++ b/src/peerinfo-tool/gnunet-peerinfo.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2001, 2002, 2003, 2004, 2006, 2009, 2010 Christian Grothoff (and other contributing authors) + (C) 2001-2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -27,64 +27,183 @@ #include "gnunet_crypto_lib.h" #include "gnunet_configuration_lib.h" #include "gnunet_getopt_lib.h" -#include "gnunet_peerinfo_service.h" -#include "gnunet_transport_service.h" #include "gnunet_program_lib.h" -#include "gnunet_transport_plugin.h" -#include "../transport/gnunet-service-transport_plugins.h" +#include "gnunet_hello_lib.h" +#include "gnunet_transport_service.h" +#include "gnunet_peerinfo_service.h" +#include "gnunet-peerinfo_plugins.h" + +/** + * How long until we time out during peerinfo iterations? + */ +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) + +/** + * Structure we use to collect printable address information. + */ +struct PrintContext; + +/** + * Record we keep for each printable address. + */ +struct AddressRecord +{ + /** + * Current address-to-string context (if active, otherwise NULL). + */ + struct GNUNET_TRANSPORT_AddressToStringContext *atsc; + + /** + * Printable address. + */ + char *result; + + /** + * Print context this address record belongs to. + */ + struct PrintContext *pc; +}; + + +/** + * Structure we use to collect printable address information. + */ +struct PrintContext +{ + + /** + * Kept in DLL. + */ + struct PrintContext *next; + + /** + * Kept in DLL. + */ + struct PrintContext *prev; + + /** + * Identity of the peer. + */ + struct GNUNET_PeerIdentity peer; + + /** + * List of printable addresses. + */ + struct AddressRecord *address_list; + + /** + * Number of completed addresses in 'address_list'. + */ + unsigned int num_addresses; + + /** + * Number of addresses allocated in 'address_list'. + */ + unsigned int address_list_size; + + /** + * Current offset in 'address_list' (counted down). + */ + unsigned int off; + +}; + +/** + * Option '-n' + */ static int no_resolve; +/** + * Option '-q' + */ static int be_quiet; +/** + * Option '-s' + */ static int get_self; +/** + * Option + */ static int get_uri; +/** + * Option '-i' + */ +static int get_info; + +/** + * Option + */ static char *put_uri; +/** + * Handle to peerinfo service. + */ static struct GNUNET_PEERINFO_Handle *peerinfo; /** * Configuration handle. */ -const struct GNUNET_CONFIGURATION_Handle *GST_cfg; +static const struct GNUNET_CONFIGURATION_Handle *cfg; /** - * Statistics handle. + * Main state machine task (if active). */ -struct GNUNET_STATISTICS_Handle *GST_stats; +static GNUNET_SCHEDULER_TaskIdentifier tt; /** - * Configuration handle. + * Current iterator context (if active, otherwise NULL). */ -struct GNUNET_PeerIdentity GST_my_identity; +static struct GNUNET_PEERINFO_IteratorContext *pic; -struct GNUNET_MessageHeader *our_hello = NULL; +/** + * My peer identity. + */ +static struct GNUNET_PeerIdentity my_peer_identity; -static const struct GNUNET_CONFIGURATION_Handle *cfg; +/** + * My public key. + */ +static struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded my_public_key; -struct PrintContext -{ - struct GNUNET_PeerIdentity peer; - char **address_list; - unsigned int num_addresses; - uint32_t off; - char *uri; - size_t uri_len; -}; +/** + * Head of list of print contexts. + */ +static struct PrintContext *pc_head; /** - * Obtain this peers HELLO message. + * Tail of list of print contexts. + */ +static struct PrintContext *pc_tail; + +/** + * Handle to current 'GNUNET_PEERINFO_add_peer' operation. + */ +static struct GNUNET_PEERINFO_AddContext *ac; + + +/** + * Main state machine that goes over all options and + * runs the next requested function. * - * @return our HELLO message + * @param cls unused + * @param tc unused */ -const struct GNUNET_MessageHeader * -GST_hello_get () -{ - return (struct GNUNET_MessageHeader *) our_hello; -} +static void +state_machine (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); + +/* ********************* 'get_info' ******************* */ + +/** + * Print the collected address information to the console and free 'pc'. + * + * @param pc printing context + */ static void dump_pc (struct PrintContext *pc) { @@ -92,18 +211,31 @@ dump_pc (struct PrintContext *pc) unsigned int i; GNUNET_CRYPTO_hash_to_enc (&pc->peer.hashPubKey, &enc); - printf (_("Peer `%s'\n"), (const char *) &enc); + printf (_("Peer `%s'\n"), + (const char *) &enc); for (i = 0; i < pc->num_addresses; i++) { - printf ("\t%s\n", pc->address_list[i]); - GNUNET_free (pc->address_list[i]); + if (NULL != pc->address_list[i].result) + { + printf ("\t%s\n", pc->address_list[i].result); + GNUNET_free (pc->address_list[i].result); + } } printf ("\n"); - GNUNET_array_grow (pc->address_list, pc->num_addresses, 0); + GNUNET_free_non_null (pc->address_list); + GNUNET_CONTAINER_DLL_remove (pc_head, + pc_tail, + pc); GNUNET_free (pc); + if ( (NULL == pc_head) && + (NULL == pic) ) + tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); } +/* ************************* list all known addresses **************** */ + + /** * Function to call with a human-readable format of an address * @@ -113,24 +245,26 @@ dump_pc (struct PrintContext *pc) static void process_resolved_address (void *cls, const char *address) { - struct PrintContext *pc = cls; + struct AddressRecord * ar = cls; + struct PrintContext *pc = ar->pc; - if (address == NULL) + if (NULL != address) { - pc->off--; - if (pc->off == 0) - dump_pc (pc); + if (NULL == ar->result) + ar->result = GNUNET_strdup (address); return; } - GNUNET_array_append (pc->address_list, pc->num_addresses, - GNUNET_strdup (address)); + ar->atsc = NULL; + pc->num_addresses++; + if (pc->num_addresses == pc->address_list_size) + dump_pc (pc); } /** - * Iterator callback to go over all addresses. + * Iterator callback to go over all addresses and count them. * - * @param cls closure + * @param cls 'struct PrintContext' with 'off' to increment * @param address the address * @param expiration expiration time * @return GNUNET_OK to keep the address and continue @@ -159,19 +293,27 @@ print_address (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { struct PrintContext *pc = cls; - - GNUNET_TRANSPORT_address_to_string (cfg, address, no_resolve, - GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 10), - &process_resolved_address, pc); + struct AddressRecord *ar; + + GNUNET_assert (0 < pc->off); + ar = &pc->address_list[--pc->off]; + ar->pc = pc; + ar->atsc = GNUNET_TRANSPORT_address_to_string (cfg, address, no_resolve, + GNUNET_TIME_relative_multiply + (GNUNET_TIME_UNIT_SECONDS, 10), + &process_resolved_address, ar); return GNUNET_OK; } /** * Print information about the peer. - * Currently prints the GNUNET_PeerIdentity and the IP. - * Could of course do more (e.g. resolve via DNS). + * Currently prints the GNUNET_PeerIdentity and the transport address. + * + * @param cls the 'struct PrintContext' + * @param peer identity of the peer + * @param hello addresses of the peer + * @param err_msg error message */ static void print_peer_info (void *cls, const struct GNUNET_PeerIdentity *peer, @@ -180,333 +322,193 @@ print_peer_info (void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_CRYPTO_HashAsciiEncoded enc; struct PrintContext *pc; - if (peer == NULL) + if (NULL == peer) { - if (err_msg != NULL) - FPRINTF (stderr, "%s", _("Error in communication with PEERINFO service\n")); - GNUNET_PEERINFO_disconnect (peerinfo); - GST_plugins_unload (); - GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO); + pic = NULL; /* end of iteration */ + if (NULL != err_msg) + { + FPRINTF (stderr, + _("Error in communication with PEERINFO service: %s\n"), + err_msg); + } + if (NULL == pc_head) + tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); return; } - if ((be_quiet) || (NULL == hello)) + if ((GNUNET_YES == be_quiet) || (NULL == hello)) { GNUNET_CRYPTO_hash_to_enc (&peer->hashPubKey, &enc); printf ("%s\n", (const char *) &enc); return; } pc = GNUNET_malloc (sizeof (struct PrintContext)); + GNUNET_CONTAINER_DLL_insert (pc_head, + pc_tail, + pc); pc->peer = *peer; - GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &count_address, pc); + GNUNET_HELLO_iterate_addresses (hello, + GNUNET_NO, + &count_address, + pc); if (0 == pc->off) { dump_pc (pc); return; } - GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &print_address, pc); + pc->address_list_size = pc->off; + pc->address_list = GNUNET_malloc (sizeof (struct AddressRecord) * pc->off); + GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, + &print_address, pc); } -static int -compose_uri (void *cls, const struct GNUNET_HELLO_Address *address, - struct GNUNET_TIME_Absolute expiration) -{ - struct PrintContext *pc = cls; - struct GNUNET_TRANSPORT_PluginFunctions *papi; - static const char *addr; - papi = GST_plugins_find (address->transport_name); - if (papi == NULL) - { - /* Not an error - we might just not have the right plugin. */ - return GNUNET_OK; - } +/* ************************* GET URI ************************** */ - addr = papi->address_to_string (papi->cls, address->address, address->address_length); - if (addr != NULL) - { - ssize_t l = strlen (addr); - if (l > 0) - { - struct tm *t; - time_t seconds; - int s; - seconds = expiration.abs_value / 1000; - t = gmtime(&seconds); - pc->uri = GNUNET_realloc (pc->uri, pc->uri_len + 1 + 14 + 1 + strlen (address->transport_name) + 1 + l + 1 /* 0 */); - s = sprintf (&pc->uri[pc->uri_len], "!%04u%02u%02u%02u%02u%02u!%s!%s", - t->tm_year, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, - address->transport_name, addr); - if (s > 0) - pc->uri_len += s; - } - } - return GNUNET_OK; -} /** - * Print information about the peer. + * Print URI of the peer. + * + * @param cls the 'struct GetUriContext' + * @param peer identity of the peer (unused) + * @param hello addresses of the peer + * @param err_msg error message */ static void print_my_uri (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_HELLO_Message *hello, const char *err_msg) + const struct GNUNET_HELLO_Message *hello, + const char *err_msg) { - struct GNUNET_CRYPTO_HashAsciiEncoded enc; - struct PrintContext *pc = cls; - if (peer == NULL) { + pic = NULL; if (err_msg != NULL) - FPRINTF (stderr, "%s", _("Error in communication with PEERINFO service\n")); - GNUNET_PEERINFO_disconnect (peerinfo); - GST_plugins_unload (); - GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO); + FPRINTF (stderr, + _("Error in communication with PEERINFO service: %s\n"), + err_msg); + tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); return; } - if ((be_quiet) || (NULL == hello)) - { - GNUNET_CRYPTO_hash_to_enc (&peer->hashPubKey, &enc); - printf ("%s\n", (const char *) &enc); - if (be_quiet && get_uri != GNUNET_YES) - return; - } - pc->peer = *peer; - GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &count_address, pc); - GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &compose_uri, pc); - printf ("%s\n", pc->uri); - GNUNET_free (pc->uri); - GNUNET_free (pc); -} -struct GNUNET_PEERINFO_HelloAddressParsingContext -{ - char *tmp; - char *pos; - size_t tmp_len; -}; + if (NULL == hello) + return; -static size_t -add_addr_to_hello (void *cls, size_t max, void *buffer) -{ - struct tm expiration_time; - char buf[5]; - long l; - time_t expiration_seconds; - struct GNUNET_TIME_Absolute expire; - - struct GNUNET_PEERINFO_HelloAddressParsingContext *ctx = cls; - char *exp1, *exp2; - struct GNUNET_TRANSPORT_PluginFunctions *papi; - void *addr; - size_t addr_len; - - /* End of string */ - if (ctx->pos - ctx->tmp == ctx->tmp_len) - return 0; - - /* Parsed past the end of string, OR wrong format */ - if ((ctx->pos - ctx->tmp > ctx->tmp_len) || ctx->pos[0] != '!') - { - GNUNET_break (0); - return 0; + char *uri = GNUNET_HELLO_compose_uri(hello, &GPI_plugins_find); + if (NULL != uri) { + printf ("%s\n", (const char *) uri); + GNUNET_free (uri); } +} - /* Not enough bytes (3 for three '!', 14 for expiration date, and - * at least 1 for type and 1 for address (1-byte long address is a joke, - * but it is not completely unrealistic. Zero-length address is. - */ - if (ctx->tmp_len - (ctx->pos - ctx->tmp) < 1 /*!*/ * 3 + 14 + /* at least */ 2) - { - GNUNET_break (0); - return 0; - } - /* Go past the first '!', now we're on expiration date */ - ctx->pos += 1; - /* Its length is known, so check for the next '!' right away */ - if (ctx->pos[14] != '!') - { - GNUNET_break (0); - return 0; - } - memset (&expiration_time, 0, sizeof (struct tm)); +/* ************************* import HELLO by URI ********************* */ - /* This is FAR more strict than strptime(ctx->pos, "%Y%m%d%H%M%S", ...); */ - /* FIXME: make it a separate function, since expiration is specified to every address */ -#define GETNDIGITS(n,cond) \ - strncpy (buf, &ctx->pos[0], n); \ - buf[n] = '\0'; \ - errno = 0; \ - l = strtol (buf, NULL, 10); \ - if (errno != 0 || cond) \ - { \ - GNUNET_break (0); \ - return 0; \ - } \ - ctx->pos += n; - GETNDIGITS (4, l < 1900) - expiration_time.tm_year = l - 1900; +/** + * Continuation called from 'GNUNET_PEERINFO_add_peer' + * + * @param cls closure, NULL + * @param emsg error message, NULL on success + */ +static void +add_continuation (void *cls, + const char *emsg) +{ + ac = NULL; + if (NULL != emsg) + fprintf (stderr, + _("Failure adding HELLO: %s\n"), + emsg); + tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); +} - GETNDIGITS (2, l < 1 || l > 12) - expiration_time.tm_mon = l; - GETNDIGITS (2, l < 1 || l > 31) - expiration_time.tm_mday = l; +/** + * Parse the PUT URI given at the command line and add it to our peerinfo + * database. + * + * @param put_uri URI string to parse + * @return GNUNET_OK on success, GNUNET_SYSERR if the URI was invalid, GNUNET_NO on other errors + */ +static int +parse_hello_uri (const char *put_uri) +{ + struct GNUNET_HELLO_Message *hello = NULL; - GETNDIGITS (2, l < 0 || l > 23) - expiration_time.tm_hour = l; + int ret = GNUNET_HELLO_parse_uri(put_uri, &my_public_key, &hello, &GPI_plugins_find); - GETNDIGITS (2, l < 0 || l > 59) - expiration_time.tm_min = l; + if (NULL != hello) { + /* WARNING: this adds the address from URI WITHOUT verification! */ + if (GNUNET_OK == ret) + ac = GNUNET_PEERINFO_add_peer (peerinfo, hello, &add_continuation, NULL); + else + tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); + GNUNET_free (hello); + } - /* 60 - with a leap second */ - GETNDIGITS (2, l < 0 || l > 60) - expiration_time.tm_sec = l; + /* wait 1s to give peerinfo operation a chance to succeed */ + /* FIXME: current peerinfo API sucks to require this; not to mention + that we get no feedback to determine if the operation actually succeeded */ + return ret; +} - expiration_time.tm_isdst = -1; -#undef GETNDIGITS +/* ************************ Main state machine ********************* */ - expiration_seconds = mktime (&expiration_time); - if (expiration_seconds == (time_t) -1) - { - GNUNET_break (0); - return 0; - } - expire.abs_value = expiration_seconds * 1000; - /* Now we're at '!', advance to the transport type */ - ctx->pos += 1; +/** + * Main state machine that goes over all options and + * runs the next requested function. + * + * @param cls unused + * @param tc scheduler context + */ +static void +shutdown_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct PrintContext *pc; + struct AddressRecord *ar; + unsigned int i; - /* Find the next '!' that separates transport type from - * the address - */ - exp1 = strstr (ctx->pos, "!"); - if (exp1 == NULL) + if (NULL != ac) { - GNUNET_break (0); - return 0; + GNUNET_PEERINFO_add_peer_cancel (ac); + ac = NULL; } - /* We need it 0-terminated */ - exp1[0] = '\0'; - /* Find the '!' that separates address from the next record. - * It might not be there, if this is the last record. - */ - exp2 = strstr (&exp1[1], "!"); - if (exp2 == NULL) - exp2 = &ctx->tmp[ctx->tmp_len]; - - papi = GST_plugins_find (ctx->pos); - if (papi == NULL) + if (GNUNET_SCHEDULER_NO_TASK != tt) { - /* Not an error - we might just not have the right plugin. - * Skip this part, advance to the next one and recurse. - * But only if this is not the end of string. - */ - ctx->pos = exp2 + 1; - if (ctx->pos - ctx->tmp >= ctx->tmp_len) - return 0; - return add_addr_to_hello (cls, max, buffer); + GNUNET_SCHEDULER_cancel (tt); + tt = GNUNET_SCHEDULER_NO_TASK; } - - if (GNUNET_OK == papi->string_to_address (papi->cls, &exp1[1], exp2 - &exp1[1], &addr, &addr_len)) + if (NULL != pic) { - struct GNUNET_HELLO_Address address; - int ret; - - /* address.peer is unset - not used by add_address() */ - address.address_length = addr_len; - address.address = addr; - address.transport_name = ctx->pos; - ret = GNUNET_HELLO_add_address (&address, expire, buffer, max); - GNUNET_free (addr); - ctx->pos = exp2; - return ret; + GNUNET_PEERINFO_iterate_cancel (pic); + pic = NULL; } - return 0; -} - -void -parse_hello (const struct GNUNET_CONFIGURATION_Handle *c, - const char *put_uri) -{ - int r; - char *scheme_part = NULL; - char *path_part = NULL; - char *exc; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub; - int std_result; - struct GNUNET_HELLO_Message *hello; - struct GNUNET_PEERINFO_HelloAddressParsingContext ctx; - - r = GNUNET_STRINGS_parse_uri (put_uri, &scheme_part, (const char **) &path_part); - if (r == GNUNET_NO) - return; - if (scheme_part == NULL || strcmp (scheme_part, "gnunet://") != 0) + while (NULL != (pc = pc_head)) { - GNUNET_free_non_null (scheme_part); - return; + GNUNET_CONTAINER_DLL_remove (pc_head, + pc_tail, + pc); + for (i=0;iaddress_list_size;i++) + { + ar = &pc->address_list[i]; + GNUNET_free_non_null (ar->result); + if (NULL != ar->atsc) + { + GNUNET_TRANSPORT_address_to_string_cancel (ar->atsc); + ar->atsc = NULL; + } + } + GNUNET_free_non_null (pc->address_list); + GNUNET_free (pc); } - GNUNET_free (scheme_part); - - if (strncmp (path_part, "hello/", 6) != 0) - return; - - path_part = &path_part[6]; - ctx.tmp = GNUNET_strdup (path_part); - ctx.tmp_len = strlen (path_part); - exc = strstr (ctx.tmp, "!"); - if (exc == NULL) - exc = ctx.pos + ctx.tmp_len; - ctx.pos = exc; - - std_result = GNUNET_STRINGS_string_to_data (ctx.tmp, exc - ctx.tmp, - (unsigned char *) &pub, sizeof (pub)); - if (std_result != GNUNET_OK) + GPI_plugins_unload (); + if (NULL != peerinfo) { - GNUNET_free (ctx.tmp); - return; + GNUNET_PEERINFO_disconnect (peerinfo); + peerinfo = NULL; } - - hello = GNUNET_HELLO_create (&pub, add_addr_to_hello, &ctx); - GNUNET_free (ctx.tmp); - - /* WARNING: this adds the address from URI WITHOUT verification! */ - GNUNET_PEERINFO_add_peer (peerinfo, hello); -} - -static struct GNUNET_TIME_Relative -receive_stub (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *ats, uint32_t ats_count, - struct Session *session, const char *sender_address, - uint16_t sender_address_len) -{ - struct GNUNET_TIME_Relative t; - t.rel_value = 0; - return t; -} - -static void -address_notification_stub (void *cls, int add_remove, - const void *addr, size_t addrlen) -{ -} - -static void -session_end_stub (void *cls, const struct GNUNET_PeerIdentity *peer, - struct Session * session) -{ -} - -static const struct GNUNET_ATS_Information -address_to_type_stub (void *cls, const struct sockaddr *addr, - size_t addrlen) -{ - struct GNUNET_ATS_Information t; - t.type = 0; - t.value = 0; - return t; } @@ -522,95 +524,115 @@ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { - struct GNUNET_CRYPTO_RsaPrivateKey *priv; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub; - struct GNUNET_PeerIdentity pid; - struct GNUNET_CRYPTO_HashAsciiEncoded enc; + struct GNUNET_CRYPTO_EccPrivateKey *priv; char *fn; cfg = c; - if (args[0] != NULL) + if ( (NULL != args[0]) && + (NULL == put_uri) && + (args[0] == strcasestr (args[0], "gnunet://hello/")) ) { - FPRINTF (stderr, _("Invalid command line argument `%s'\n"), args[0]); - return; + put_uri = GNUNET_strdup (args[0]); + args++; } - if (put_uri != NULL && get_uri == GNUNET_YES) + if (NULL != args[0]) { - FPRINTF (stderr, "%s", _("--put-uri and --get-uri are mutually exclusive\n")); + FPRINTF (stderr, + _("Invalid command line argument `%s'\n"), + args[0]); return; } - if (put_uri != NULL || get_uri == GNUNET_YES || get_self != GNUNET_YES) + if (NULL == (peerinfo = GNUNET_PEERINFO_connect (cfg))) { - peerinfo = GNUNET_PEERINFO_connect (cfg); - if (peerinfo == NULL) - { - FPRINTF (stderr, "%s", _("Could not access PEERINFO service. Exiting.\n")); - return; - } - GST_cfg = c; - GST_stats = GNUNET_STATISTICS_create ("transport", c); - /* FIXME: shouldn't we free GST_stats somewhere? */ - GST_plugins_load (receive_stub, address_notification_stub, - session_end_stub, address_to_type_stub); - } - if (put_uri != NULL) - { - parse_hello (c, put_uri); - GST_plugins_unload (); - GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO); + FPRINTF (stderr, "%s", _("Could not access PEERINFO service. Exiting.\n")); return; } - if (get_self != GNUNET_YES) - { - GNUNET_PEERINFO_iterate (peerinfo, NULL, - GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 5), &print_peer_info, - NULL); - } - else + if ( (GNUNET_YES == get_self) || (GNUNET_YES == get_uri) ) { + /* load private key */ if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY", - &fn)) + GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", + &fn)) { FPRINTF (stderr, _("Could not find option `%s:%s' in configuration.\n"), - "GNUNETD", "HOSTKEYFILE"); + "GNUNETD", "HOSTKEYFILE"); return; } - priv = GNUNET_CRYPTO_rsa_key_create_from_file (fn); - if (priv == NULL) + if (NULL == (priv = GNUNET_CRYPTO_ecc_key_create_from_file (fn))) { FPRINTF (stderr, _("Loading hostkey from `%s' failed.\n"), fn); GNUNET_free (fn); return; } GNUNET_free (fn); - GNUNET_CRYPTO_rsa_key_get_public (priv, &pub); - GNUNET_CRYPTO_rsa_key_free (priv); - GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey); - GNUNET_CRYPTO_hash_to_enc (&pid.hashPubKey, &enc); + GNUNET_CRYPTO_ecc_key_get_public (priv, &my_public_key); + GNUNET_CRYPTO_ecc_key_free (priv); + GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), &my_peer_identity.hashPubKey); + } + + tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, + &shutdown_task, + NULL); +} + + +/** + * Main state machine that goes over all options and + * runs the next requested function. + * + * @param cls unused + * @param tc scheduler context + */ +static void +state_machine (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + tt = GNUNET_SCHEDULER_NO_TASK; + + if (NULL != put_uri) + { + GPI_plugins_load (cfg); + if (GNUNET_SYSERR == parse_hello_uri (put_uri)) + { + fprintf (stderr, + _("Invalid URI `%s'\n"), + put_uri); + GNUNET_SCHEDULER_shutdown (); + } + GNUNET_free (put_uri); + put_uri = NULL; + return; + } + if (GNUNET_YES == get_info) + { + get_info = GNUNET_NO; + GPI_plugins_load (cfg); + pic = GNUNET_PEERINFO_iterate (peerinfo, NULL, + TIMEOUT, + &print_peer_info, NULL); + return; + } + if (GNUNET_YES == get_self) + { + struct GNUNET_CRYPTO_HashAsciiEncoded enc; + + get_self = GNUNET_NO; + GNUNET_CRYPTO_hash_to_enc (&my_peer_identity.hashPubKey, &enc); if (be_quiet) printf ("%s\n", (char *) &enc); else printf (_("I am peer `%s'.\n"), (const char *) &enc); - if (get_uri == GNUNET_YES) - { - struct PrintContext *pc; - char *pkey; - ssize_t l, pl; - pc = GNUNET_malloc (sizeof (struct PrintContext)); - pkey = GNUNET_CRYPTO_rsa_public_key_to_string (&pub); - pl = strlen ("gnunet://hello/"); - l = strlen (pkey) + pl; - pc->uri = GNUNET_malloc (l + 1); - strcpy (pc->uri, "gnunet://hello/"); - strcpy (&pc->uri[pl], pkey); - pc->uri_len = l; - GNUNET_PEERINFO_iterate (peerinfo, &pid, - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), - print_my_uri, pc); - } } + if (GNUNET_YES == get_uri) + { + GPI_plugins_load (cfg); + pic = GNUNET_PEERINFO_iterate (peerinfo, &my_peer_identity, + TIMEOUT, &print_my_uri, NULL); + get_uri = GNUNET_NO; + return; + } + GNUNET_SCHEDULER_shutdown (); } @@ -634,6 +656,9 @@ main (int argc, char *const *argv) {'s', "self", NULL, gettext_noop ("output our own identity only"), 0, &GNUNET_GETOPT_set_one, &get_self}, + {'i', "info", NULL, + gettext_noop ("list all known peers"), + 0, &GNUNET_GETOPT_set_one, &get_info}, {'g', "get-hello", NULL, gettext_noop ("also output HELLO uri(s)"), 0, &GNUNET_GETOPT_set_one, &get_uri}, @@ -642,10 +667,17 @@ main (int argc, char *const *argv) 1, &GNUNET_GETOPT_set_string, &put_uri}, GNUNET_GETOPT_OPTION_END }; - return (GNUNET_OK == - GNUNET_PROGRAM_run (argc, argv, "gnunet-peerinfo", - gettext_noop ("Print information about peers."), - options, &run, NULL)) ? 0 : 1; + int ret; + + if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) + return 2; + + ret = (GNUNET_OK == + GNUNET_PROGRAM_run (argc, argv, "gnunet-peerinfo", + gettext_noop ("Print information about peers."), + options, &run, NULL)) ? 0 : 1; + GNUNET_free ((void*) argv); + return ret; } /* end of gnunet-peerinfo.c */