diff options
Diffstat (limited to 'src/gns/gns_api.c')
-rw-r--r-- | src/gns/gns_api.c | 925 |
1 files changed, 576 insertions, 349 deletions
diff --git a/src/gns/gns_api.c b/src/gns/gns_api.c index a92280f..1e3cb01 100644 --- a/src/gns/gns_api.c +++ b/src/gns/gns_api.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009, 2010 Christian Grothoff (and other contributing authors) + (C) 2009, 2010, 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 @@ -17,14 +17,12 @@ Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - /** - * * @file gns/gns_api.c * @brief library to access the GNS service * @author Martin Schanzenbach + * @author Christian Grothoff */ - #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" @@ -35,47 +33,119 @@ #include "gns.h" #include "gnunet_gns_service.h" -/* TODO into gnunet_protocols */ -#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP 23 -#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT 24 -#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN 25 -#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT 26 -#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH 27 -#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT 28 /** - * A QueueEntry. + * Handle to a lookup request */ -struct GNUNET_GNS_QueueEntry +struct GNUNET_GNS_LookupRequest { + /** * DLL */ - struct GNUNET_GNS_QueueEntry *next; + struct GNUNET_GNS_LookupRequest *next; /** * DLL */ - struct GNUNET_GNS_QueueEntry *prev; + struct GNUNET_GNS_LookupRequest *prev; + + /** + * handle to gns + */ + struct GNUNET_GNS_Handle *gns_handle; + + /** + * processor to call on lookup result + */ + GNUNET_GNS_LookupResultProcessor lookup_proc; - /* request id */ + /** + * processor closure + */ + void *proc_cls; + + /** + * request id + */ uint32_t r_id; + +}; + + +/** + * Handle to a shorten request + */ +struct GNUNET_GNS_ShortenRequest +{ + /** + * DLL + */ + struct GNUNET_GNS_ShortenRequest *next; - /* handle to gns */ + /** + * DLL + */ + struct GNUNET_GNS_ShortenRequest *prev; + + /** + * handle to gns + */ struct GNUNET_GNS_Handle *gns_handle; - /* processor to call on shorten result */ + /** + * processor to call on shorten result + */ GNUNET_GNS_ShortenResultProcessor shorten_proc; - /* processor to call on lookup result */ - GNUNET_GNS_LookupResultProcessor lookup_proc; + /** + * processor closure + */ + void *proc_cls; - /* processor to call on authority lookup result */ + /** + * request id + */ + uint32_t r_id; + +}; + + +/** + * Handle to GetAuthorityRequest + */ +struct GNUNET_GNS_GetAuthRequest +{ + /** + * DLL + */ + struct GNUNET_GNS_GetAuthRequest *next; + + /** + * DLL + */ + struct GNUNET_GNS_GetAuthRequest *prev; + + /** + * handle to gns + */ + struct GNUNET_GNS_Handle *gns_handle; + + /** + * processor to call on authority lookup result + */ GNUNET_GNS_GetAuthResultProcessor auth_proc; - /* processor closure */ + /** + * processor closure + */ void *proc_cls; + /** + * request id + */ + uint32_t r_id; + }; @@ -99,6 +169,18 @@ struct PendingMessage */ size_t size; + /** + * request id + */ + uint32_t r_id; + + /** + * This message has been transmitted. GNUNET_NO if the message is + * in the "pending" DLL, GNUNET_YES if it has been transmitted to + * the service via the current client connection. + */ + int transmitted; + }; @@ -123,8 +205,6 @@ struct GNUNET_GNS_Handle */ struct GNUNET_CLIENT_TransmitHandle *th; - uint32_t r_id; - /** * Head of linked list of shorten messages we would like to transmit. */ @@ -138,49 +218,56 @@ struct GNUNET_GNS_Handle /** * Head of linked list of shorten messages we would like to transmit. */ - struct GNUNET_GNS_QueueEntry *shorten_head; + struct GNUNET_GNS_ShortenRequest *shorten_head; /** * Tail of linked list of shorten messages we would like to transmit. */ - struct GNUNET_GNS_QueueEntry *shorten_tail; + struct GNUNET_GNS_ShortenRequest *shorten_tail; /** * Head of linked list of lookup messages we would like to transmit. */ - struct GNUNET_GNS_QueueEntry *lookup_head; + struct GNUNET_GNS_LookupRequest *lookup_head; /** * Tail of linked list of lookup messages we would like to transmit. */ - struct GNUNET_GNS_QueueEntry *lookup_tail; + struct GNUNET_GNS_LookupRequest *lookup_tail; /** * Head of linked list of authority lookup messages we would like to transmit. */ - struct GNUNET_GNS_QueueEntry *get_auth_head; + struct GNUNET_GNS_GetAuthRequest *get_auth_head; /** * Tail of linked list of authority lookup messages we would like to transmit. */ - struct GNUNET_GNS_QueueEntry *get_auth_tail; + struct GNUNET_GNS_GetAuthRequest *get_auth_tail; /** * Reconnect task */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; + + /** + * How long do we wait until we try to reconnect? + */ + struct GNUNET_TIME_Relative reconnect_backoff; /** + * Request Id generator. Incremented by one for each request. + */ + uint32_t r_id_gen; + + /** * Did we start our receive loop yet? */ int in_receive; - /** - * Reconnect necessary - */ - int reconnect; }; + /** * Try to send messages from list of messages to send * @param handle GNS_Handle @@ -192,18 +279,20 @@ process_pending_messages (struct GNUNET_GNS_Handle *handle); /** * Reconnect to GNS service. * - * @param h the handle to the namestore service + * @param handle the handle to the GNS service */ static void -reconnect (struct GNUNET_GNS_Handle *h) +reconnect (struct GNUNET_GNS_Handle *handle) { - GNUNET_assert (NULL == h->client); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Trying to connect to GNS...\n"); - h->client = GNUNET_CLIENT_connect ("gns", h->cfg); - GNUNET_assert (NULL != h->client); + GNUNET_assert (NULL == handle->client); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Trying to connect to GNS\n"); + handle->client = GNUNET_CLIENT_connect ("gns", handle->cfg); + GNUNET_assert (NULL != handle->client); + process_pending_messages (handle); } + /** * Reconnect to GNS * @@ -213,35 +302,78 @@ reconnect (struct GNUNET_GNS_Handle *h) static void reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct GNUNET_GNS_Handle *h = cls; + struct GNUNET_GNS_Handle *handle = cls; - h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; - reconnect (h); + handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; + reconnect (handle); } /** * Disconnect from service and then reconnect. * - * @param h our handle + * @param handle our handle */ static void -force_reconnect (struct GNUNET_GNS_Handle *h) +force_reconnect (struct GNUNET_GNS_Handle *handle) { - h->reconnect = GNUNET_NO; - GNUNET_CLIENT_disconnect (h->client); - h->client = NULL; - h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, + struct GNUNET_GNS_ShortenRequest *st; + struct GNUNET_GNS_LookupRequest *lh; + struct GNUNET_GNS_GetAuthRequest *ga; + struct PendingMessage *p; + + GNUNET_CLIENT_disconnect (handle->client); + handle->client = NULL; + handle->in_receive = GNUNET_NO; + for (st = handle->shorten_head; NULL != st; st = st->next) + { + p = (struct PendingMessage *) &st[1]; + if (GNUNET_NO == p->transmitted) + continue; + p->transmitted = GNUNET_NO; + GNUNET_CONTAINER_DLL_insert (handle->pending_head, + handle->pending_tail, + p); + } + for (lh = handle->lookup_head; NULL != lh; lh = lh->next) + { + p = (struct PendingMessage *) &lh[1]; + if (GNUNET_NO == p->transmitted) + continue; + p->transmitted = GNUNET_NO; + GNUNET_CONTAINER_DLL_insert (handle->pending_head, + handle->pending_tail, + p); + } + for (ga = handle->get_auth_head; NULL != ga; ga = ga->next) + { + p = (struct PendingMessage *) &ga[1]; + if (GNUNET_NO == p->transmitted) + continue; + p->transmitted = GNUNET_NO; + GNUNET_CONTAINER_DLL_insert (handle->pending_head, + handle->pending_tail, + p); + } + handle->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff); + handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff, &reconnect_task, - h); + handle); } + /** * Transmit the next pending message, called by notify_transmit_ready + * + * @param cls the closure + * @param size size of pending data + * @param buf buffer with pending data + * @return size data transmitted */ static size_t transmit_pending (void *cls, size_t size, void *buf); + /** * Handler for messages received from the GNS service * @@ -251,93 +383,92 @@ transmit_pending (void *cls, size_t size, void *buf); static void process_message (void *cls, const struct GNUNET_MessageHeader *msg); + /** * Try to send messages from list of messages to send + * + * @param handle the GNS handle */ static void process_pending_messages (struct GNUNET_GNS_Handle *handle) { - struct PendingMessage *p; + struct PendingMessage *p = handle->pending_head; - if (handle->client == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "process_pending_messages called, but client is null\n"); - return; - } - - if (handle->th != NULL) - return; - - if (NULL == (p = handle->pending_head)) - return; - - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, - "Trying to transmit %d bytes...\n", p->size); + if (NULL == handle->client) + return; /* wait for reconnect */ + if (NULL != handle->th) + return; /* transmission request already pending */ + while ((NULL != p) && (p->transmitted == GNUNET_YES)) + p = p->next; + if (NULL == p) + return; /* no messages pending */ + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Trying to transmit %u bytes\n", + (unsigned int) p->size); handle->th = GNUNET_CLIENT_notify_transmit_ready (handle->client, p->size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_pending, handle); - if (NULL != handle->th) - return; - - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "notify_transmit_ready returned NULL!\n"); + GNUNET_break (NULL != handle->th); } /** * Transmit the next pending message, called by notify_transmit_ready + * + * @param cls the closure + * @param size size of pending data + * @param buf buffer with pending data + * @return size data transmitted */ static size_t transmit_pending (void *cls, size_t size, void *buf) { struct GNUNET_GNS_Handle *handle = cls; + char *cbuf = buf; struct PendingMessage *p; size_t tsize; - char *cbuf; handle->th = NULL; - - if ((size == 0) || (buf == NULL)) + if ((0 == size) || (NULL == buf)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmission to GNS service failed!\n"); - force_reconnect(handle); + "Transmission to GNS service failed!\n"); + force_reconnect (handle); return 0; - } - - tsize = 0; - cbuf = buf; - + } if (NULL == (p = handle->pending_head)) return 0; + tsize = 0; while ((NULL != (p = handle->pending_head)) && (p->size <= size)) { memcpy (&cbuf[tsize], &p[1], p->size); tsize += p->size; size -= p->size; - GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, p); + p->transmitted = GNUNET_YES; + GNUNET_CONTAINER_DLL_remove (handle->pending_head, + handle->pending_tail, + p); if (GNUNET_YES != handle->in_receive) { GNUNET_CLIENT_receive (handle->client, &process_message, handle, GNUNET_TIME_UNIT_FOREVER_REL); handle->in_receive = GNUNET_YES; } - GNUNET_free(p); } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending %d bytes\n", tsize); - - process_pending_messages(handle); + "Sending %u bytes\n", + (unsigned int) tsize); + process_pending_messages (handle); return tsize; } + /** * Process a given reply that might match the given * request. @@ -346,34 +477,43 @@ transmit_pending (void *cls, size_t size, void *buf) * @param msg the shorten msg received */ static void -process_shorten_reply (struct GNUNET_GNS_QueueEntry *qe, +process_shorten_reply (struct GNUNET_GNS_ShortenRequest *qe, const struct GNUNET_GNS_ClientShortenResultMessage *msg) { - struct GNUNET_GNS_Handle *h = qe->gns_handle; + struct GNUNET_GNS_Handle *handle = qe->gns_handle; + struct PendingMessage *p = (struct PendingMessage *)&qe[1]; const char *short_name; - - GNUNET_CONTAINER_DLL_remove(h->shorten_head, h->shorten_tail, qe); - - short_name = (char*)(&msg[1]); - - if (ntohs (((struct GNUNET_MessageHeader*)msg)->size) < - sizeof (struct GNUNET_GNS_ClientShortenResultMessage)) + size_t mlen; + + if (GNUNET_YES != p->transmitted) { + /* service send reply to query we never managed to send!? */ GNUNET_break (0); - force_reconnect (h); - GNUNET_free(qe); + force_reconnect (handle); return; } - + mlen = ntohs (msg->header.size); + if (ntohs (msg->header.size) == sizeof (struct GNUNET_GNS_ClientShortenResultMessage)) + { + /* service reports resolution failed */ + short_name = NULL; + } + else + { + short_name = (const char *) &msg[1]; + if ('\0' != short_name[mlen - sizeof (struct GNUNET_GNS_ClientShortenResultMessage) - 1]) + { + GNUNET_break (0); + force_reconnect (handle); + return; + } + } + GNUNET_CONTAINER_DLL_remove (handle->shorten_head, handle->shorten_tail, qe); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received shortened reply `%s' from GNS service\n", short_name); - - GNUNET_CLIENT_receive (h->client, &process_message, h, - GNUNET_TIME_UNIT_FOREVER_REL); - qe->shorten_proc(qe->proc_cls, short_name); - GNUNET_free(qe); - + qe->shorten_proc (qe->proc_cls, short_name); + GNUNET_free (qe); } @@ -385,35 +525,45 @@ process_shorten_reply (struct GNUNET_GNS_QueueEntry *qe, * @param msg the message to process */ static void -process_get_auth_reply (struct GNUNET_GNS_QueueEntry *qe, +process_get_auth_reply (struct GNUNET_GNS_GetAuthRequest *qe, const struct GNUNET_GNS_ClientGetAuthResultMessage *msg) { - struct GNUNET_GNS_Handle *h = qe->gns_handle; + struct GNUNET_GNS_Handle *handle = qe->gns_handle; + struct PendingMessage *p = (struct PendingMessage *)&qe[1]; const char *auth_name; + size_t mlen; - GNUNET_CONTAINER_DLL_remove(h->get_auth_head, h->get_auth_tail, qe); - - auth_name = (char*)(&msg[1]); - - if (ntohs (((struct GNUNET_MessageHeader*)msg)->size) < - sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage)) + if (GNUNET_YES != p->transmitted) { - GNUNET_free(qe); + /* service send reply to query we never managed to send!? */ GNUNET_break (0); - force_reconnect (h); + force_reconnect (handle); return; } - + mlen = ntohs (msg->header.size); + if (mlen == sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage)) + { + auth_name = NULL; + } + else + { + auth_name = (const char*) &msg[1]; + if ('\0' != auth_name[mlen - sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage) - 1]) + { + GNUNET_break (0); + force_reconnect (handle); + return; + } + } + GNUNET_CONTAINER_DLL_remove (handle->get_auth_head, handle->get_auth_tail, qe); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received GET_AUTH reply `%s' from GNS service\n", auth_name); - - GNUNET_CLIENT_receive (h->client, &process_message, h, - GNUNET_TIME_UNIT_FOREVER_REL); - qe->auth_proc(qe->proc_cls, auth_name); - GNUNET_free(qe); - + qe->auth_proc (qe->proc_cls, auth_name); + GNUNET_free (qe); } + + /** * Process a given reply to the lookup request * @@ -421,48 +571,45 @@ process_get_auth_reply (struct GNUNET_GNS_QueueEntry *qe, * @param msg the lookup message received */ static void -process_lookup_reply (struct GNUNET_GNS_QueueEntry *qe, +process_lookup_reply (struct GNUNET_GNS_LookupRequest *qe, const struct GNUNET_GNS_ClientLookupResultMessage *msg) { - struct GNUNET_GNS_Handle *h = qe->gns_handle; - int rd_count = ntohl(msg->rd_count); - size_t len = ntohs (((struct GNUNET_MessageHeader*)msg)->size); + struct GNUNET_GNS_Handle *handle = qe->gns_handle; + struct PendingMessage *p = (struct PendingMessage *) &qe[1]; + uint32_t rd_count = ntohl (msg->rd_count); struct GNUNET_NAMESTORE_RecordData rd[rd_count]; + size_t mlen; - GNUNET_CONTAINER_DLL_remove(h->lookup_head, h->lookup_tail, qe); - - if (len < sizeof (struct GNUNET_GNS_ClientLookupResultMessage)) + if (GNUNET_YES != p->transmitted) { - GNUNET_free(qe); + /* service send reply to query we never managed to send!? */ GNUNET_break (0); - force_reconnect (h); + force_reconnect (handle); return; } - - len -= sizeof(struct GNUNET_GNS_ClientLookupResultMessage); - - GNUNET_CLIENT_receive (h->client, &process_message, h, - GNUNET_TIME_UNIT_FOREVER_REL); - if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (len, - (char*)&msg[1], + mlen = ntohs (msg->header.size); + mlen -= sizeof (struct GNUNET_GNS_ClientLookupResultMessage); + if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (mlen, + (const char*) &msg[1], rd_count, rd)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to serialize lookup reply from GNS service!\n"); - qe->lookup_proc(qe->proc_cls, 0, NULL); + _("Failed to serialize lookup reply from GNS service!\n")); + qe->lookup_proc (qe->proc_cls, 0, NULL); } else - { - + { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received lookup reply from GNS service (count=%d)\n", - ntohl(msg->rd_count)); - qe->lookup_proc(qe->proc_cls, rd_count, rd); + "Received lookup reply from GNS service (%u records)\n", + (unsigned int) rd_count); + qe->lookup_proc (qe->proc_cls, rd_count, rd); } - GNUNET_free(qe); + GNUNET_CONTAINER_DLL_remove (handle->lookup_head, handle->lookup_tail, qe); + GNUNET_free (qe); } + /** * Handler for messages received from the GNS service * @@ -473,109 +620,82 @@ static void process_message (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_GNS_Handle *handle = cls; - struct GNUNET_GNS_QueueEntry *qe; + struct GNUNET_GNS_LookupRequest *lr; + struct GNUNET_GNS_ShortenRequest *sr; + struct GNUNET_GNS_GetAuthRequest *gar; const struct GNUNET_GNS_ClientLookupResultMessage *lookup_msg; const struct GNUNET_GNS_ClientShortenResultMessage *shorten_msg; const struct GNUNET_GNS_ClientGetAuthResultMessage *get_auth_msg; - uint16_t type; uint32_t r_id; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Got message\n"); - if (msg == NULL) + if (NULL == msg) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Error receiving data from GNS service, reconnecting\n"); force_reconnect (handle); return; } - - type = ntohs (msg->type); - - if (type == GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT) + switch (ntohs (msg->type)) { + case GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Got lookup msg\n"); - lookup_msg = (const struct GNUNET_GNS_ClientLookupResultMessage *) msg; - r_id = ntohl (lookup_msg->id); - - if (r_id > handle->r_id) + "Got LOOKUP_RESULT msg\n"); + if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientLookupResultMessage)) { - /** no request found */ - GNUNET_break_op (0); - GNUNET_CLIENT_receive (handle->client, &process_message, handle, - GNUNET_TIME_UNIT_FOREVER_REL); + GNUNET_break (0); + force_reconnect (handle); return; } - - for (qe = handle->lookup_head; qe != NULL; qe = qe->next) - { - if (qe->r_id == r_id) - break; - } - if (qe) - process_lookup_reply(qe, lookup_msg); - - return; - - } - else if (type == GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT) - { + lookup_msg = (const struct GNUNET_GNS_ClientLookupResultMessage *) msg; + r_id = ntohl (lookup_msg->id); + for (lr = handle->lookup_head; NULL != lr; lr = lr->next) + if (lr->r_id == r_id) + { + process_lookup_reply(lr, lookup_msg); + break; + } + break; + case GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got SHORTEN_RESULT msg\n"); - shorten_msg = (struct GNUNET_GNS_ClientShortenResultMessage *) msg; - - r_id = ntohl (shorten_msg->id); - - if (r_id > handle->r_id) + if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientShortenResultMessage)) { - /** no request found */ - GNUNET_break_op (0); - GNUNET_CLIENT_receive (handle->client, &process_message, handle, - GNUNET_TIME_UNIT_FOREVER_REL); + GNUNET_break (0); + force_reconnect (handle); return; } - - for (qe = handle->shorten_head; qe != NULL; qe = qe->next) - { - if (qe->r_id == r_id) - break; - } - if (qe) - process_shorten_reply(qe, shorten_msg); - return; - } - else if (type == GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT) - { + shorten_msg = (const struct GNUNET_GNS_ClientShortenResultMessage *) msg; + r_id = ntohl (shorten_msg->id); + for (sr = handle->shorten_head; NULL != sr; sr = sr->next) + if (sr->r_id == r_id) + { + process_shorten_reply (sr, shorten_msg); + break; + } + break; + case GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got GET_AUTH_RESULT msg\n"); - get_auth_msg = (struct GNUNET_GNS_ClientGetAuthResultMessage *) msg; - - r_id = ntohl (get_auth_msg->id); - - if (r_id > handle->r_id) + if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage)) { - /** no request found */ - GNUNET_break_op (0); - GNUNET_CLIENT_receive (handle->client, &process_message, handle, - GNUNET_TIME_UNIT_FOREVER_REL); + GNUNET_break (0); + force_reconnect (handle); return; } - - for (qe = handle->get_auth_head; qe != NULL; qe = qe->next) - { - if (qe->r_id == r_id) - break; - } - if (qe) - process_get_auth_reply(qe, get_auth_msg); + get_auth_msg = (const struct GNUNET_GNS_ClientGetAuthResultMessage *) msg; + r_id = ntohl (get_auth_msg->id); + for (gar = handle->get_auth_head; NULL != gar; gar = gar->next) + if (gar->r_id == r_id) + { + process_get_auth_reply (gar, get_auth_msg); + break; + } + break; + default: + GNUNET_break (0); + force_reconnect (handle); return; } - - - if (GNUNET_YES == handle->reconnect) - force_reconnect (handle); - + GNUNET_CLIENT_receive (handle->client, &process_message, handle, + GNUNET_TIME_UNIT_FOREVER_REL); } @@ -591,13 +711,8 @@ GNUNET_GNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) struct GNUNET_GNS_Handle *handle; handle = GNUNET_malloc (sizeof (struct GNUNET_GNS_Handle)); - handle->reconnect = GNUNET_NO; handle->cfg = cfg; reconnect (handle); - //handle->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, handle); - handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; - handle->r_id = 0; - handle->in_receive = GNUNET_NO; return handle; } @@ -616,24 +731,79 @@ GNUNET_GNS_disconnect (struct GNUNET_GNS_Handle *handle) GNUNET_SCHEDULER_cancel (handle->reconnect_task); handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } - GNUNET_free(handle); - /* disco from GNS */ + GNUNET_assert (NULL == handle->lookup_head); + GNUNET_assert (NULL == handle->shorten_head); + GNUNET_assert (NULL == handle->get_auth_head); + GNUNET_free (handle); } -/* - * Helper function to generate request ids - * - * @param h handle - * @return a new id + +/** + * Cancel pending lookup request + * + * @param lr the lookup request to cancel */ -static uint32_t -get_request_id (struct GNUNET_GNS_Handle *h) +void +GNUNET_GNS_cancel_lookup_request (struct GNUNET_GNS_LookupRequest *lr) { - uint32_t r_id = h->r_id; - h->r_id++; - return r_id; + struct PendingMessage *p = (struct PendingMessage*) &lr[1]; + + GNUNET_assert (NULL != lr->gns_handle); + if (GNUNET_NO == p->transmitted) + GNUNET_CONTAINER_DLL_remove (lr->gns_handle->pending_head, + lr->gns_handle->pending_tail, + p); + GNUNET_CONTAINER_DLL_remove (lr->gns_handle->lookup_head, + lr->gns_handle->lookup_tail, + lr); + GNUNET_free (lr); } + +/** + * Cancel pending shorten request + * + * @param sr the lookup request to cancel + */ +void +GNUNET_GNS_cancel_shorten_request (struct GNUNET_GNS_ShortenRequest *sr) +{ + struct PendingMessage *p = (struct PendingMessage*) &sr[1]; + + GNUNET_assert (NULL != sr->gns_handle); + if (GNUNET_NO == p->transmitted) + GNUNET_CONTAINER_DLL_remove (sr->gns_handle->pending_head, + sr->gns_handle->pending_tail, + p); + GNUNET_CONTAINER_DLL_remove (sr->gns_handle->shorten_head, + sr->gns_handle->shorten_tail, + sr); + GNUNET_free (sr); +} + + +/** + * Cancel pending get auth request + * + * @param gar the lookup request to cancel + */ +void +GNUNET_GNS_cancel_get_auth_request (struct GNUNET_GNS_GetAuthRequest *gar) +{ + struct PendingMessage *p = (struct PendingMessage*) &gar[1]; + + GNUNET_assert (NULL != gar->gns_handle); + if (GNUNET_NO == p->transmitted) + GNUNET_CONTAINER_DLL_remove (gar->gns_handle->pending_head, + gar->gns_handle->pending_tail, + p); + GNUNET_CONTAINER_DLL_remove (gar->gns_handle->get_auth_head, + gar->gns_handle->get_auth_tail, + gar); + GNUNET_free (gar); +} + + /** * Perform an asynchronous Lookup operation on the GNS. * @@ -641,179 +811,235 @@ get_request_id (struct GNUNET_GNS_Handle *h) * @param name the name to look up * @param zone the zone to start the resolution in * @param type the record type to look up + * @param only_cached GNUNET_YES to only check locally not DHT for performance + * @param shorten_key the private key of the shorten zone (can be NULL) * @param proc processor to call on result * @param proc_cls closure for processor - * @return handle to the get + * @return handle to the get request */ -struct GNUNET_GNS_QueueEntry * +struct GNUNET_GNS_LookupRequest* GNUNET_GNS_lookup_zone (struct GNUNET_GNS_Handle *handle, - const char * name, - struct GNUNET_CRYPTO_ShortHashCode *zone, - enum GNUNET_GNS_RecordType type, - GNUNET_GNS_LookupResultProcessor proc, - void *proc_cls) + const char *name, + struct GNUNET_CRYPTO_ShortHashCode *zone, + enum GNUNET_GNS_RecordType type, + int only_cached, + struct GNUNET_CRYPTO_RsaPrivateKey *shorten_key, + GNUNET_GNS_LookupResultProcessor proc, + void *proc_cls) { /* IPC to shorten gns names, return shorten_handle */ struct GNUNET_GNS_ClientLookupMessage *lookup_msg; - struct GNUNET_GNS_QueueEntry *qe; + struct GNUNET_GNS_LookupRequest *lr; size_t msize; struct PendingMessage *pending; + struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *pkey_enc; + size_t key_len; + char* pkey_tmp; if (NULL == name) { + GNUNET_break (0); return NULL; + } + if (NULL != shorten_key) + { + pkey_enc = GNUNET_CRYPTO_rsa_encode_key (shorten_key); + GNUNET_assert (pkey_enc != NULL); + key_len = ntohs (pkey_enc->len); } - - msize = sizeof (struct GNUNET_GNS_ClientLookupMessage) + strlen(name) + 1; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to lookup %s in GNS\n", name); - - qe = GNUNET_malloc(sizeof (struct GNUNET_GNS_QueueEntry)); - qe->gns_handle = handle; - qe->lookup_proc = proc; - qe->proc_cls = proc_cls; - qe->r_id = get_request_id(handle); - GNUNET_CONTAINER_DLL_insert_tail(handle->lookup_head, - handle->lookup_tail, qe); - - pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize); - memset(pending, 0, (sizeof (struct PendingMessage) + msize)); - + else + { + pkey_enc = NULL; + key_len = 0; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Trying to lookup `%s' in GNS\n", + name); + msize = sizeof (struct GNUNET_GNS_ClientLookupMessage) + + key_len + strlen (name) + 1; + if (msize > UINT16_MAX) + { + GNUNET_break (0); + GNUNET_free (pkey_enc); + return NULL; + } + lr = GNUNET_malloc (sizeof (struct GNUNET_GNS_LookupRequest) + + sizeof (struct PendingMessage) + msize); + lr->gns_handle = handle; + lr->lookup_proc = proc; + lr->proc_cls = proc_cls; + lr->r_id = handle->r_id_gen++; + pending = (struct PendingMessage *)&lr[1]; pending->size = msize; + pending->r_id = lr->r_id; + GNUNET_CONTAINER_DLL_insert_tail (handle->lookup_head, + handle->lookup_tail, lr); lookup_msg = (struct GNUNET_GNS_ClientLookupMessage *) &pending[1]; lookup_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_LOOKUP); lookup_msg->header.size = htons (msize); - lookup_msg->id = htonl(qe->r_id); - + lookup_msg->id = htonl (lr->r_id); + lookup_msg->only_cached = htonl (only_cached); if (NULL != zone) { - lookup_msg->use_default_zone = htonl(0); - memcpy(&lookup_msg->zone, zone, sizeof(struct GNUNET_CRYPTO_ShortHashCode)); + lookup_msg->use_default_zone = htonl (GNUNET_NO); + memcpy (&lookup_msg->zone, zone, sizeof (struct GNUNET_CRYPTO_ShortHashCode)); } else { - lookup_msg->use_default_zone = htonl(1); - memset(&lookup_msg->zone, 0, sizeof(struct GNUNET_CRYPTO_ShortHashCode)); + lookup_msg->use_default_zone = htonl (GNUNET_YES); + memset (&lookup_msg->zone, 0, sizeof(struct GNUNET_CRYPTO_ShortHashCode)); + } + lookup_msg->type = htonl (type); + pkey_tmp = (char *) &lookup_msg[1]; + if (pkey_enc != NULL) + { + lookup_msg->have_key = htonl (GNUNET_YES); + memcpy (pkey_tmp, pkey_enc, key_len); } + else + lookup_msg->have_key = htonl (GNUNET_NO); + GNUNET_free_non_null (pkey_enc); + memcpy (&pkey_tmp[key_len], name, strlen (name) + 1); - lookup_msg->type = htonl(type); - - memcpy(&lookup_msg[1], name, strlen(name)); - - GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, handle->pending_tail, - pending); - + GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, + handle->pending_tail, + pending); process_pending_messages (handle); - return qe; + return lr; } + /** * Perform an asynchronous Lookup operation on the GNS. * * @param handle handle to the GNS service * @param name the name to look up * @param type the record type to look up + * @param only_cached GNUNET_YES to only check locally not DHT for performance + * @param shorten_key the private key of the shorten zone (can be NULL) * @param proc processor to call on result * @param proc_cls closure for processor - * @return handle to the get + * @return handle to the lookup request */ -struct GNUNET_GNS_QueueEntry * +struct GNUNET_GNS_LookupRequest * GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle, - const char * name, + const char *name, enum GNUNET_GNS_RecordType type, + int only_cached, + struct GNUNET_CRYPTO_RsaPrivateKey *shorten_key, GNUNET_GNS_LookupResultProcessor proc, void *proc_cls) { - return GNUNET_GNS_lookup_zone (handle, name, NULL, type, proc, proc_cls); + return GNUNET_GNS_lookup_zone (handle, name, + NULL, + type, only_cached, + shorten_key, + proc, proc_cls); } + /** * Perform a name shortening operation on the GNS. * * @param handle handle to the GNS service * @param name the name to look up + * @param private_zone the public zone of the private zone + * @param shorten_zone the public zone of the shorten zone * @param zone the zone to start the resolution in * @param proc function to call on result * @param proc_cls closure for processor * @return handle to the operation */ -struct GNUNET_GNS_QueueEntry * +struct GNUNET_GNS_ShortenRequest* GNUNET_GNS_shorten_zone (struct GNUNET_GNS_Handle *handle, - const char * name, - struct GNUNET_CRYPTO_ShortHashCode *zone, - GNUNET_GNS_ShortenResultProcessor proc, - void *proc_cls) + const char *name, + struct GNUNET_CRYPTO_ShortHashCode *private_zone, + struct GNUNET_CRYPTO_ShortHashCode *shorten_zone, + struct GNUNET_CRYPTO_ShortHashCode *zone, + GNUNET_GNS_ShortenResultProcessor proc, + void *proc_cls) { /* IPC to shorten gns names, return shorten_handle */ struct GNUNET_GNS_ClientShortenMessage *shorten_msg; - struct GNUNET_GNS_QueueEntry *qe; + struct GNUNET_GNS_ShortenRequest *sr; size_t msize; struct PendingMessage *pending; if (NULL == name) { + GNUNET_break (0); return NULL; } - - msize = sizeof (struct GNUNET_GNS_ClientShortenMessage) + strlen(name) + 1; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to shorten %s in GNS\n", name); - - qe = GNUNET_malloc(sizeof (struct GNUNET_GNS_QueueEntry)); - qe->gns_handle = handle; - qe->shorten_proc = proc; - qe->proc_cls = proc_cls; - qe->r_id = get_request_id(handle); - GNUNET_CONTAINER_DLL_insert_tail(handle->shorten_head, - handle->shorten_tail, qe); - - pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize); - memset(pending, 0, (sizeof (struct PendingMessage) + msize)); - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to shorten `%s' in GNS\n", name); + msize = sizeof (struct GNUNET_GNS_ClientShortenMessage) + strlen (name) + 1; + if (msize > UINT16_MAX) + { + GNUNET_break (0); + return NULL; + } + sr = GNUNET_malloc (sizeof (struct GNUNET_GNS_ShortenRequest) + + sizeof (struct PendingMessage) + msize); + sr->gns_handle = handle; + sr->shorten_proc = proc; + sr->proc_cls = proc_cls; + sr->r_id = handle->r_id_gen++; + GNUNET_CONTAINER_DLL_insert_tail (handle->shorten_head, + handle->shorten_tail, sr); + pending = (struct PendingMessage *)&sr[1]; pending->size = msize; + pending->r_id = sr->r_id; shorten_msg = (struct GNUNET_GNS_ClientShortenMessage *) &pending[1]; shorten_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_SHORTEN); - shorten_msg->header.size = htons (msize); - shorten_msg->id = htonl(qe->r_id); - + shorten_msg->header.size = htons ((uint16_t) msize); + shorten_msg->id = htonl (sr->r_id); + shorten_msg->private_zone = *private_zone; + shorten_msg->shorten_zone = *shorten_zone; if (NULL != zone) { - shorten_msg->use_default_zone = htonl(0); - memcpy(&shorten_msg->zone, zone, - sizeof(struct GNUNET_CRYPTO_ShortHashCode)); + shorten_msg->use_default_zone = htonl (GNUNET_NO); + memcpy (&shorten_msg->zone, zone, + sizeof (struct GNUNET_CRYPTO_ShortHashCode)); } else { - shorten_msg->use_default_zone = htonl(1); - memset(&shorten_msg->zone, 0, sizeof(struct GNUNET_CRYPTO_ShortHashCode)); - } - - memcpy(&shorten_msg[1], name, strlen(name)); - + shorten_msg->use_default_zone = htonl (GNUNET_YES); + memset (&shorten_msg->zone, 0, sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + } + memcpy (&shorten_msg[1], name, strlen (name) + 1); GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, handle->pending_tail, - pending); - + pending); process_pending_messages (handle); - return qe; + return sr; } + /** * Perform a name shortening operation on the GNS. * * @param handle handle to the GNS service * @param name the name to look up + * @param private_zone the public zone of the private zone + * @param shorten_zone the public zone of the shorten zone * @param proc function to call on result * @param proc_cls closure for processor * @return handle to the operation */ -struct GNUNET_GNS_QueueEntry * +struct GNUNET_GNS_ShortenRequest* GNUNET_GNS_shorten (struct GNUNET_GNS_Handle *handle, - const char * name, + const char *name, + struct GNUNET_CRYPTO_ShortHashCode *private_zone, + struct GNUNET_CRYPTO_ShortHashCode *shorten_zone, GNUNET_GNS_ShortenResultProcessor proc, void *proc_cls) { - return GNUNET_GNS_shorten_zone (handle, name, NULL, proc, proc_cls); + return GNUNET_GNS_shorten_zone (handle, name, + private_zone, shorten_zone, + NULL, proc, proc_cls); } + + /** * Perform an authority lookup for a given name. * @@ -823,51 +1049,52 @@ GNUNET_GNS_shorten (struct GNUNET_GNS_Handle *handle, * @param proc_cls closure for processor * @return handle to the operation */ -struct GNUNET_GNS_QueueEntry * +struct GNUNET_GNS_GetAuthRequest* GNUNET_GNS_get_authority (struct GNUNET_GNS_Handle *handle, - const char * name, - GNUNET_GNS_GetAuthResultProcessor proc, - void *proc_cls) + const char *name, + GNUNET_GNS_GetAuthResultProcessor proc, + void *proc_cls) { struct GNUNET_GNS_ClientGetAuthMessage *get_auth_msg; - struct GNUNET_GNS_QueueEntry *qe; + struct GNUNET_GNS_GetAuthRequest *gar; size_t msize; struct PendingMessage *pending; if (NULL == name) { + GNUNET_break (0); return NULL; } - - msize = sizeof (struct GNUNET_GNS_ClientGetAuthMessage) + strlen(name) + 1; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to look up authority for %s in GNS\n", name); - - qe = GNUNET_malloc(sizeof (struct GNUNET_GNS_QueueEntry)); - qe->gns_handle = handle; - qe->auth_proc = proc; - qe->proc_cls = proc_cls; - qe->r_id = get_request_id(handle); - GNUNET_CONTAINER_DLL_insert_tail(handle->get_auth_head, - handle->get_auth_tail, qe); - - pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize); - memset(pending, 0, (sizeof (struct PendingMessage) + msize)); - + msize = sizeof (struct GNUNET_GNS_ClientGetAuthMessage) + strlen (name) + 1; + if (msize > UINT16_MAX) + { + GNUNET_break (0); + return NULL; + } + gar = GNUNET_malloc (sizeof (struct GNUNET_GNS_GetAuthRequest) + + sizeof (struct PendingMessage) + msize); + gar->gns_handle = handle; + gar->auth_proc = proc; + gar->proc_cls = proc_cls; + gar->r_id = handle->r_id_gen++; + GNUNET_CONTAINER_DLL_insert_tail (handle->get_auth_head, + handle->get_auth_tail, gar); + + pending = (struct PendingMessage *) &gar[1]; pending->size = msize; - + pending->r_id = gar->r_id; get_auth_msg = (struct GNUNET_GNS_ClientGetAuthMessage *) &pending[1]; get_auth_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_GET_AUTH); get_auth_msg->header.size = htons (msize); - get_auth_msg->id = htonl(qe->r_id); - - memcpy(&get_auth_msg[1], name, strlen(name)); - - GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, handle->pending_tail, - pending); - + get_auth_msg->id = htonl (gar->r_id); + memcpy (&get_auth_msg[1], name, strlen (name) + 1); + GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, + handle->pending_tail, + pending); process_pending_messages (handle); - return qe; + return gar; } |