X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fclient.c;h=d87be74f6d943c1bfdc072906ca6fe8a523b3919;hb=ed28dd2141e77aa073d81089cb5a07e0a0fc013c;hp=6c5e93ce4444acc9388322a6d147b9ddda01fb1f;hpb=3d7fefedc9ba60bd8e8448efe8b628446d958536;p=oweals%2Fgnunet.git diff --git a/src/util/client.c b/src/util/client.c index 6c5e93ce4..d87be74f6 100644 --- a/src/util/client.c +++ b/src/util/client.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2001-2013 Christian Grothoff (and other contributing authors) + Copyright (C) 2001-2013 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 @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** @@ -29,6 +29,7 @@ #include "platform.h" #include "gnunet_protocols.h" #include "gnunet_util_lib.h" +#include "gnunet_socks.h" /** @@ -56,7 +57,7 @@ struct GNUNET_CLIENT_TransmitHandle GNUNET_CONNECTION_TransmitReadyNotify notify; /** - * Closure for notify. + * Closure for @e notify. */ void *notify_cls; @@ -70,7 +71,7 @@ struct GNUNET_CLIENT_TransmitHandle * If we are re-trying and are delaying to do so, * handle to the scheduled task managing the delay. */ - GNUNET_SCHEDULER_TaskIdentifier reconnect_task; + struct GNUNET_SCHEDULER_Task *reconnect_task; /** * Timeout for the operation overall. @@ -127,7 +128,7 @@ struct TransmitGetResponseContext GNUNET_CLIENT_MessageHandler rn; /** - * Closure for "rn". + * Closure for @e rn. */ void *rn_cls; }; @@ -168,7 +169,7 @@ struct GNUNET_CLIENT_Connection GNUNET_CLIENT_MessageHandler receiver_handler; /** - * Closure for receiver_handler. + * Closure for @e receiver_handler. */ void *receiver_handler_cls; @@ -182,7 +183,7 @@ struct GNUNET_CLIENT_Connection * If we are re-trying and are delaying to do so, * handle to the scheduled task managing the delay. */ - GNUNET_SCHEDULER_TaskIdentifier receive_task; + struct GNUNET_SCHEDULER_Task * receive_task; /** * Buffer for received message. @@ -217,7 +218,9 @@ struct GNUNET_CLIENT_Connection /** * Are we currently busy doing receive-processing? - * GNUNET_YES if so, GNUNET_NO if not. + * #GNUNET_YES if so, #GNUNET_NO if not. #GNUNET_SYSERR + * if the connection has failed (but we may not have + * closed the handle itself yet). */ int in_receive; @@ -251,8 +254,8 @@ try_unixpath (const char *service_name, struct sockaddr_un s_un; unixpath = NULL; - if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "UNIXPATH", &unixpath)) && - (0 < strlen (unixpath))) + if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH", &unixpath)) && + (0 < strlen (unixpath))) { /* We have a non-NULL unixpath, need to validate it */ if (strlen (unixpath) >= sizeof (s_un.sun_path)) @@ -263,6 +266,8 @@ try_unixpath (const char *service_name, unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath); LOG (GNUNET_ERROR_TYPE_INFO, _("Using `%s' instead\n"), unixpath); + if (NULL == unixpath) + return NULL; } connection = GNUNET_CONNECTION_create_from_connect_to_unixpath (cfg, unixpath); if (NULL != connection) @@ -285,7 +290,7 @@ try_unixpath (const char *service_name, * * @param service_name name of service to connect to * @param cfg configuration to use - * @return GNUNET_OK if the configuration is valid, GNUNET_SYSERR if not + * @return #GNUNET_OK if the configuration is valid, #GNUNET_SYSERR if not */ static int test_service_configuration (const char *service_name, @@ -297,8 +302,8 @@ test_service_configuration (const char *service_name, #if AF_UNIX char *unixpath = NULL; - if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "UNIXPATH", &unixpath)) && - (0 < strlen (unixpath))) + if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH", &unixpath)) && + (0 < strlen (unixpath))) ret = GNUNET_OK; GNUNET_free_non_null (unixpath); #endif @@ -306,7 +311,7 @@ test_service_configuration (const char *service_name, if ( (GNUNET_YES == GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT")) && (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "PORT", &port)) && + GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "PORT", &port)) && (port <= 65535) && (0 != port) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "HOSTNAME", @@ -328,12 +333,17 @@ test_service_configuration (const char *service_name, */ static struct GNUNET_CONNECTION_Handle * do_connect (const char *service_name, - const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int attempt) + const struct GNUNET_CONFIGURATION_Handle *cfg, + unsigned int attempt) { struct GNUNET_CONNECTION_Handle *connection; char *hostname; unsigned long long port; + /* Never use a local source if a proxy is configured */ + if (GNUNET_YES == GNUNET_SOCKS_check_service (service_name,cfg)) + return GNUNET_SOCKS_do_connect (service_name,cfg); + connection = NULL; if (0 == (attempt % 2)) { @@ -377,7 +387,10 @@ do_connect (const char *service_name, /* if port is 0, try UNIX */ connection = try_unixpath (service_name, cfg); if (NULL != connection) + { + GNUNET_free_non_null (hostname); return connection; + } LOG (GNUNET_ERROR_TYPE_DEBUG, "Port is 0 for service `%s', UNIXPATH did not work, returning NULL!\n", service_name); @@ -404,7 +417,7 @@ GNUNET_CLIENT_connect (const char *service_name, struct GNUNET_CLIENT_Connection *client; struct GNUNET_CONNECTION_Handle *connection; - if (GNUNET_OK != + if (GNUNET_OK != test_service_configuration (service_name, cfg)) return NULL; @@ -451,10 +464,10 @@ GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *client) GNUNET_CONNECTION_destroy (client->connection); client->connection = NULL; } - if (GNUNET_SCHEDULER_NO_TASK != client->receive_task) + if (NULL != client->receive_task) { GNUNET_SCHEDULER_cancel (client->receive_task); - client->receive_task = GNUNET_SCHEDULER_NO_TASK; + client->receive_task = NULL; } if (NULL != client->tag) { @@ -487,19 +500,23 @@ check_complete (struct GNUNET_CLIENT_Connection *client) /** * Callback function for data received from the network. Note that - * both "available" and "errCode" would be 0 if the read simply timed out. + * both @a available and @a errCode would be 0 if the read simply timed out. * * @param cls closure * @param buf pointer to received data - * @param available number of bytes availabe in "buf", + * @param available number of bytes availabe in @a buf, * possibly 0 (on errors) * @param addr address of the sender - * @param addrlen size of addr + * @param addrlen size of @a addr * @param errCode value of errno (on errors receiving) */ static void -receive_helper (void *cls, const void *buf, size_t available, - const struct sockaddr *addr, socklen_t addrlen, int errCode) +receive_helper (void *cls, + const void *buf, + size_t available, + const struct sockaddr *addr, + socklen_t addrlen, + int errCode) { struct GNUNET_CLIENT_Connection *client = cls; struct GNUNET_TIME_Relative remaining; @@ -509,18 +526,24 @@ receive_helper (void *cls, const void *buf, size_t available, GNUNET_assert (GNUNET_NO == client->msg_complete); GNUNET_assert (GNUNET_YES == client->in_receive); client->in_receive = GNUNET_NO; - if ((0 == available) || (NULL == client->connection) || (0 != errCode)) + if ( (0 == available) || + (NULL == client->connection) || + (0 != errCode) ) { /* signal timeout! */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Timeout in receive_helper, available %u, client->connection %s, errCode `%s'\n", - (unsigned int) available, NULL == client->connection ? "NULL" : "non-NULL", + (unsigned int) available, + NULL == client->connection ? "NULL" : "non-NULL", STRERROR (errCode)); + /* remember failure */ + client->in_receive = GNUNET_SYSERR; if (NULL != (receive_handler = client->receiver_handler)) { receive_handler_cls = client->receiver_handler_cls; client->receiver_handler = NULL; - receive_handler (receive_handler_cls, NULL); + receive_handler (receive_handler_cls, + NULL); } return; } @@ -539,8 +562,11 @@ receive_helper (void *cls, const void *buf, size_t available, if (0 == remaining.rel_value_us) { /* signal timeout! */ - if (NULL != client->receiver_handler) - client->receiver_handler (client->receiver_handler_cls, NULL); + if (NULL != (receive_handler = client->receiver_handler)) + { + client->receiver_handler = NULL; + receive_handler (client->receiver_handler_cls, NULL); + } return; } /* back to receive -- either for more data or to call callback! */ @@ -556,7 +582,8 @@ receive_helper (void *cls, const void *buf, size_t available, * @param tc scheduler context */ static void -receive_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +receive_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CLIENT_Connection *client = cls; GNUNET_CLIENT_MessageHandler handler = client->receiver_handler; @@ -564,12 +591,25 @@ receive_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) (const struct GNUNET_MessageHeader *) client->received_buf; void *handler_cls = client->receiver_handler_cls; uint16_t msize = ntohs (cmsg->size); - char mbuf[msize]; + char mbuf[msize] GNUNET_ALIGN; struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) mbuf; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %u and size %u\n", - ntohs (cmsg->type), msize); - client->receive_task = GNUNET_SCHEDULER_NO_TASK; + client->receive_task = NULL; + if ( (GNUNET_SYSERR == client->in_receive) && + (GNUNET_YES != client->msg_complete) ) + { + /* Connection failure, signal to caller! */ + client->receiver_handler = NULL; + if (NULL != handler) + handler (handler_cls, + NULL); + return; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Received message of type %u and size %u from %s service.\n", + ntohs (cmsg->type), + msize, + client->service_name); GNUNET_assert (GNUNET_YES == client->msg_complete); GNUNET_assert (client->received_pos >= msize); memcpy (msg, cmsg, msize); @@ -589,45 +629,53 @@ receive_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * * @param client the service * @param handler function to call with the message - * @param handler_cls closure for handler + * @param handler_cls closure for @a handler * @param timeout how long to wait until timing out */ void GNUNET_CLIENT_receive (struct GNUNET_CLIENT_Connection *client, - GNUNET_CLIENT_MessageHandler handler, void *handler_cls, + GNUNET_CLIENT_MessageHandler handler, + void *handler_cls, struct GNUNET_TIME_Relative timeout) { if (NULL == client->connection) { /* already disconnected, fail instantly! */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Client API violation for service `%s'\n", + client->service_name); GNUNET_break (0); /* this should not happen in well-written code! */ if (NULL != handler) - handler (handler_cls, NULL); + handler (handler_cls, + NULL); return; } client->receiver_handler = handler; client->receiver_handler_cls = handler_cls; client->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout); - if (GNUNET_YES == client->msg_complete) + if ( (GNUNET_YES == client->msg_complete) || + (GNUNET_SYSERR == client->in_receive) ) { - GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == client->receive_task); + GNUNET_assert (NULL == client->receive_task); client->receive_task = GNUNET_SCHEDULER_add_now (&receive_task, client); + return; } - else - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "calling GNUNET_CONNECTION_receive\n"); - GNUNET_assert (GNUNET_NO == client->in_receive); - client->in_receive = GNUNET_YES; - GNUNET_CONNECTION_receive (client->connection, GNUNET_SERVER_MAX_MESSAGE_SIZE - 1, - timeout, &receive_helper, client); - } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "calling GNUNET_CONNECTION_receive\n"); + GNUNET_assert (GNUNET_NO == client->in_receive); + client->in_receive = GNUNET_YES; + GNUNET_CONNECTION_receive (client->connection, + GNUNET_SERVER_MAX_MESSAGE_SIZE - 1, + timeout, + &receive_helper, + client); } /** * Handle for a test to check if a service is running. */ -struct GNUNET_CLIENT_TestHandle +struct GNUNET_CLIENT_TestHandle { /** * Function to call with the result of the test. @@ -635,13 +683,13 @@ struct GNUNET_CLIENT_TestHandle GNUNET_CLIENT_TestResultCallback cb; /** - * Closure for 'cb'. + * Closure for @e cb. */ void *cb_cls; /** * Client connection we are using for the test, if any. - */ + */ struct GNUNET_CLIENT_Connection *client; /** @@ -650,14 +698,14 @@ struct GNUNET_CLIENT_TestHandle struct GNUNET_CLIENT_TransmitHandle *th; /** - * Deadline for calling 'cb'. + * Deadline for calling @e cb. */ struct GNUNET_TIME_Absolute test_deadline; /** * ID of task used for asynchronous operations. */ - GNUNET_SCHEDULER_TaskIdentifier task; + struct GNUNET_SCHEDULER_Task * task; /** * Final result to report back (once known). @@ -684,10 +732,10 @@ GNUNET_CLIENT_service_test_cancel (struct GNUNET_CLIENT_TestHandle *th) GNUNET_CLIENT_disconnect (th->client); th->client = NULL; } - if (GNUNET_SCHEDULER_NO_TASK != th->task) + if (NULL != th->task) { GNUNET_SCHEDULER_cancel (th->task); - th->task = GNUNET_SCHEDULER_NO_TASK; + th->task = NULL; } GNUNET_free (th); } @@ -697,7 +745,7 @@ GNUNET_CLIENT_service_test_cancel (struct GNUNET_CLIENT_TestHandle *th) * Task that reports back the result by calling the callback * and then cleans up. * - * @param cls the 'struct GNUNET_CLIENT_TestHandle' + * @param cls the `struct GNUNET_CLIENT_TestHandle` * @param tc scheduler context */ static void @@ -705,8 +753,8 @@ report_result (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CLIENT_TestHandle *th = cls; - - th->task = GNUNET_SCHEDULER_NO_TASK; + + th->task = NULL; th->cb (th->cb_cls, th->result); GNUNET_CLIENT_service_test_cancel (th); } @@ -724,18 +772,19 @@ service_test_report (struct GNUNET_CLIENT_TestHandle *th, { th->result = result; th->task = GNUNET_SCHEDULER_add_now (&report_result, - th); + th); } /** * Receive confirmation from test, service is up. * - * @param cls closure with the 'struct GNUNET_CLIENT_TestHandle' + * @param cls closure with the `struct GNUNET_CLIENT_TestHandle` * @param msg message received, NULL on timeout or fatal error */ static void -confirm_handler (void *cls, const struct GNUNET_MessageHeader *msg) +confirm_handler (void *cls, + const struct GNUNET_MessageHeader *msg) { struct GNUNET_CLIENT_TestHandle *th = cls; @@ -759,10 +808,10 @@ confirm_handler (void *cls, const struct GNUNET_MessageHeader *msg) * Send the 'TEST' message to the service. If successful, prepare to * receive the reply. * - * @param cls the 'struct GNUNET_CLIENT_TestHandle' of the test - * @param size number of bytes available in buf + * @param cls the `struct GNUNET_CLIENT_TestHandle` of the test + * @param size number of bytes available in @a buf * @param buf where to write the message - * @return number of bytes written to buf + * @return number of bytes written to @a buf */ static size_t write_test (void *cls, size_t size, void *buf) @@ -773,18 +822,18 @@ write_test (void *cls, size_t size, void *buf) th->th = NULL; if (size < sizeof (struct GNUNET_MessageHeader)) { - LOG (GNUNET_ERROR_TYPE_DEBUG, + LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit TEST request.\n"); service_test_report (th, GNUNET_NO); return 0; /* client disconnected */ } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Transmitting `%s' request.\n", + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Transmitting `%s' request.\n", "TEST"); msg = (struct GNUNET_MessageHeader *) buf; msg->type = htons (GNUNET_MESSAGE_TYPE_TEST); msg->size = htons (sizeof (struct GNUNET_MessageHeader)); - GNUNET_CLIENT_receive (th->client, + GNUNET_CLIENT_receive (th->client, &confirm_handler, th, GNUNET_TIME_absolute_get_remaining (th->test_deadline)); @@ -802,14 +851,15 @@ write_test (void *cls, size_t size, void *buf) * @param cfg configuration to use * @param timeout how long to wait at most * @param cb function to call with the result - * @param cb_cls closure for 'cb' + * @param cb_cls closure for @a cb * @return handle to cancel the test */ struct GNUNET_CLIENT_TestHandle * GNUNET_CLIENT_service_test (const char *service, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TIME_Relative timeout, - GNUNET_CLIENT_TestResultCallback cb, void *cb_cls) + GNUNET_CLIENT_TestResultCallback cb, + void *cb_cls) { struct GNUNET_CLIENT_TestHandle *th; char *hostname; @@ -820,29 +870,48 @@ GNUNET_CLIENT_service_test (const char *service, th->cb = cb; th->cb_cls = cb_cls; th->test_deadline = GNUNET_TIME_relative_to_absolute (timeout); - LOG (GNUNET_ERROR_TYPE_DEBUG, + LOG (GNUNET_ERROR_TYPE_DEBUG, "Testing if service `%s' is running.\n", service); #ifdef AF_UNIX { /* probe UNIX support */ struct sockaddr_un s_un; - size_t slen; char *unixpath; + int abstract; unixpath = NULL; - if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, service, "UNIXPATH", &unixpath)) && (0 < strlen (unixpath))) /* We have a non-NULL unixpath, does that mean it's valid? */ + if ((GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, + service, + "UNIXPATH", + &unixpath)) && + (0 < strlen (unixpath))) /* We have a non-NULL unixpath, does that mean it's valid? */ { if (strlen (unixpath) >= sizeof (s_un.sun_path)) { LOG (GNUNET_ERROR_TYPE_WARNING, - _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath, + _("UNIXPATH `%s' too long, maximum length is %llu\n"), + unixpath, (unsigned long long) sizeof (s_un.sun_path)); unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath); LOG (GNUNET_ERROR_TYPE_INFO, _("Using `%s' instead\n"), unixpath); } } +#ifdef LINUX + abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg, + "TESTING", + "USE_ABSTRACT_SOCKETS"); +#else + abstract = GNUNET_NO; +#endif + if ((NULL != unixpath) && (GNUNET_YES != abstract)) + { + if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (unixpath)) + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, + "mkdir", unixpath); + } if (NULL != unixpath) { sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0); @@ -850,21 +919,15 @@ GNUNET_CLIENT_service_test (const char *service, { memset (&s_un, 0, sizeof (s_un)); s_un.sun_family = AF_UNIX; - slen = strlen (unixpath) + 1; - if (slen >= sizeof (s_un.sun_path)) - slen = sizeof (s_un.sun_path) - 1; - memcpy (s_un.sun_path, unixpath, slen); - s_un.sun_path[slen] = '\0'; - slen = sizeof (struct sockaddr_un); -#if LINUX - s_un.sun_path[0] = '\0'; -#endif + strncpy (s_un.sun_path, unixpath, sizeof (s_un.sun_path) - 1); + if (GNUNET_YES == abstract) + s_un.sun_path[0] = '\0'; #if HAVE_SOCKADDR_IN_SIN_LEN - s_un.sun_len = (u_char) slen; + s_un.sun_len = (u_char) sizeof (struct sockaddr_un); #endif if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un, - slen, GNUNET_BIND_EXCLUSIVE)) + sizeof (struct sockaddr_un))) { /* failed to bind => service must be running */ GNUNET_free (unixpath); @@ -872,7 +935,7 @@ GNUNET_CLIENT_service_test (const char *service, service_test_report (th, GNUNET_YES); return th; } - (void) GNUNET_NETWORK_socket_close (sock); + (void) GNUNET_NETWORK_socket_close (sock); /* let's try IP */ } } @@ -914,7 +977,7 @@ GNUNET_CLIENT_service_test (const char *service, { if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in, - sizeof (s_in), GNUNET_BIND_EXCLUSIVE)) + sizeof (s_in))) { /* failed to bind => service must be running */ GNUNET_free (hostname); @@ -947,7 +1010,7 @@ GNUNET_CLIENT_service_test (const char *service, { if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in6, - sizeof (s_in6), GNUNET_BIND_EXCLUSIVE)) + sizeof (s_in6))) { /* failed to bind => service must be running */ GNUNET_free (hostname); @@ -1003,10 +1066,10 @@ GNUNET_CLIENT_service_test (const char *service, * a transmission request. Either pass it on to our * user or, if possible, retry. * - * @param cls our "struct GNUNET_CLIENT_TransmissionHandle" + * @param cls our `struct GNUNET_CLIENT_TransmissionHandle` * @param size number of bytes available for transmission * @param buf where to write them - * @return number of bytes written to buf + * @return number of bytes written to @a buf */ static size_t client_notify (void *cls, size_t size, void *buf); @@ -1016,16 +1079,17 @@ client_notify (void *cls, size_t size, void *buf); * This task is run if we should re-try connection to the * service after a while. * - * @param cls our "struct GNUNET_CLIENT_TransmitHandle" of the request + * @param cls our `struct GNUNET_CLIENT_TransmitHandle` of the request * @param tc unused */ static void -client_delayed_retry (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +client_delayed_retry (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CLIENT_TransmitHandle *th = cls; struct GNUNET_TIME_Relative delay; - - th->reconnect_task = GNUNET_SCHEDULER_NO_TASK; + + th->reconnect_task = NULL; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { /* give up, was shutdown */ @@ -1035,22 +1099,22 @@ client_delayed_retry (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) return; } th->client->connection = - do_connect (th->client->service_name, th->client->cfg, th->client->attempts++); + do_connect (th->client->service_name, + th->client->cfg, + th->client->attempts++); th->client->first_message = GNUNET_YES; if (NULL == th->client->connection) { /* could happen if we're out of sockets */ - delay = - GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining - (th->timeout), th->client->back_off); - th->client->back_off = - GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply - (th->client->back_off, 2), - GNUNET_TIME_UNIT_SECONDS); + delay = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (th->timeout), + th->client->back_off); + th->client->back_off = GNUNET_TIME_STD_BACKOFF (th->client->back_off); LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed %u times, trying again in %s.\n", MAX_ATTEMPTS - th->attempts_left, GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); + GNUNET_assert (NULL == th->th); + GNUNET_assert (NULL == th->reconnect_task); th->reconnect_task = GNUNET_SCHEDULER_add_delayed (delay, &client_delayed_retry, th); return; @@ -1075,34 +1139,39 @@ client_delayed_retry (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * Connection notifies us about failure or success of a transmission * request. Either pass it on to our user or, if possible, retry. * - * @param cls our "struct GNUNET_CLIENT_TransmissionHandle" + * @param cls our `struct GNUNET_CLIENT_TransmissionHandle` * @param size number of bytes available for transmission * @param buf where to write them - * @return number of bytes written to buf + * @return number of bytes written to @a buf */ static size_t -client_notify (void *cls, size_t size, void *buf) +client_notify (void *cls, + size_t size, + void *buf) { struct GNUNET_CLIENT_TransmitHandle *th = cls; struct GNUNET_CLIENT_Connection *client = th->client; size_t ret; struct GNUNET_TIME_Relative delay; - LOG (GNUNET_ERROR_TYPE_DEBUG, "client_notify is running\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "client_notify is running\n"); th->th = NULL; client->th = NULL; if (NULL == buf) { delay = GNUNET_TIME_absolute_get_remaining (th->timeout); delay.rel_value_us /= 2; - if ((GNUNET_YES != th->auto_retry) || (0 == --th->attempts_left) || - (delay.rel_value_us < 1)|| - (0 != (GNUNET_SCHEDULER_get_reason() & GNUNET_SCHEDULER_REASON_SHUTDOWN))) + if ( (GNUNET_YES != th->auto_retry) || + (0 == --th->attempts_left) || + (delay.rel_value_us < 1)|| + (0 != (GNUNET_SCHEDULER_get_reason() & GNUNET_SCHEDULER_REASON_SHUTDOWN))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed %u times, giving up.\n", MAX_ATTEMPTS - th->attempts_left); - GNUNET_break (0 == th->notify (th->notify_cls, 0, NULL)); + GNUNET_break (0 == + th->notify (th->notify_cls, 0, NULL)); GNUNET_free (th); return 0; } @@ -1114,7 +1183,7 @@ client_notify (void *cls, size_t size, void *buf) { GNUNET_CONNECTION_receive_cancel (client->connection); client->in_receive = GNUNET_NO; - } + } GNUNET_CONNECTION_destroy (client->connection); client->connection = NULL; delay = GNUNET_TIME_relative_min (delay, client->back_off); @@ -1127,6 +1196,8 @@ client_notify (void *cls, size_t size, void *buf) MAX_ATTEMPTS - th->attempts_left, GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); client->th = th; + GNUNET_assert (NULL == th->reconnect_task); + GNUNET_assert (NULL == th->th); th->reconnect_task = GNUNET_SCHEDULER_add_delayed (delay, &client_delayed_retry, th); return 0; @@ -1134,14 +1205,22 @@ client_notify (void *cls, size_t size, void *buf) GNUNET_assert (size >= th->size); ret = th->notify (th->notify_cls, size, buf); GNUNET_free (th); + if (sizeof (struct GNUNET_MessageHeader) <= ret) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Transmitting message of type %u and size %u to %s service.\n", + ntohs (((struct GNUNET_MessageHeader *) buf)->type), + ntohs (((struct GNUNET_MessageHeader *) buf)->size), + client->service_name); + } return ret; } /** * Ask the client to call us once the specified number of bytes - * are free in the transmission buffer. May call the notify - * method immediately if enough space is available. + * are free in the transmission buffer. Will never call the @a notify + * callback in this task, but always first go into the scheduler. * * @param client connection to the service * @param size number of bytes to send @@ -1153,7 +1232,7 @@ client_notify (void *cls, size_t size, void *buf) * if the caller does not care about temporary connection errors, * for example because the protocol is stateless * @param notify function to call - * @param notify_cls closure for notify + * @param notify_cls closure for @a notify * @return NULL if our buffer will never hold size bytes, * a handle if the notify callback was queued (can be used to cancel) */ @@ -1162,8 +1241,8 @@ GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client, size_t size, struct GNUNET_TIME_Relative timeout, int auto_retry, - GNUNET_CONNECTION_TransmitReadyNotify - notify, void *notify_cls) + GNUNET_CONNECTION_TransmitReadyNotify notify, + void *notify_cls) { struct GNUNET_CLIENT_TransmitHandle *th; @@ -1171,10 +1250,10 @@ GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client, { /* If this breaks, you most likley called this function twice without waiting * for completion or canceling the request */ - GNUNET_break (0); + GNUNET_assert (0); return NULL; } - th = GNUNET_malloc (sizeof (struct GNUNET_CLIENT_TransmitHandle)); + th = GNUNET_new (struct GNUNET_CLIENT_TransmitHandle); th->client = client; th->size = size; th->timeout = GNUNET_TIME_relative_to_absolute (timeout); @@ -1187,16 +1266,20 @@ GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client, client->th = th; if (NULL == client->connection) { + GNUNET_assert (NULL == th->th); + GNUNET_assert (NULL == th->reconnect_task); th->reconnect_task = - GNUNET_SCHEDULER_add_delayed (client->back_off, &client_delayed_retry, + GNUNET_SCHEDULER_add_delayed (client->back_off, + &client_delayed_retry, th); - } else { - th->th = - GNUNET_CONNECTION_notify_transmit_ready (client->connection, size, timeout, - &client_notify, th); + th->th = GNUNET_CONNECTION_notify_transmit_ready (client->connection, + size, + timeout, + &client_notify, + th); if (NULL == th->th) { GNUNET_break (0); @@ -1215,14 +1298,13 @@ GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client, * @param th handle from the original request. */ void -GNUNET_CLIENT_notify_transmit_ready_cancel (struct GNUNET_CLIENT_TransmitHandle - *th) +GNUNET_CLIENT_notify_transmit_ready_cancel (struct GNUNET_CLIENT_TransmitHandle *th) { - if (GNUNET_SCHEDULER_NO_TASK != th->reconnect_task) + if (NULL != th->reconnect_task) { GNUNET_assert (NULL == th->th); GNUNET_SCHEDULER_cancel (th->reconnect_task); - th->reconnect_task = GNUNET_SCHEDULER_NO_TASK; + th->reconnect_task = NULL; } else { @@ -1236,17 +1318,19 @@ GNUNET_CLIENT_notify_transmit_ready_cancel (struct GNUNET_CLIENT_TransmitHandle /** * Function called to notify a client about the socket - * begin ready to queue the message. "buf" will be - * NULL and "size" zero if the socket was closed for + * begin ready to queue the message. @a buf will be + * NULL and @a size zero if the socket was closed for * writing in the meantime. * - * @param cls closure of type "struct TransmitGetResponseContext*" - * @param size number of bytes available in buf + * @param cls closure of type `struct TransmitGetResponseContext *` + * @param size number of bytes available in @a buf * @param buf where the callee should write the message - * @return number of bytes written to buf + * @return number of bytes written to @a buf */ static size_t -transmit_for_response (void *cls, size_t size, void *buf) +transmit_for_response (void *cls, + size_t size, + void *buf) { struct TransmitGetResponseContext *tc = cls; uint16_t msize; @@ -1256,7 +1340,7 @@ transmit_for_response (void *cls, size_t size, void *buf) if (NULL == buf) { LOG (GNUNET_ERROR_TYPE_DEBUG, - _("Could not submit request, not expecting to receive a response.\n")); + "Could not submit request, not expecting to receive a response.\n"); if (NULL != tc->rn) tc->rn (tc->rn_cls, NULL); GNUNET_free (tc); @@ -1264,7 +1348,9 @@ transmit_for_response (void *cls, size_t size, void *buf) } GNUNET_assert (size >= msize); memcpy (buf, tc->hdr, msize); - GNUNET_CLIENT_receive (tc->client, tc->rn, tc->rn_cls, + GNUNET_CLIENT_receive (tc->client, + tc->rn, + tc->rn_cls, GNUNET_TIME_absolute_get_remaining (tc->timeout)); GNUNET_free (tc); return msize; @@ -1288,8 +1374,8 @@ transmit_for_response (void *cls, size_t size, void *buf) * if the caller does not care about temporary connection errors, * for example because the protocol is stateless * @param rn function to call with the response - * @param rn_cls closure for rn - * @return GNUNET_OK on success, GNUNET_SYSERR if a request + * @param rn_cls closure for @a rn + * @return #GNUNET_OK on success, #GNUNET_SYSERR if a request * is already pending */ int