X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fclient.c;h=d87be74f6d943c1bfdc072906ca6fe8a523b3919;hb=ed28dd2141e77aa073d81089cb5a07e0a0fc013c;hp=15d52ec60e6b7113dbd8715b5dcca53f7b431029;hpb=10ae843114fd76b94cf684fd4347e7ece49dd57c;p=oweals%2Fgnunet.git diff --git a/src/util/client.c b/src/util/client.c index 15d52ec60..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" /** @@ -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. @@ -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; @@ -337,6 +340,10 @@ do_connect (const char *service_name, 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)) { @@ -457,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) { @@ -504,8 +511,12 @@ check_complete (struct GNUNET_CLIENT_Connection *client) * @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; @@ -515,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; } @@ -565,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; @@ -576,12 +594,22 @@ receive_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) char mbuf[msize] GNUNET_ALIGN; struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) mbuf; + 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); - client->receive_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (GNUNET_YES == client->msg_complete); GNUNET_assert (client->received_pos >= msize); memcpy (msg, cmsg, msize); @@ -613,27 +641,34 @@ GNUNET_CLIENT_receive (struct GNUNET_CLIENT_Connection *client, 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); } @@ -670,7 +705,7 @@ struct GNUNET_CLIENT_TestHandle /** * ID of task used for asynchronous operations. */ - GNUNET_SCHEDULER_TaskIdentifier task; + struct GNUNET_SCHEDULER_Task * task; /** * Final result to report back (once known). @@ -697,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); } @@ -719,7 +754,7 @@ report_result (void *cls, { 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); } @@ -748,7 +783,8 @@ service_test_report (struct GNUNET_CLIENT_TestHandle *th, * @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; @@ -1033,7 +1069,7 @@ GNUNET_CLIENT_service_test (const char *service, * @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); @@ -1053,7 +1089,7 @@ client_delayed_retry (void *cls, 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 */ @@ -1070,18 +1106,15 @@ client_delayed_retry (void *cls, 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 (GNUNET_SCHEDULER_NO_TASK == th->reconnect_task); + GNUNET_assert (NULL == th->th); + GNUNET_assert (NULL == th->reconnect_task); th->reconnect_task = GNUNET_SCHEDULER_add_delayed (delay, &client_delayed_retry, th); return; @@ -1112,7 +1145,9 @@ client_delayed_retry (void *cls, * @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; @@ -1127,14 +1162,16 @@ client_notify (void *cls, size_t size, void *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; } @@ -1159,7 +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 (GNUNET_SCHEDULER_NO_TASK == th->reconnect_task); + 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; @@ -1212,7 +1250,7 @@ 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_new (struct GNUNET_CLIENT_TransmitHandle); @@ -1228,18 +1266,20 @@ GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client, client->th = th; if (NULL == client->connection) { - GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == th->reconnect_task); + GNUNET_assert (NULL == th->th); + GNUNET_assert (NULL == th->reconnect_task); th->reconnect_task = 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); @@ -1260,11 +1300,11 @@ GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client, void 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 { @@ -1282,7 +1322,7 @@ GNUNET_CLIENT_notify_transmit_ready_cancel (struct GNUNET_CLIENT_TransmitHandle * NULL and @a size zero if the socket was closed for * writing in the meantime. * - * @param cls closure of type "struct TransmitGetResponseContext*" + * @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 @a buf @@ -1300,7 +1340,7 @@ transmit_for_response (void *cls, 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); @@ -1308,7 +1348,9 @@ transmit_for_response (void *cls, } 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;