aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-10-21 05:23:21 +0000
committerChristian Grothoff <christian@grothoff.org>2016-10-21 05:23:21 +0000
commit4bcb854976f9f86f3b05e519542015bc2f14d484 (patch)
tree51f44dc747052f5a63f97066b4707dfd30221d9e /src/util
parente9a6c28aad064456c26923cf579f0ed9282afe3c (diff)
downloadgnunet-4bcb854976f9f86f3b05e519542015bc2f14d484.tar.gz
gnunet-4bcb854976f9f86f3b05e519542015bc2f14d484.zip
misc fixes to new client impl
Diffstat (limited to 'src/util')
-rw-r--r--src/util/Makefile.am5
-rw-r--r--src/util/client_new.c221
2 files changed, 126 insertions, 100 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 2325874b2..776927219 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -60,6 +60,7 @@ libgnunetutil_la_SOURCES = \
60 bandwidth.c \ 60 bandwidth.c \
61 bio.c \ 61 bio.c \
62 client.c \ 62 client.c \
63 client_new.c \
63 common_allocation.c \ 64 common_allocation.c \
64 common_endian.c \ 65 common_endian.c \
65 common_logging.c \ 66 common_logging.c \
@@ -325,13 +326,13 @@ check_PROGRAMS = \
325# Declare .nc (NO-CONCURRENCY) as a test extension so that we can impart 326# Declare .nc (NO-CONCURRENCY) as a test extension so that we can impart
326# sequential execution order for them 327# sequential execution order for them
327TEST_EXTENSIONS = .nc 328TEST_EXTENSIONS = .nc
328test_connection.log: test_client.log 329test_connection.log: test_client.log
329test_connection_addressing.log: test_connection.log 330test_connection_addressing.log: test_connection.log
330test_connection_timeout_no_connect.log: test_connection_addressing.log 331test_connection_timeout_no_connect.log: test_connection_addressing.log
331test_connection_transmit_cancel.log: test_connection_timeout_no_connect.log 332test_connection_transmit_cancel.log: test_connection_timeout_no_connect.log
332test_connection_receive_cancel.log: test_connection_transmit_cancel.log 333test_connection_receive_cancel.log: test_connection_transmit_cancel.log
333test_connection_timeout.log: test_connection_receive_cancel.log 334test_connection_timeout.log: test_connection_receive_cancel.log
334test_resolver_api.log: test_connection_timeout.log 335test_resolver_api.log: test_connection_timeout.log
335test_server.log: test_resolver_api.log 336test_server.log: test_resolver_api.log
336test_server_disconnect.log: test_server.log 337test_server_disconnect.log: test_server.log
337test_server_with_client.log: test_server_disconnect.log 338test_server_with_client.log: test_server_disconnect.log
diff --git a/src/util/client_new.c b/src/util/client_new.c
index b5c0147b3..d2b70388c 100644
--- a/src/util/client_new.c
+++ b/src/util/client_new.c
@@ -29,16 +29,10 @@
29#include "platform.h" 29#include "platform.h"
30#include "gnunet_protocols.h" 30#include "gnunet_protocols.h"
31#include "gnunet_util_lib.h" 31#include "gnunet_util_lib.h"
32#include "gnunet_resolver_service.h"
32#include "gnunet_socks.h" 33#include "gnunet_socks.h"
33 34
34 35
35/**
36 * How often do we re-try tranmsitting requests before giving up?
37 * Note that if we succeeded transmitting a request but failed to read
38 * a response, we do NOT re-try.
39 */
40#define MAX_ATTEMPTS 50
41
42#define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__) 36#define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__)
43 37
44 38
@@ -161,6 +155,11 @@ struct ClientState
161 struct GNUNET_MessageStreamTokenizer *mst; 155 struct GNUNET_MessageStreamTokenizer *mst;
162 156
163 /** 157 /**
158 * Message queue under our control.
159 */
160 struct GNUNET_MQ_Handle *mq;
161
162 /**
164 * Timeout for receiving a response (absolute time). 163 * Timeout for receiving a response (absolute time).
165 */ 164 */
166 struct GNUNET_TIME_Absolute receive_timeout; 165 struct GNUNET_TIME_Absolute receive_timeout;
@@ -182,14 +181,16 @@ struct ClientState
182 size_t msg_off; 181 size_t msg_off;
183 182
184 /** 183 /**
185 * Is this the first message we are sending to the service? 184 * How often have we tried to connect?
186 */ 185 */
187 int first_message; 186 unsigned int attempts;
188 187
189 /** 188 /**
190 * How often have we tried to connect? 189 * Are we supposed to die? #GNUNET_SYSERR if destruction must be
190 * deferred, #GNUNET_NO by default, #GNUNET_YES if destruction was
191 * deferred.
191 */ 192 */
192 unsigned int attempts; 193 int in_destroy;
193 194
194}; 195};
195 196
@@ -220,11 +221,13 @@ connect_fail_continuation (struct ClientState *cstate)
220 GNUNET_break (NULL == cstate->ap_tail); 221 GNUNET_break (NULL == cstate->ap_tail);
221 GNUNET_break (NULL == cstate->dns_active); 222 GNUNET_break (NULL == cstate->dns_active);
222 GNUNET_break (NULL == cstate->sock); 223 GNUNET_break (NULL == cstate->sock);
223 GNUNET_assert (NULL == cstate->write_task); 224 GNUNET_assert (NULL == cstate->send_task);
225 GNUNET_assert (NULL == cstate->recv_task);
224 // GNUNET_assert (NULL == cstate->proxy_handshake); 226 // GNUNET_assert (NULL == cstate->proxy_handshake);
225 227
228 cstate->back_off = GNUNET_TIME_STD_BACKOFF (cstate->back_off);
226 cstate->retry_task 229 cstate->retry_task
227 = GNUNET_SCHEDULER_add_delayed (cstate->retry_delay, 230 = GNUNET_SCHEDULER_add_delayed (cstate->back_off,
228 &start_connect, 231 &start_connect,
229 cstate); 232 cstate);
230} 233}
@@ -263,7 +266,7 @@ transmit_ready (void *cls)
263 { 266 {
264 GNUNET_MQ_impl_send_in_flight (cstate->mq); 267 GNUNET_MQ_impl_send_in_flight (cstate->mq);
265 } 268 }
266 cstate->msg_off += pos; 269 cstate->msg_off += ret;
267 if (cstate->msg_off < len) 270 if (cstate->msg_off < len)
268 { 271 {
269 cstate->send_task 272 cstate->send_task
@@ -284,15 +287,81 @@ transmit_ready (void *cls)
284 * 287 *
285 * @param cls the `struct ClientState` 288 * @param cls the `struct ClientState`
286 * @param msg message we received. 289 * @param msg message we received.
290 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
287 */ 291 */
288static void 292static int
289recv_message (void *cls, 293recv_message (void *cls,
290 const struct GNUNET_MessageHeader *msg) 294 const struct GNUNET_MessageHeader *msg)
291{ 295{
292 struct ClientState *cstate = cls; 296 struct ClientState *cstate = cls;
293 297
298 if (GNUNET_YES == cstate->in_destroy)
299 return GNUNET_SYSERR;
294 GNUNET_MQ_inject_message (cstate->mq, 300 GNUNET_MQ_inject_message (cstate->mq,
295 msg); 301 msg);
302 if (GNUNET_YES == cstate->in_destroy)
303 return GNUNET_SYSERR;
304 return GNUNET_OK;
305}
306
307
308/**
309 * Cancel all remaining connect attempts
310 *
311 * @param cstate handle of the client state to process
312 */
313static void
314cancel_aps (struct ClientState *cstate)
315{
316 struct AddressProbe *pos;
317
318 while (NULL != (pos = cstate->ap_head))
319 {
320 GNUNET_break (GNUNET_OK ==
321 GNUNET_NETWORK_socket_close (pos->sock));
322 GNUNET_SCHEDULER_cancel (pos->task);
323 GNUNET_CONTAINER_DLL_remove (cstate->ap_head,
324 cstate->ap_tail,
325 pos);
326 GNUNET_free (pos);
327 }
328}
329
330
331/**
332 * Implement the destruction of a message queue. Implementations must
333 * not free @a mq, but should take care of @a impl_state.
334 *
335 * @param mq the message queue to destroy
336 * @param impl_state our `struct ClientState`
337 */
338static void
339connection_client_destroy_impl (struct GNUNET_MQ_Handle *mq,
340 void *impl_state)
341{
342 struct ClientState *cstate = impl_state;
343
344 if (GNUNET_SYSERR == cstate->in_destroy)
345 {
346 /* defer destruction */
347 cstate->in_destroy = GNUNET_YES;
348 return;
349 }
350 if (NULL != cstate->dns_active)
351 GNUNET_RESOLVER_request_cancel (cstate->dns_active);
352 if (NULL != cstate->send_task)
353 GNUNET_SCHEDULER_cancel (cstate->send_task);
354 if (NULL != cstate->recv_task)
355 GNUNET_SCHEDULER_cancel (cstate->recv_task);
356 if (NULL != cstate->retry_task)
357 GNUNET_SCHEDULER_cancel (cstate->retry_task);
358 if (NULL != cstate->sock)
359 GNUNET_NETWORK_socket_close (cstate->sock);
360 cancel_aps (cstate);
361 GNUNET_free (cstate->service_name);
362 GNUNET_free_non_null (cstate->hostname);
363 GNUNET_MST_destroy (cstate->mst);
364 GNUNET_free (cstate);
296} 365}
297 366
298 367
@@ -305,11 +374,11 @@ static void
305receive_ready (void *cls) 374receive_ready (void *cls)
306{ 375{
307 struct ClientState *cstate = cls; 376 struct ClientState *cstate = cls;
308 const struct GNUNET_SCHEDULER_TaskContext *tc;
309 int ret; 377 int ret;
310 378
311 connection->recv_task = NULL; 379 cstate->recv_task = NULL;
312 ret = GNUNET_MST_read (cstate->msg, 380 cstate->in_destroy = GNUNET_SYSERR;
381 ret = GNUNET_MST_read (cstate->mst,
313 cstate->sock, 382 cstate->sock,
314 GNUNET_NO, 383 GNUNET_NO,
315 GNUNET_NO); 384 GNUNET_NO);
@@ -319,6 +388,13 @@ receive_ready (void *cls)
319 GNUNET_MQ_ERROR_READ); 388 GNUNET_MQ_ERROR_READ);
320 return; 389 return;
321 } 390 }
391 if (GNUNET_YES == cstate->in_destroy)
392 {
393 connection_client_destroy_impl (cstate->mq,
394 cstate);
395 return;
396 }
397 cstate->in_destroy = GNUNET_NO;
322 cstate->recv_task 398 cstate->recv_task
323 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, 399 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
324 cstate->sock, 400 cstate->sock,
@@ -335,7 +411,7 @@ receive_ready (void *cls)
335static void 411static void
336connect_success_continuation (struct ClientState *cstate) 412connect_success_continuation (struct ClientState *cstate)
337{ 413{
338 GNUNET_assert (NULL == connection->read_task); 414 GNUNET_assert (NULL == cstate->recv_task);
339 cstate->recv_task 415 cstate->recv_task
340 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, 416 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
341 cstate->sock, 417 cstate->sock,
@@ -391,13 +467,13 @@ try_unixpath (const char *service_name,
391 if (NULL == unixpath) 467 if (NULL == unixpath)
392 return NULL; 468 return NULL;
393 } 469 }
394 memset (&un, 470 memset (&s_un,
395 0, 471 0,
396 sizeof (un)); 472 sizeof (s_un));
397 un.sun_family = AF_UNIX; 473 s_un.sun_family = AF_UNIX;
398 strncpy (un.sun_path, 474 strncpy (s_un.sun_path,
399 unixpath, 475 unixpath,
400 sizeof (un->sun_path) - 1); 476 sizeof (s_un.sun_path) - 1);
401#ifdef LINUX 477#ifdef LINUX
402 { 478 {
403 int abstract; 479 int abstract;
@@ -406,7 +482,7 @@ try_unixpath (const char *service_name,
406 "TESTING", 482 "TESTING",
407 "USE_ABSTRACT_SOCKETS"); 483 "USE_ABSTRACT_SOCKETS");
408 if (GNUNET_YES == abstract) 484 if (GNUNET_YES == abstract)
409 un.sun_path[0] = '\0'; 485 s_un.sun_path[0] = '\0';
410 } 486 }
411#endif 487#endif
412#if HAVE_SOCKADDR_IN_SIN_LEN 488#if HAVE_SOCKADDR_IN_SIN_LEN
@@ -417,8 +493,8 @@ try_unixpath (const char *service_name,
417 0); 493 0);
418 if ( (GNUNET_OK == 494 if ( (GNUNET_OK ==
419 GNUNET_NETWORK_socket_connect (sock, 495 GNUNET_NETWORK_socket_connect (sock,
420 (struct sockaddr *) &un, 496 (struct sockaddr *) &s_un,
421 sizeof (un))) || 497 sizeof (s_un))) ||
422 (EINPROGRESS == errno) ) 498 (EINPROGRESS == errno) )
423 { 499 {
424 LOG (GNUNET_ERROR_TYPE_DEBUG, 500 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -435,29 +511,6 @@ try_unixpath (const char *service_name,
435 511
436 512
437/** 513/**
438 * Cancel all remaining connect attempts
439 *
440 * @param cstate handle of the client state to process
441 */
442static void
443cancel_aps (struct ClientState *cstate)
444{
445 struct AddressProbe *pos;
446
447 while (NULL != (pos = cstate->ap_head))
448 {
449 GNUNET_break (GNUNET_OK ==
450 GNUNET_NETWORK_socket_close (pos->sock));
451 GNUNET_SCHEDULER_cancel (pos->task);
452 GNUNET_CONTAINER_DLL_remove (cstate->ap_head,
453 cstate->ap_tail,
454 pos);
455 GNUNET_free (pos);
456 }
457}
458
459
460/**
461 * Scheduler let us know that we're either ready to write on the 514 * Scheduler let us know that we're either ready to write on the
462 * socket OR connect timed out. Do the right thing. 515 * socket OR connect timed out. Do the right thing.
463 * 516 *
@@ -467,15 +520,15 @@ static void
467connect_probe_continuation (void *cls) 520connect_probe_continuation (void *cls)
468{ 521{
469 struct AddressProbe *ap = cls; 522 struct AddressProbe *ap = cls;
470 struct ClientState *cstate *connection = ap->cstate; 523 struct ClientState *cstate = ap->cstate;
471 const struct GNUNET_SCHEDULER_TaskContext *tc; 524 const struct GNUNET_SCHEDULER_TaskContext *tc;
472 int error; 525 int error;
473 socklen_t len; 526 socklen_t len;
474 527
475 ap->task = NULL; 528 ap->task = NULL;
476 GNUNET_assert (NULL != ap->sock); 529 GNUNET_assert (NULL != ap->sock);
477 GNUNET_CONTAINER_DLL_remove (connection->ap_head, 530 GNUNET_CONTAINER_DLL_remove (cstate->ap_head,
478 connection->ap_tail, 531 cstate->ap_tail,
479 ap); 532 ap);
480 len = sizeof (error); 533 len = sizeof (error);
481 error = 0; 534 error = 0;
@@ -500,8 +553,7 @@ connect_probe_continuation (void *cls)
500 } 553 }
501 LOG (GNUNET_ERROR_TYPE_DEBUG, 554 LOG (GNUNET_ERROR_TYPE_DEBUG,
502 "Connection to `%s' succeeded!\n", 555 "Connection to `%s' succeeded!\n",
503 GNUNET_a2s (cstate->addr, 556 cstate->service_name);
504 cstate->addrlen));
505 /* trigger jobs that waited for the connection */ 557 /* trigger jobs that waited for the connection */
506 GNUNET_assert (NULL == cstate->sock); 558 GNUNET_assert (NULL == cstate->sock);
507 cstate->sock = ap->sock; 559 cstate->sock = ap->sock;
@@ -515,7 +567,7 @@ connect_probe_continuation (void *cls)
515 * Try to establish a connection given the specified address. 567 * Try to establish a connection given the specified address.
516 * This function is called by the resolver once we have a DNS reply. 568 * This function is called by the resolver once we have a DNS reply.
517 * 569 *
518 * @param cls our `struct GNUNET_CONNECTION_Handle *` 570 * @param cls our `struct ClientState *`
519 * @param addr address to try, NULL for "last call" 571 * @param addr address to try, NULL for "last call"
520 * @param addrlen length of @a addr 572 * @param addrlen length of @a addr
521 */ 573 */
@@ -526,7 +578,6 @@ try_connect_using_address (void *cls,
526{ 578{
527 struct ClientState *cstate = cls; 579 struct ClientState *cstate = cls;
528 struct AddressProbe *ap; 580 struct AddressProbe *ap;
529 struct GNUNET_TIME_Relative delay;
530 581
531 if (NULL == addr) 582 if (NULL == addr)
532 { 583 {
@@ -544,22 +595,22 @@ try_connect_using_address (void *cls,
544 "Trying to connect using address `%s:%u'\n", 595 "Trying to connect using address `%s:%u'\n",
545 GNUNET_a2s (addr, 596 GNUNET_a2s (addr,
546 addrlen), 597 addrlen),
547 connection->port); 598 cstate->port);
548 ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen); 599 ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen);
549 ap->addr = (const struct sockaddr *) &ap[1]; 600 ap->addr = (const struct sockaddr *) &ap[1];
550 GNUNET_memcpy (&ap[1], 601 GNUNET_memcpy (&ap[1],
551 addr, 602 addr,
552 addrlen); 603 addrlen);
553 ap->addrlen = addrlen; 604 ap->addrlen = addrlen;
554 ap->connection = connection; 605 ap->cstate = cstate;
555 606
556 switch (ap->addr->sa_family) 607 switch (ap->addr->sa_family)
557 { 608 {
558 case AF_INET: 609 case AF_INET:
559 ((struct sockaddr_in *) ap->addr)->sin_port = htons (connection->port); 610 ((struct sockaddr_in *) ap->addr)->sin_port = htons (cstate->port);
560 break; 611 break;
561 case AF_INET6: 612 case AF_INET6:
562 ((struct sockaddr_in6 *) ap->addr)->sin6_port = htons (connection->port); 613 ((struct sockaddr_in6 *) ap->addr)->sin6_port = htons (cstate->port);
563 break; 614 break;
564 default: 615 default:
565 GNUNET_break (0); 616 GNUNET_break (0);
@@ -581,15 +632,15 @@ try_connect_using_address (void *cls,
581 (EINPROGRESS != errno) ) 632 (EINPROGRESS != errno) )
582 { 633 {
583 /* maybe refused / unsupported address, try next */ 634 /* maybe refused / unsupported address, try next */
584 LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, 635 GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO,
585 "connect"); 636 "connect");
586 GNUNET_break (GNUNET_OK == 637 GNUNET_break (GNUNET_OK ==
587 GNUNET_NETWORK_socket_close (ap->sock)); 638 GNUNET_NETWORK_socket_close (ap->sock));
588 GNUNET_free (ap); 639 GNUNET_free (ap);
589 return; 640 return;
590 } 641 }
591 GNUNET_CONTAINER_DLL_insert (connection->ap_head, 642 GNUNET_CONTAINER_DLL_insert (cstate->ap_head,
592 connection->ap_tail, 643 cstate->ap_tail,
593 ap); 644 ap);
594 ap->task = GNUNET_SCHEDULER_add_write_net (GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT, 645 ap->task = GNUNET_SCHEDULER_add_write_net (GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
595 ap->sock, 646 ap->sock,
@@ -663,8 +714,8 @@ start_connect (void *cls)
663#if 0 714#if 0
664 /* Never use a local source if a proxy is configured */ 715 /* Never use a local source if a proxy is configured */
665 if (GNUNET_YES == 716 if (GNUNET_YES ==
666 GNUNET_SOCKS_check_service (service_name, 717 GNUNET_SOCKS_check_service (cstate->service_name,
667 cfg)) 718 cstate->cfg))
668 { 719 {
669 socks_connect (cstate); 720 socks_connect (cstate);
670 return; 721 return;
@@ -675,8 +726,8 @@ start_connect (void *cls)
675 (0 == cstate->port) ) 726 (0 == cstate->port) )
676 { 727 {
677 /* on even rounds, try UNIX first */ 728 /* on even rounds, try UNIX first */
678 cstate->sock = try_unixpath (service_name, 729 cstate->sock = try_unixpath (cstate->service_name,
679 cfg); 730 cstate->cfg);
680 if (NULL != cstate->sock) 731 if (NULL != cstate->sock)
681 { 732 {
682 connect_success_continuation (cstate); 733 connect_success_continuation (cstate);
@@ -689,33 +740,6 @@ start_connect (void *cls)
689 GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT, 740 GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
690 &try_connect_using_address, 741 &try_connect_using_address,
691 cstate); 742 cstate);
692 return connection;
693}
694
695
696
697/**
698 * Implement the destruction of a message queue. Implementations must
699 * not free @a mq, but should take care of @a impl_state.
700 *
701 * @param mq the message queue to destroy
702 * @param impl_state our `struct ClientState`
703 */
704static void
705connection_client_destroy_impl (struct GNUNET_MQ_Handle *mq,
706 void *impl_state)
707{
708 struct ClientState *cstate = impl_state;
709
710 if (NULL != cstate->dns_active)
711 GNUNET_RESOLVER_ip_get_cancel (cstate->dns_active);
712 if (NULL != cstate->sock)
713 GNUNET_NETWORK_socket_close (cstate->sock);
714 cancel_aps (cstate);
715 GNUNET_free (cstate->service_name);
716 GNUNET_free_non_null (cstate->hostname);
717 GNUNET_MST_destroy (cstate->mst);
718 GNUNET_free (cstate);
719} 743}
720 744
721 745
@@ -770,7 +794,8 @@ connection_client_cancel_impl (struct GNUNET_MQ_Handle *mq,
770 * Create a message queue to connect to a GNUnet service. 794 * Create a message queue to connect to a GNUnet service.
771 * If handlers are specfied, receive messages from the connection. 795 * If handlers are specfied, receive messages from the connection.
772 * 796 *
773 * @param connection the client connection 797 * @param cfg our configuration
798 * @param service_name name of the service to connect to
774 * @param handlers handlers for receiving messages, can be NULL 799 * @param handlers handlers for receiving messages, can be NULL
775 * @param error_handler error handler 800 * @param error_handler error handler
776 * @param error_handler_cls closure for the @a error_handler 801 * @param error_handler_cls closure for the @a error_handler
@@ -794,7 +819,7 @@ GNUNET_CLIENT_connecT2 (const struct GNUNET_CONFIGURATION_Handle *cfg,
794 cstate->cfg = cfg; 819 cstate->cfg = cfg;
795 cstate->retry_task = GNUNET_SCHEDULER_add_now (&start_connect, 820 cstate->retry_task = GNUNET_SCHEDULER_add_now (&start_connect,
796 cstate); 821 cstate);
797 cstate->msg = GNUNET_MST_create (&recv_message, 822 cstate->mst = GNUNET_MST_create (&recv_message,
798 cstate); 823 cstate);
799 if (GNUNET_YES == 824 if (GNUNET_YES ==
800 GNUNET_CONFIGURATION_have_value (cfg, 825 GNUNET_CONFIGURATION_have_value (cfg,