From 64fda257bdaf166ed3d96dce3a01ea14017a2a3e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 19 Sep 2016 13:26:44 +0000 Subject: [PATCH] misc minor fixes for new service MQ API, implementing resolver using new service API --- src/include/gnunet_mq_lib.h | 8 +- src/include/gnunet_scheduler_lib.h | 2 +- src/include/gnunet_service_lib.h | 36 ++- src/statistics/statistics_api.c | 33 ++- src/util/gnunet-service-resolver.c | 410 +++++++++++++++++++---------- src/util/mq.c | 13 +- 6 files changed, 337 insertions(+), 165 deletions(-) diff --git a/src/include/gnunet_mq_lib.h b/src/include/gnunet_mq_lib.h index 86144abca..999ee4134 100644 --- a/src/include/gnunet_mq_lib.h +++ b/src/include/gnunet_mq_lib.h @@ -171,7 +171,13 @@ enum GNUNET_MQ_Error * We received a message that was malformed and thus * could not be passed to its handler. */ - GNUNET_MQ_ERROR_MALFORMED = 8 + GNUNET_MQ_ERROR_MALFORMED = 8, + + /** + * We received a message for which we have no matching + * handler. + */ + GNUNET_MQ_ERROR_NO_MATCH = 16 }; diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h index 87cb3b6f1..1a0438bed 100644 --- a/src/include/gnunet_scheduler_lib.h +++ b/src/include/gnunet_scheduler_lib.h @@ -346,7 +346,7 @@ GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, * scheduled for execution once either the delay has expired or the * socket operation is ready. It will be run with the DEFAULT priority. * - * * @param delay when should this operation time out? + * @param delay when should this operation time out? * @param rfd read file-descriptor * @param task main function of the task * @param task_cls closure of @a task diff --git a/src/include/gnunet_service_lib.h b/src/include/gnunet_service_lib.h index 797857ed8..9c7009ef4 100644 --- a/src/include/gnunet_service_lib.h +++ b/src/include/gnunet_service_lib.h @@ -336,16 +336,36 @@ GNUNET_SERVICE_ruN_ (int argc, * @param connect_cb function to call whenever a client connects * @param disconnect_cb function to call whenever a client disconnects * @param cls closure argument for @a service_init_cb, @a connect_cb and @a disconnect_cb - * @param handlers NULL-terminated array of message handlers for the service, + * @param ... array of message handlers for the service, terminated + * by #GNUNET_MQ_handler_end(); * the closure will be set to the value returned by * the @a connect_cb for the respective connection * @return 0 on success, non-zero on error + * + * Sample invocation: + * + * GNUNET_SERVICE_MAIN + * ("resolver", + * GNUNET_SERVICE_OPTION_NONE, + * &init_cb, + * &connect_cb, + * &disconnect_cb, + * closure_for_cb, + * GNUNET_MQ_hd_var_size (get, + * GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST, + * struct GNUNET_RESOLVER_GetMessage, + * NULL), + * GNUNET_MQ_handler_end ()); + * */ -#define GNUNET_SERVICE_MAIN(service_name,service_options,init_cb,connect_cb,disconnect_cb,cls,handlers) \ +#define GNUNET_SERVICE_MAIN(service_name,service_options,init_cb,connect_cb,disconnect_cb,cls,...) \ int \ main (int argc,\ char *const *argv)\ { \ + struct GNUNET_MQ_MessageHandler mh[] = { \ + __VA_ARGS__ \ + }; \ return GNUNET_SERVICE_ruN_ (argc, \ argv, \ service_name, \ @@ -354,7 +374,7 @@ GNUNET_SERVICE_ruN_ (int argc, connect_cb, \ disconnect_cb, \ cls, \ - handlers); \ + mh); \ } @@ -387,6 +407,16 @@ void GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c); +/** + * Obtain the message queue of @a c. Convenience function. + * + * @param c the client to continue receiving from + * @return the message queue of @a c + */ +struct GNUNET_MQ_Handle * +GNUNET_SERVICE_client_get_mq (struct GNUNET_SERVICE_Client *c); + + /** * Disable the warning the server issues if a message is not * acknowledged in a timely fashion. Use this call if a client is diff --git a/src/statistics/statistics_api.c b/src/statistics/statistics_api.c index c8709145b..856873d00 100644 --- a/src/statistics/statistics_api.c +++ b/src/statistics/statistics_api.c @@ -295,12 +295,18 @@ update_memory_statistics (struct GNUNET_STATISTICS_Handle *h) if (current_heap_size > h->peak_heap_size) { h->peak_heap_size = current_heap_size; - GNUNET_STATISTICS_set (h, "# peak heap size", current_heap_size, GNUNET_NO); + GNUNET_STATISTICS_set (h, + "# peak heap size", + current_heap_size, + GNUNET_NO); } if (current_rss > h->peak_rss) { h->peak_rss = current_rss; - GNUNET_STATISTICS_set (h, "# peak resident set size", current_rss, GNUNET_NO); + GNUNET_STATISTICS_set (h, + "# peak resident set size", + current_rss, + GNUNET_NO); } #endif } @@ -739,7 +745,8 @@ reconnect_later (struct GNUNET_STATISTICS_Handle *h) */ loss = GNUNET_NO; for (gh = h->action_head; NULL != gh; gh = gh->next) - if ( (gh->make_persistent) && (ACTION_SET == gh->type) ) + if ( (gh->make_persistent) && + (ACTION_SET == gh->type) ) loss = GNUNET_YES; if (GNUNET_YES == loss) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -922,8 +929,7 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, GNUNET_assert (GNUNET_NO == h->do_destroy); /* Don't call twice. */ if ( (sync_first) && (NULL != h->mq) && - (0 != GNUNET_MQ_get_length (h->mq)) && - (GNUNET_YES == try_connect (h)) ) + (0 != GNUNET_MQ_get_length (h->mq)) ) { if ( (NULL != h->current) && (ACTION_GET == h->current->type) ) @@ -933,8 +939,7 @@ GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, { next = pos->next; if ( (ACTION_GET == pos->type) || - (ACTION_WATCH == pos->type) || - (GNUNET_NO == pos->make_persistent) ) + (ACTION_WATCH == pos->type) ) { GNUNET_CONTAINER_DLL_remove (h->action_head, h->action_tail, @@ -1009,7 +1014,7 @@ schedule_action (void *cls) reconnect_later (h); return; } - if (0 < GNUNET_MQ_get_length (h->mq) ) + if (0 < GNUNET_MQ_get_length (h->mq)) return; /* Wait for queue to be reduced more */ /* schedule next action */ while (NULL == h->current) @@ -1200,8 +1205,10 @@ GNUNET_STATISTICS_watch_cancel (struct GNUNET_STATISTICS_Handle *handle, continue; if ( (w->proc == proc) && (w->proc_cls == proc_cls) && - (0 == strcmp (w->name, name)) && - (0 == strcmp (w->subsystem, subsystem)) ) + (0 == strcmp (w->name, + name)) && + (0 == strcmp (w->subsystem, + subsystem)) ) { GNUNET_free (w->name); GNUNET_free (w->subsystem); @@ -1291,8 +1298,10 @@ add_setter_action (struct GNUNET_STATISTICS_Handle *h, ai->type = type; } } - ai->timeout = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT); - ai->make_persistent = make_persistent; + ai->timeout + = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT); + ai->make_persistent + = make_persistent; return; } /* no existing entry matches, create a fresh one */ diff --git a/src/util/gnunet-service-resolver.c b/src/util/gnunet-service-resolver.c index a87b1f5d0..12e484845 100644 --- a/src/util/gnunet-service-resolver.c +++ b/src/util/gnunet-service-resolver.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2007-2013 GNUnet e.V. + Copyright (C) 2007-2016 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -196,6 +196,22 @@ cache_resolve (struct IPCache *cache) } +/** + * Function called after the replies for the request have all + * been transmitted to the client, and we can now read the next + * request from the client. + * + * @param cls the `struct GNUNET_SERVICE_Client` to continue with + */ +static void +notify_service_client_done (void *cls) +{ + struct GNUNET_SERVICE_Client *client = cls; + + GNUNET_SERVICE_client_continue (client); +} + + /** * Get an IP address as a string (works for both IPv4 and IPv6). Note * that the resolution happens asynchronously and that the first call @@ -207,16 +223,19 @@ cache_resolve (struct IPCache *cache) * @param ip `struct in_addr` or `struct in6_addr` */ static void -get_ip_as_string (struct GNUNET_SERVER_Client *client, +get_ip_as_string (struct GNUNET_SERVICE_Client *client, int af, const void *ip) { struct IPCache *pos; struct IPCache *next; struct GNUNET_TIME_Absolute now; - struct GNUNET_SERVER_TransmitContext *tc; + struct GNUNET_MQ_Envelope *env; + struct GNUNET_MQ_Handle *mq; + struct GNUNET_MessageHeader *msg; size_t ip_len; struct in6_addr ix; + size_t alen; switch (af) { @@ -267,7 +286,9 @@ get_ip_as_string (struct GNUNET_SERVER_Client *client, { pos = GNUNET_malloc (sizeof (struct IPCache) + ip_len); pos->ip = &pos[1]; - GNUNET_memcpy (&pos[1], ip, ip_len); + GNUNET_memcpy (&pos[1], + ip, + ip_len); pos->last_request = now; pos->last_refresh = now; pos->ip_len = ip_len; @@ -277,29 +298,41 @@ get_ip_as_string (struct GNUNET_SERVER_Client *client, pos); cache_resolve (pos); } - tc = GNUNET_SERVER_transmit_context_create (client); if (NULL != pos->addr) - GNUNET_SERVER_transmit_context_append_data (tc, pos->addr, - strlen (pos->addr) + 1, - GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + alen = strlen (pos->addr) + 1; else - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Reverse lookup failed\n"); - GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, - GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); - GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); + alen = 0; + mq = GNUNET_SERVICE_client_get_mq (client); + env = GNUNET_MQ_msg_extra (msg, + alen, + GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + GNUNET_memcpy (&msg[1], + pos->addr, + alen); + GNUNET_MQ_send (mq, + env); + env = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + GNUNET_MQ_notify_sent (env, + ¬ify_service_client_done, + client); + GNUNET_MQ_send (mq, + env); } #if HAVE_GETADDRINFO static int -getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc, - const char *hostname, int af) +getaddrinfo_resolve (struct GNUNET_MQ_Handle *mq, + const char *hostname, + int af) { int s; struct addrinfo hints; struct addrinfo *result; struct addrinfo *pos; + struct GNUNET_MessageHeader *msg; + struct GNUNET_MQ_Envelope *env; #ifdef WINDOWS /* Due to a bug, getaddrinfo will not return a mix of different families */ @@ -307,21 +340,32 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc, { int ret1; int ret2; - ret1 = getaddrinfo_resolve (tc, hostname, AF_INET); - ret2 = getaddrinfo_resolve (tc, hostname, AF_INET6); - if ((ret1 == GNUNET_OK) || (ret2 == GNUNET_OK)) + ret1 = getaddrinfo_resolve (mq, + hostname, + AF_INET); + ret2 = getaddrinfo_resolve (mq, + hostname, + AF_INET6); + if ( (ret1 == GNUNET_OK) || + (ret2 == GNUNET_OK) ) return GNUNET_OK; - if ((ret1 == GNUNET_SYSERR) || (ret2 == GNUNET_SYSERR)) + if ( (ret1 == GNUNET_SYSERR) || + (ret2 == GNUNET_SYSERR) ) return GNUNET_SYSERR; return GNUNET_NO; } #endif - memset (&hints, 0, sizeof (struct addrinfo)); + memset (&hints, + 0, + sizeof (struct addrinfo)); hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; /* go for TCP */ - if (0 != (s = getaddrinfo (hostname, NULL, &hints, &result))) + if (0 != (s = getaddrinfo (hostname, + NULL, + &hints, + &result))) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Could not resolve `%s' (%s): %s\n"), @@ -329,13 +373,11 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc, (af == AF_INET) ? "IPv4" : ((af == AF_INET6) ? "IPv6" : "any"), gai_strerror (s)); - if ((s == EAI_BADFLAGS) || (s == EAI_MEMORY) + if ( (s == EAI_BADFLAGS) || #ifndef WINDOWS - || (s == EAI_SYSTEM) -#else - || 1 + (s == EAI_SYSTEM) || #endif - ) + (s == EAI_MEMORY) ) return GNUNET_NO; /* other function may still succeed */ return GNUNET_SYSERR; } @@ -346,16 +388,24 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc, switch (pos->ai_family) { case AF_INET: - GNUNET_SERVER_transmit_context_append_data (tc, - &((struct sockaddr_in*) pos->ai_addr)->sin_addr, - sizeof (struct in_addr), - GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + env = GNUNET_MQ_msg_extra (msg, + sizeof (struct in_addr), + GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + GNUNET_memcpy (&msg[1], + &((struct sockaddr_in*) pos->ai_addr)->sin_addr, + sizeof (struct in_addr)); + GNUNET_MQ_send (mq, + env); break; case AF_INET6: - GNUNET_SERVER_transmit_context_append_data (tc, - &((struct sockaddr_in6*) pos->ai_addr)->sin6_addr, - sizeof (struct in6_addr), - GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + env = GNUNET_MQ_msg_extra (msg, + sizeof (struct in6_addr), + GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + GNUNET_memcpy (&msg[1], + &((struct sockaddr_in6*) pos->ai_addr)->sin6_addr, + sizeof (struct in6_addr)); + GNUNET_MQ_send (mq, + env); break; default: /* unsupported, skip */ @@ -371,13 +421,15 @@ getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc, static int -gethostbyname2_resolve (struct GNUNET_SERVER_TransmitContext *tc, +gethostbyname2_resolve (struct GNUNET_MQ_Handle *mq, const char *hostname, int af) { struct hostent *hp; int ret1; int ret2; + struct GNUNET_MQ_Envelope *env; + struct GNUNET_MessageHeader *msg; #ifdef WINDOWS /* gethostbyname2() in plibc is a compat dummy that calls gethostbyname(). */ @@ -386,19 +438,27 @@ gethostbyname2_resolve (struct GNUNET_SERVER_TransmitContext *tc, if (af == AF_UNSPEC) { - ret1 = gethostbyname2_resolve (tc, hostname, AF_INET); - ret2 = gethostbyname2_resolve (tc, hostname, AF_INET6); - if ((ret1 == GNUNET_OK) || (ret2 == GNUNET_OK)) + ret1 = gethostbyname2_resolve (mq, + hostname, + AF_INET); + ret2 = gethostbyname2_resolve (mq, + hostname, + AF_INET6); + if ( (ret1 == GNUNET_OK) || + (ret2 == GNUNET_OK) ) return GNUNET_OK; - if ((ret1 == GNUNET_SYSERR) || (ret2 == GNUNET_SYSERR)) + if ( (ret1 == GNUNET_SYSERR) || + (ret2 == GNUNET_SYSERR) ) return GNUNET_SYSERR; return GNUNET_NO; } - hp = gethostbyname2 (hostname, af); + hp = gethostbyname2 (hostname, + af); if (hp == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Could not find IP of host `%s': %s\n"), hostname, + _("Could not find IP of host `%s': %s\n"), + hostname, hstrerror (h_errno)); return GNUNET_SYSERR; } @@ -407,17 +467,25 @@ gethostbyname2_resolve (struct GNUNET_SERVER_TransmitContext *tc, { case AF_INET: GNUNET_assert (hp->h_length == sizeof (struct in_addr)); - GNUNET_SERVER_transmit_context_append_data (tc, - hp->h_addr_list[0], - hp->h_length, - GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + env = GNUNET_MQ_msg_extra (msg, + hp->h_length, + GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + GNUNET_memcpy (&msg[1], + hp->h_addr_list[0], + hp->h_length); + GNUNET_MQ_send (mq, + env); break; case AF_INET6: GNUNET_assert (hp->h_length == sizeof (struct in6_addr)); - GNUNET_SERVER_transmit_context_append_data (tc, - hp->h_addr_list[0], - hp->h_length, - GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + env = GNUNET_MQ_msg_extra (msg, + hp->h_length, + GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + GNUNET_memcpy (&msg[1], + hp->h_addr_list[0], + hp->h_length); + GNUNET_MQ_send (mq, + env); break; default: GNUNET_break (0); @@ -430,10 +498,12 @@ gethostbyname2_resolve (struct GNUNET_SERVER_TransmitContext *tc, static int -gethostbyname_resolve (struct GNUNET_SERVER_TransmitContext *tc, - const char *hostname) +gethostbyname_resolve (struct GNUNET_MQ_Handle *mq, + const char *hostname) { struct hostent *hp; + struct GNUNET_MessageHeader *msg; + struct GNUNET_MQ_Envelope *env; hp = GETHOSTBYNAME (hostname); if (NULL == hp) @@ -450,10 +520,14 @@ gethostbyname_resolve (struct GNUNET_SERVER_TransmitContext *tc, return GNUNET_SYSERR; } GNUNET_assert (hp->h_length == sizeof (struct in_addr)); - GNUNET_SERVER_transmit_context_append_data (tc, - hp->h_addr_list[0], - hp->h_length, - GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + env = GNUNET_MQ_msg_extra (msg, + hp->h_length, + GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + GNUNET_memcpy (&msg[1], + hp->h_addr_list[0], + hp->h_length); + GNUNET_MQ_send (mq, + env); return GNUNET_OK; } #endif @@ -467,168 +541,197 @@ gethostbyname_resolve (struct GNUNET_SERVER_TransmitContext *tc, * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any" */ static void -get_ip_from_hostname (struct GNUNET_SERVER_Client *client, +get_ip_from_hostname (struct GNUNET_SERVICE_Client *client, const char *hostname, int af) { int ret; - struct GNUNET_SERVER_TransmitContext *tc; + struct GNUNET_MQ_Handle *mq; + struct GNUNET_MQ_Envelope *env; + struct GNUNET_MessageHeader *msg; - tc = GNUNET_SERVER_transmit_context_create (client); + mq = GNUNET_SERVICE_client_get_mq (client); ret = GNUNET_NO; #if HAVE_GETADDRINFO if (ret == GNUNET_NO) - ret = getaddrinfo_resolve (tc, hostname, af); + ret = getaddrinfo_resolve (mq, + hostname, + af); #elif HAVE_GETHOSTBYNAME2 if (ret == GNUNET_NO) - ret = gethostbyname2_resolve (tc, hostname, af); + ret = gethostbyname2_resolve (mq, + hostname, + af); #elif HAVE_GETHOSTBYNAME - if ((ret == GNUNET_NO) && ((af == AF_UNSPEC) || (af == PF_INET))) - gethostbyname_resolve (tc, hostname); + if ( (ret == GNUNET_NO) && + ( (af == AF_UNSPEC) || + (af == PF_INET) ) ) + gethostbyname_resolve (mq, + hostname); #endif - GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, - GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); - GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); + env = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); + GNUNET_MQ_notify_sent (env, + ¬ify_service_client_done, + client); + GNUNET_MQ_send (mq, + env); } /** - * Handle GET-message. + * Verify well-formedness of GET-message. * * @param cls closure - * @param client identification of the client - * @param message the actual message + * @param get the actual message + * @return #GNUNET_OK if @a get is well-formed */ -static void -handle_get (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +static int +check_get (void *cls, + const struct GNUNET_RESOLVER_GetMessage *get) { - uint16_t msize; - const struct GNUNET_RESOLVER_GetMessage *msg; - const void *ip; uint16_t size; int direction; int af; - msize = ntohs (message->size); - if (msize < sizeof (struct GNUNET_RESOLVER_GetMessage)) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, - GNUNET_SYSERR); - return; - } - msg = (const struct GNUNET_RESOLVER_GetMessage *) message; - size = msize - sizeof (struct GNUNET_RESOLVER_GetMessage); - direction = ntohl (msg->direction); - af = ntohl (msg->af); + size = ntohs (get->header.size) - sizeof (*get); + direction = ntohl (get->direction); if (GNUNET_NO == direction) { /* IP from hostname */ const char *hostname; - hostname = (const char *) &msg[1]; + hostname = (const char *) &get[1]; if (hostname[size - 1] != '\0') { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, - GNUNET_SYSERR); - return; + return GNUNET_SYSERR; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Resolver asked to look up `%s'.\n", - hostname); - get_ip_from_hostname (client, hostname, af); - return; + return GNUNET_OK; } - ip = &msg[1]; + af = ntohl (get->af); switch (af) { case AF_INET: if (size != sizeof (struct in_addr)) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, - GNUNET_SYSERR); - return; + return GNUNET_SYSERR; } break; case AF_INET6: if (size != sizeof (struct in6_addr)) { GNUNET_break (0); - GNUNET_SERVER_receive_done (client, - GNUNET_SYSERR); - return; + return GNUNET_SYSERR; } break; default: GNUNET_break (0); - GNUNET_SERVER_receive_done (client, - GNUNET_SYSERR); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Handle GET-message. + * + * @param cls identification of the client + * @param msg the actual message + */ +static void +handle_get (void *cls, + const struct GNUNET_RESOLVER_GetMessage *msg) +{ + struct GNUNET_SERVICE_Client *client = cls; + const void *ip; + int direction; + int af; + + direction = ntohl (msg->direction); + af = ntohl (msg->af); + if (GNUNET_NO == direction) + { + /* IP from hostname */ + const char *hostname; + + hostname = (const char *) &msg[1]; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Resolver asked to look up `%s'.\n", + hostname); + get_ip_from_hostname (client, + hostname, + af); return; } + ip = &msg[1]; { char buf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Resolver asked to look up IP address `%s'.\n", - inet_ntop (af, ip, buf, sizeof (buf))); + inet_ntop (af, + ip, + buf, + sizeof (buf))); } - get_ip_as_string (client, af, ip); + get_ip_as_string (client, + af, + ip); } /** - * Process resolver requests. + * Callback called when a client connects to the service. * - * @param cls closure - * @param server the initialized server - * @param cfg configuration to use + * @param cls closure for the service + * @param c the new client that connected to the service + * @param mq the message queue used to send messages to the client + * @return @a c */ -static void -run (void *cls, struct GNUNET_SERVER_Handle *server, - const struct GNUNET_CONFIGURATION_Handle *cfg) +static void * +connect_cb (void *cls, + struct GNUNET_SERVICE_Client *c, + struct GNUNET_MQ_Handle *mq) { - static const struct GNUNET_SERVER_MessageHandler handlers[] = { - {&handle_get, NULL, GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST, 0}, - {NULL, NULL, 0, 0} - }; - GNUNET_SERVER_add_handlers (server, handlers); + return c; } /** - * The main function for the resolver service. + * Callback called when a client disconnected from the service * - * @param argc number of arguments from the command line - * @param argv command line arguments - * @return 0 ok, 1 on error + * @param cls closure for the service + * @param c the client that disconnected + * @param internal_cls should be equal to @a c */ -int -main (int argc, char *const *argv) +static void +disconnect_cb (void *cls, + struct GNUNET_SERVICE_Client *c, + void *internal_cls) { - struct IPCache *pos; - int ret; - - ret = - (GNUNET_OK == - GNUNET_SERVICE_run (argc, argv, - "resolver", - GNUNET_SERVICE_OPTION_NONE, - &run, NULL)) ? 0 : 1; - while (NULL != (pos = cache_head)) - { - GNUNET_CONTAINER_DLL_remove (cache_head, - cache_tail, - pos); - GNUNET_free_non_null (pos->addr); - GNUNET_free (pos); - } - return ret; + GNUNET_assert (c == internal_cls); } + +/** + * Define "main" method using service macro. + */ +GNUNET_SERVICE_MAIN +("resolver", + GNUNET_SERVICE_OPTION_NONE, + NULL, + &connect_cb, + &disconnect_cb, + NULL, + GNUNET_MQ_hd_var_size (get, + GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST, + struct GNUNET_RESOLVER_GetMessage, + NULL), + GNUNET_MQ_handler_end ()); + + #if defined(LINUX) && defined(__GLIBC__) #include @@ -636,7 +739,7 @@ main (int argc, char *const *argv) * MINIMIZE heap size (way below 128k) since this process doesn't need much. */ void __attribute__ ((constructor)) -GNUNET_ARM_memory_init () +GNUNET_RESOLVER_memory_init () { mallopt (M_TRIM_THRESHOLD, 4 * 1024); mallopt (M_TOP_PAD, 1 * 1024); @@ -645,4 +748,23 @@ GNUNET_ARM_memory_init () #endif +/** + * Free globals on exit. + */ +void __attribute__ ((destructor)) +GNUNET_RESOLVER_memory_done () +{ + struct IPCache *pos; + + while (NULL != (pos = cache_head)) + { + GNUNET_CONTAINER_DLL_remove (cache_head, + cache_tail, + pos); + GNUNET_free_non_null (pos->addr); + GNUNET_free (pos); + } +} + + /* end of gnunet-service-resolver.c */ diff --git a/src/util/mq.c b/src/util/mq.c index b22d97f59..e9dba3d9d 100644 --- a/src/util/mq.c +++ b/src/util/mq.c @@ -359,6 +359,7 @@ GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq, GNUNET_assert (NULL != mq); GNUNET_assert (NULL == ev->parent_queue); + mq->queue_length++; ev->parent_queue = mq; /* is the implementation busy? queue it! */ if (NULL != mq->current_envelope) @@ -366,11 +367,12 @@ GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq, GNUNET_CONTAINER_DLL_insert_tail (mq->envelope_head, mq->envelope_tail, ev); - mq->queue_length++; return; } mq->current_envelope = ev; - mq->send_impl (mq, ev->mh, mq->impl_state); + mq->send_impl (mq, + ev->mh, + mq->impl_state); } @@ -422,6 +424,8 @@ impl_send_continue (void *cls) current_envelope = mq->current_envelope; GNUNET_assert (NULL != current_envelope); current_envelope->parent_queue = NULL; + GNUNET_assert (0 < mq->queue_length); + mq->queue_length--; if (NULL == mq->envelope_head) { mq->current_envelope = NULL; @@ -432,7 +436,6 @@ impl_send_continue (void *cls) GNUNET_CONTAINER_DLL_remove (mq->envelope_head, mq->envelope_tail, mq->current_envelope); - mq->queue_length--; mq->send_impl (mq, mq->current_envelope->mh, mq->impl_state); @@ -973,7 +976,6 @@ GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq) mq->queue_length--; GNUNET_MQ_discard (ev); } - GNUNET_assert (0 == mq->queue_length); if (NULL != mq->current_envelope) { /* we can only discard envelopes that @@ -981,7 +983,9 @@ GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq) mq->current_envelope->parent_queue = NULL; GNUNET_MQ_discard (mq->current_envelope); mq->current_envelope = NULL; + mq->queue_length--; } + GNUNET_assert (0 == mq->queue_length); if (NULL != mq->assoc_map) { GNUNET_CONTAINER_multihashmap32_destroy (mq->assoc_map); @@ -1039,6 +1043,7 @@ GNUNET_MQ_send_cancel (struct GNUNET_MQ_Envelope *ev) { // complex case, we already started with transmitting // the message + mq->queue_length--; mq->cancel_impl (mq, mq->impl_state); // continue sending the next message, if any -- 2.25.1