diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-04-21 15:16:45 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-04-21 15:16:45 +0000 |
commit | a5ca53b73e643a0e62ded4ac9595bff38d08cb0b (patch) | |
tree | eaf74f5b38c35e1530f9d49946db01a13cce3217 /src/util/connection.c | |
parent | 90c9abc573f95de334a1f61faa089e79046d2f11 (diff) | |
download | gnunet-a5ca53b73e643a0e62ded4ac9595bff38d08cb0b.tar.gz gnunet-a5ca53b73e643a0e62ded4ac9595bff38d08cb0b.zip |
-misc offline hacking / code cleanup in util
Diffstat (limited to 'src/util/connection.c')
-rw-r--r-- | src/util/connection.c | 551 |
1 files changed, 217 insertions, 334 deletions
diff --git a/src/util/connection.c b/src/util/connection.c index 95c8347d0..1e792adc8 100644 --- a/src/util/connection.c +++ b/src/util/connection.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2009 Christian Grothoff (and other contributing authors) | 3 | (C) 2009, 2012 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -44,28 +44,6 @@ | |||
44 | 44 | ||
45 | #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) | 45 | #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) |
46 | 46 | ||
47 | /** | ||
48 | * Possible functions to call after connect failed or succeeded. | ||
49 | */ | ||
50 | enum ConnectContinuations | ||
51 | { | ||
52 | /** | ||
53 | * Call nothing. | ||
54 | */ | ||
55 | COCO_NONE = 0, | ||
56 | |||
57 | /** | ||
58 | * Call "receive_again". | ||
59 | */ | ||
60 | COCO_RECEIVE_AGAIN = 1, | ||
61 | |||
62 | /** | ||
63 | * Call "transmit_ready". | ||
64 | */ | ||
65 | COCO_TRANSMIT_READY = 2 | ||
66 | |||
67 | }; | ||
68 | |||
69 | 47 | ||
70 | /** | 48 | /** |
71 | * Transmission handle. There can only be one for each connection. | 49 | * Transmission handle. There can only be one for each connection. |
@@ -254,21 +232,11 @@ struct GNUNET_CONNECTION_Handle | |||
254 | struct GNUNET_TIME_Absolute receive_timeout; | 232 | struct GNUNET_TIME_Absolute receive_timeout; |
255 | 233 | ||
256 | /** | 234 | /** |
257 | * Functions to call after connect failed or succeeded. | ||
258 | */ | ||
259 | enum ConnectContinuations ccs; | ||
260 | |||
261 | /** | ||
262 | * Maximum number of bytes to read (for receiving). | 235 | * Maximum number of bytes to read (for receiving). |
263 | */ | 236 | */ |
264 | size_t max; | 237 | size_t max; |
265 | 238 | ||
266 | /** | 239 | /** |
267 | * Ignore GNUNET_SCHEDULER_REASON_SHUTDOWN for this connection. | ||
268 | */ | ||
269 | int ignore_shutdown; | ||
270 | |||
271 | /** | ||
272 | * Port to connect to. | 240 | * Port to connect to. |
273 | */ | 241 | */ |
274 | uint16_t port; | 242 | uint16_t port; |
@@ -283,6 +251,7 @@ struct GNUNET_CONNECTION_Handle | |||
283 | 251 | ||
284 | }; | 252 | }; |
285 | 253 | ||
254 | |||
286 | /** | 255 | /** |
287 | * Set the persist option on this connection handle. Indicates | 256 | * Set the persist option on this connection handle. Indicates |
288 | * that the underlying socket or fd should never really be closed. | 257 | * that the underlying socket or fd should never really be closed. |
@@ -361,7 +330,6 @@ GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access, | |||
361 | void *uaddr; | 330 | void *uaddr; |
362 | struct GNUNET_CONNECTION_Credentials *gcp; | 331 | struct GNUNET_CONNECTION_Credentials *gcp; |
363 | struct GNUNET_CONNECTION_Credentials gc; | 332 | struct GNUNET_CONNECTION_Credentials gc; |
364 | |||
365 | #ifdef SO_PEERCRED | 333 | #ifdef SO_PEERCRED |
366 | struct ucred uc; | 334 | struct ucred uc; |
367 | socklen_t olen; | 335 | socklen_t olen; |
@@ -384,7 +352,7 @@ GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access, | |||
384 | 352 | ||
385 | sa = (struct sockaddr *) addr; | 353 | sa = (struct sockaddr *) addr; |
386 | v6 = (struct sockaddr_in6 *) addr; | 354 | v6 = (struct sockaddr_in6 *) addr; |
387 | if ((sa->sa_family == AF_INET6) && (IN6_IS_ADDR_V4MAPPED (&v6->sin6_addr))) | 355 | if ((AF_INET6 == sa->sa_family) && (IN6_IS_ADDR_V4MAPPED (&v6->sin6_addr))) |
388 | { | 356 | { |
389 | /* convert to V4 address */ | 357 | /* convert to V4 address */ |
390 | v4 = GNUNET_malloc (sizeof (struct sockaddr_in)); | 358 | v4 = GNUNET_malloc (sizeof (struct sockaddr_in)); |
@@ -409,7 +377,7 @@ GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access, | |||
409 | gcp = NULL; | 377 | gcp = NULL; |
410 | gc.uid = 0; | 378 | gc.uid = 0; |
411 | gc.gid = 0; | 379 | gc.gid = 0; |
412 | if (sa->sa_family == AF_UNIX) | 380 | if (AF_UNIX == sa->sa_family) |
413 | { | 381 | { |
414 | #if HAVE_GETPEEREID | 382 | #if HAVE_GETPEEREID |
415 | /* most BSDs */ | 383 | /* most BSDs */ |
@@ -445,10 +413,10 @@ GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access, | |||
445 | #endif | 413 | #endif |
446 | } | 414 | } |
447 | 415 | ||
448 | if ((access != NULL) && | 416 | if ((NULL != access) && |
449 | (GNUNET_YES != (aret = access (access_cls, gcp, uaddr, addrlen)))) | 417 | (GNUNET_YES != (aret = access (access_cls, gcp, uaddr, addrlen)))) |
450 | { | 418 | { |
451 | if (aret == GNUNET_NO) | 419 | if (GNUNET_NO == aret) |
452 | LOG (GNUNET_ERROR_TYPE_INFO, _("Access denied to `%s'\n"), | 420 | LOG (GNUNET_ERROR_TYPE_INFO, _("Access denied to `%s'\n"), |
453 | GNUNET_a2s (uaddr, addrlen)); | 421 | GNUNET_a2s (uaddr, addrlen)); |
454 | GNUNET_break (GNUNET_OK == | 422 | GNUNET_break (GNUNET_OK == |
@@ -482,7 +450,7 @@ int | |||
482 | GNUNET_CONNECTION_get_address (struct GNUNET_CONNECTION_Handle *connection, | 450 | GNUNET_CONNECTION_get_address (struct GNUNET_CONNECTION_Handle *connection, |
483 | void **addr, size_t * addrlen) | 451 | void **addr, size_t * addrlen) |
484 | { | 452 | { |
485 | if ((connection->addr == NULL) || (connection->addrlen == 0)) | 453 | if ((NULL == connection->addr) || (0 == connection->addrlen)) |
486 | return GNUNET_NO; | 454 | return GNUNET_NO; |
487 | *addr = GNUNET_malloc (connection->addrlen); | 455 | *addr = GNUNET_malloc (connection->addrlen); |
488 | memcpy (*addr, connection->addr, connection->addrlen); | 456 | memcpy (*addr, connection->addr, connection->addrlen); |
@@ -492,73 +460,136 @@ GNUNET_CONNECTION_get_address (struct GNUNET_CONNECTION_Handle *connection, | |||
492 | 460 | ||
493 | 461 | ||
494 | /** | 462 | /** |
495 | * This function is called after establishing a connection either has | 463 | * Tell the receiver callback that we had an IO error. |
496 | * succeeded or timed out. Note that it is possible that the attempt | ||
497 | * timed out and that we're immediately retrying. If we are retrying, | ||
498 | * we need to wait again (or timeout); if we succeeded, we need to | ||
499 | * wait for data (or timeout). | ||
500 | * | 464 | * |
501 | * @param cls our connection handle | 465 | * @param connection connection to signal error |
502 | * @param tc task context describing why we are here | 466 | * @param errcode error code to send |
503 | */ | 467 | */ |
504 | static void | 468 | static void |
505 | receive_again (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | 469 | signal_receive_error (struct GNUNET_CONNECTION_Handle *connection, int errcode) |
470 | { | ||
471 | GNUNET_CONNECTION_Receiver receiver; | ||
472 | |||
473 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
474 | "Receive encounters error (%s), connection closed (%p)\n", | ||
475 | STRERROR (errcode), | ||
476 | connection); | ||
477 | GNUNET_assert (NULL != (receiver = connection->receiver)); | ||
478 | connection->receiver = NULL; | ||
479 | receiver (connection->receiver_cls, NULL, 0, connection->addr, connection->addrlen, errcode); | ||
480 | } | ||
506 | 481 | ||
507 | 482 | ||
508 | /** | 483 | /** |
509 | * See if we are now connected. If not, wait longer for | 484 | * Tell the receiver callback that a timeout was reached. |
510 | * connect to succeed. If connected, we should be able | ||
511 | * to write now as well, unless we timed out. | ||
512 | * | 485 | * |
513 | * @param cls our connection handle | 486 | * @param connection connection to signal for |
514 | * @param tc task context describing why we are here | ||
515 | */ | 487 | */ |
516 | static void | 488 | static void |
517 | transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | 489 | signal_receive_timeout (struct GNUNET_CONNECTION_Handle *connection) |
490 | { | ||
491 | GNUNET_CONNECTION_Receiver receiver; | ||
492 | |||
493 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection signals timeout to receiver (%p)!\n", | ||
494 | connection); | ||
495 | GNUNET_assert (NULL != (receiver = connection->receiver)); | ||
496 | connection->receiver = NULL; | ||
497 | receiver (connection->receiver_cls, NULL, 0, NULL, 0, 0); | ||
498 | } | ||
518 | 499 | ||
519 | 500 | ||
520 | /** | 501 | /** |
521 | * We've failed for good to establish a connection. | 502 | * We failed to transmit data to the service, signal the error. |
522 | * | 503 | * |
523 | * @param h the connection we tried to establish | 504 | * @param connection handle that had trouble |
505 | * @param ecode error code (errno) | ||
524 | */ | 506 | */ |
525 | static void | 507 | static void |
526 | connect_fail_continuation (struct GNUNET_CONNECTION_Handle *h) | 508 | signal_transmit_error (struct GNUNET_CONNECTION_Handle *connection, |
509 | int ecode) | ||
527 | { | 510 | { |
528 | LOG (GNUNET_ERROR_TYPE_INFO, | 511 | GNUNET_CONNECTION_TransmitReadyNotify notify; |
529 | _("Failed to establish TCP connection to `%s:%u', no further addresses to try.\n"), | 512 | |
530 | h->hostname, h->port); | 513 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
531 | /* connect failed / timed out */ | 514 | "Transmission encounterd error (%s), connection closed (%p)\n", |
532 | GNUNET_break (h->ap_head == NULL); | 515 | STRERROR (ecode), |
533 | GNUNET_break (h->ap_tail == NULL); | 516 | connection); |
534 | GNUNET_break (h->dns_active == GNUNET_NO); | 517 | if (NULL != connection->sock) |
535 | GNUNET_break (h->sock == NULL); | ||
536 | |||
537 | /* trigger jobs that used to wait on "connect_task" */ | ||
538 | if (0 != (h->ccs & COCO_RECEIVE_AGAIN)) | ||
539 | { | 518 | { |
540 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 519 | GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR); |
541 | "connect_fail_continuation triggers receive_again (%p)\n", h); | 520 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock)); |
542 | h->ccs -= COCO_RECEIVE_AGAIN; | 521 | connection->sock = NULL; |
543 | h->read_task = GNUNET_SCHEDULER_add_now (&receive_again, h); | 522 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task); |
544 | } | 523 | } |
545 | if (0 != (h->ccs & COCO_TRANSMIT_READY)) | 524 | if (GNUNET_SCHEDULER_NO_TASK != connection->read_task) |
546 | { | 525 | { |
547 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 526 | /* send errors trigger read errors... */ |
548 | "connect_fail_continuation cancels timeout_task, triggers transmit_ready (%p)\n", | 527 | GNUNET_SCHEDULER_cancel (connection->read_task); |
549 | h); | 528 | connection->read_task = GNUNET_SCHEDULER_NO_TASK; |
550 | GNUNET_assert (h->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK); | 529 | signal_receive_timeout (connection); |
551 | GNUNET_SCHEDULER_cancel (h->nth.timeout_task); | 530 | return; |
552 | h->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; | 531 | } |
553 | h->ccs -= COCO_TRANSMIT_READY; | 532 | if (NULL == connection->nth.notify_ready) |
554 | GNUNET_assert (h->nth.notify_ready != NULL); | 533 | return; /* nobody to tell about it */ |
555 | GNUNET_assert (h->write_task == GNUNET_SCHEDULER_NO_TASK); | 534 | notify = connection->nth.notify_ready; |
556 | h->write_task = GNUNET_SCHEDULER_add_now (&transmit_ready, h); | 535 | connection->nth.notify_ready = NULL; |
536 | notify (connection->nth.notify_ready_cls, 0, NULL); | ||
537 | } | ||
538 | |||
539 | |||
540 | /** | ||
541 | * We've failed for good to establish a connection (timeout or | ||
542 | * no more addresses to try). | ||
543 | * | ||
544 | * @param connection the connection we tried to establish | ||
545 | */ | ||
546 | static void | ||
547 | connect_fail_continuation (struct GNUNET_CONNECTION_Handle *connection) | ||
548 | { | ||
549 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
550 | _("Failed to establish TCP connection to `%s:%u', no further addresses to try.\n"), | ||
551 | connection->hostname, connection->port); | ||
552 | GNUNET_break (NULL == connection->ap_head); | ||
553 | GNUNET_break (NULL == connection->ap_tail); | ||
554 | GNUNET_break (GNUNET_NO == connection->dns_active); | ||
555 | GNUNET_break (NULL == connection->sock); | ||
556 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task); | ||
557 | |||
558 | /* signal errors for jobs that used to wait on the connection */ | ||
559 | if (NULL != connection->receiver) | ||
560 | signal_receive_error (connection, ECONNREFUSED); | ||
561 | if (NULL != connection->nth.notify_ready) | ||
562 | { | ||
563 | GNUNET_assert (connection->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK); | ||
564 | GNUNET_SCHEDULER_cancel (connection->nth.timeout_task); | ||
565 | connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
566 | signal_transmit_error (connection, ECONNREFUSED); | ||
557 | } | 567 | } |
558 | } | 568 | } |
559 | 569 | ||
560 | 570 | ||
561 | /** | 571 | /** |
572 | * We are ready to transmit (or got a timeout). | ||
573 | * | ||
574 | * @param cls our connection handle | ||
575 | * @param tc task context describing why we are here | ||
576 | */ | ||
577 | static void | ||
578 | transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
579 | |||
580 | |||
581 | /** | ||
582 | * This function is called once we either timeout or have data ready | ||
583 | * to read. | ||
584 | * | ||
585 | * @param cls connection to read from | ||
586 | * @param tc scheduler context | ||
587 | */ | ||
588 | static void | ||
589 | receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
590 | |||
591 | |||
592 | /** | ||
562 | * We've succeeded in establishing a connection. | 593 | * We've succeeded in establishing a connection. |
563 | * | 594 | * |
564 | * @param connection the connection we tried to establish | 595 | * @param connection the connection we tried to establish |
@@ -566,27 +597,29 @@ connect_fail_continuation (struct GNUNET_CONNECTION_Handle *h) | |||
566 | static void | 597 | static void |
567 | connect_success_continuation (struct GNUNET_CONNECTION_Handle *connection) | 598 | connect_success_continuation (struct GNUNET_CONNECTION_Handle *connection) |
568 | { | 599 | { |
569 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection to `%s' succeeded! (%p)\n", | 600 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
601 | "Connection to `%s' succeeded! (%p)\n", | ||
570 | GNUNET_a2s (connection->addr, connection->addrlen), connection); | 602 | GNUNET_a2s (connection->addr, connection->addrlen), connection); |
571 | /* trigger jobs that waited for the connection */ | 603 | /* trigger jobs that waited for the connection */ |
572 | if (0 != (connection->ccs & COCO_RECEIVE_AGAIN)) | 604 | if (NULL != connection->receiver) |
573 | { | 605 | { |
574 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 606 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
575 | "connect_success_continuation runs receive_again (%p)\n", connection); | 607 | "Connection succeeded, starting with receiving data (%p)\n", |
576 | connection->ccs -= COCO_RECEIVE_AGAIN; | 608 | connection); |
577 | connection->read_task = GNUNET_SCHEDULER_add_now (&receive_again, connection); | 609 | connection->read_task = |
610 | GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining | ||
611 | (connection->receive_timeout), connection->sock, | ||
612 | &receive_ready, connection); | ||
578 | } | 613 | } |
579 | if (0 != (connection->ccs & COCO_TRANSMIT_READY)) | 614 | if (NULL != connection->nth.notify_ready) |
580 | { | 615 | { |
581 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 616 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
582 | "connect_success_continuation runs transmit_ready, cancels timeout_task (%p)\n", | 617 | "Connection succeeded, starting with sending data (%p)\n", |
583 | connection); | 618 | connection); |
584 | GNUNET_assert (connection->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK); | 619 | GNUNET_assert (connection->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK); |
585 | GNUNET_SCHEDULER_cancel (connection->nth.timeout_task); | 620 | GNUNET_SCHEDULER_cancel (connection->nth.timeout_task); |
586 | connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; | 621 | connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; |
587 | connection->ccs -= COCO_TRANSMIT_READY; | ||
588 | GNUNET_assert (connection->write_task == GNUNET_SCHEDULER_NO_TASK); | 622 | GNUNET_assert (connection->write_task == GNUNET_SCHEDULER_NO_TASK); |
589 | GNUNET_assert (connection->nth.notify_ready != NULL); | ||
590 | connection->write_task = | 623 | connection->write_task = |
591 | GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining | 624 | GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining |
592 | (connection->nth.transmit_timeout), connection->sock, | 625 | (connection->nth.transmit_timeout), connection->sock, |
@@ -612,7 +645,7 @@ connect_probe_continuation (void *cls, | |||
612 | int error; | 645 | int error; |
613 | socklen_t len; | 646 | socklen_t len; |
614 | 647 | ||
615 | GNUNET_assert (ap->sock != NULL); | 648 | GNUNET_assert (NULL != ap->sock); |
616 | GNUNET_CONTAINER_DLL_remove (connection->ap_head, connection->ap_tail, ap); | 649 | GNUNET_CONTAINER_DLL_remove (connection->ap_head, connection->ap_tail, ap); |
617 | len = sizeof (error); | 650 | len = sizeof (error); |
618 | errno = 0; | 651 | errno = 0; |
@@ -620,17 +653,17 @@ connect_probe_continuation (void *cls, | |||
620 | if ((0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) || | 653 | if ((0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) || |
621 | (GNUNET_OK != | 654 | (GNUNET_OK != |
622 | GNUNET_NETWORK_socket_getsockopt (ap->sock, SOL_SOCKET, SO_ERROR, &error, | 655 | GNUNET_NETWORK_socket_getsockopt (ap->sock, SOL_SOCKET, SO_ERROR, &error, |
623 | &len)) || (error != 0)) | 656 | &len)) || (0 != error)) |
624 | { | 657 | { |
625 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock)); | 658 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock)); |
626 | GNUNET_free (ap); | 659 | GNUNET_free (ap); |
627 | if ((NULL == connection->ap_head) && (connection->dns_active == GNUNET_NO)) | 660 | if ((NULL == connection->ap_head) && (GNUNET_NO == connection->dns_active)) |
628 | connect_fail_continuation (connection); | 661 | connect_fail_continuation (connection); |
629 | return; | 662 | return; |
630 | } | 663 | } |
631 | GNUNET_assert (connection->sock == NULL); | 664 | GNUNET_assert (NULL == connection->sock); |
632 | connection->sock = ap->sock; | 665 | connection->sock = ap->sock; |
633 | GNUNET_assert (connection->addr == NULL); | 666 | GNUNET_assert (NULL == connection->addr); |
634 | connection->addr = GNUNET_malloc (ap->addrlen); | 667 | connection->addr = GNUNET_malloc (ap->addrlen); |
635 | memcpy (connection->addr, ap->addr, ap->addrlen); | 668 | memcpy (connection->addr, ap->addr, ap->addrlen); |
636 | connection->addrlen = ap->addrlen; | 669 | connection->addrlen = ap->addrlen; |
@@ -663,16 +696,16 @@ try_connect_using_address (void *cls, const struct sockaddr *addr, | |||
663 | struct AddressProbe *ap; | 696 | struct AddressProbe *ap; |
664 | struct GNUNET_TIME_Relative delay; | 697 | struct GNUNET_TIME_Relative delay; |
665 | 698 | ||
666 | if (addr == NULL) | 699 | if (NULL == addr) |
667 | { | 700 | { |
668 | connection->dns_active = NULL; | 701 | connection->dns_active = NULL; |
669 | if ((NULL == connection->ap_head) && (NULL == connection->sock)) | 702 | if ((NULL == connection->ap_head) && (NULL == connection->sock)) |
670 | connect_fail_continuation (connection); | 703 | connect_fail_continuation (connection); |
671 | return; | 704 | return; |
672 | } | 705 | } |
673 | if (connection->sock != NULL) | 706 | if (NULL != connection->sock) |
674 | return; /* already connected */ | 707 | return; /* already connected */ |
675 | GNUNET_assert (connection->addr == NULL); | 708 | GNUNET_assert (NULL == connection->addr); |
676 | /* try to connect */ | 709 | /* try to connect */ |
677 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 710 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
678 | "Trying to connect using address `%s:%u/%s:%u'\n", connection->hostname, connection->port, | 711 | "Trying to connect using address `%s:%u/%s:%u'\n", connection->hostname, connection->port, |
@@ -697,7 +730,7 @@ try_connect_using_address (void *cls, const struct sockaddr *addr, | |||
697 | return; /* not supported by us */ | 730 | return; /* not supported by us */ |
698 | } | 731 | } |
699 | ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family, SOCK_STREAM, 0); | 732 | ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family, SOCK_STREAM, 0); |
700 | if (ap->sock == NULL) | 733 | if (NULL == ap->sock) |
701 | { | 734 | { |
702 | GNUNET_free (ap); | 735 | GNUNET_free (ap); |
703 | return; /* not supported by OS */ | 736 | return; /* not supported by OS */ |
@@ -706,7 +739,7 @@ try_connect_using_address (void *cls, const struct sockaddr *addr, | |||
706 | GNUNET_a2s (ap->addr, ap->addrlen), connection); | 739 | GNUNET_a2s (ap->addr, ap->addrlen), connection); |
707 | if ((GNUNET_OK != | 740 | if ((GNUNET_OK != |
708 | GNUNET_NETWORK_socket_connect (ap->sock, ap->addr, ap->addrlen)) && | 741 | GNUNET_NETWORK_socket_connect (ap->sock, ap->addr, ap->addrlen)) && |
709 | (errno != EINPROGRESS)) | 742 | (EINPROGRESS != errno)) |
710 | { | 743 | { |
711 | /* maybe refused / unsupported address, try next */ | 744 | /* maybe refused / unsupported address, try next */ |
712 | LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect"); | 745 | LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect"); |
@@ -720,12 +753,12 @@ try_connect_using_address (void *cls, const struct sockaddr *addr, | |||
720 | } | 753 | } |
721 | GNUNET_CONTAINER_DLL_insert (connection->ap_head, connection->ap_tail, ap); | 754 | GNUNET_CONTAINER_DLL_insert (connection->ap_head, connection->ap_tail, ap); |
722 | delay = GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT; | 755 | delay = GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT; |
723 | if (connection->nth.notify_ready != NULL) | 756 | if (NULL != connection->nth.notify_ready) |
724 | delay = | 757 | delay = |
725 | GNUNET_TIME_relative_min (delay, | 758 | GNUNET_TIME_relative_min (delay, |
726 | GNUNET_TIME_absolute_get_remaining (connection-> | 759 | GNUNET_TIME_absolute_get_remaining (connection-> |
727 | nth.transmit_timeout)); | 760 | nth.transmit_timeout)); |
728 | if (connection->receiver != NULL) | 761 | if (NULL != connection->receiver) |
729 | delay = | 762 | delay = |
730 | GNUNET_TIME_relative_min (delay, | 763 | GNUNET_TIME_relative_min (delay, |
731 | GNUNET_TIME_absolute_get_remaining | 764 | GNUNET_TIME_absolute_get_remaining |
@@ -852,15 +885,14 @@ GNUNET_CONNECTION_create_from_sockaddr (int af_family, | |||
852 | struct GNUNET_NETWORK_Handle *s; | 885 | struct GNUNET_NETWORK_Handle *s; |
853 | struct GNUNET_CONNECTION_Handle *connection; | 886 | struct GNUNET_CONNECTION_Handle *connection; |
854 | 887 | ||
855 | |||
856 | s = GNUNET_NETWORK_socket_create (af_family, SOCK_STREAM, 0); | 888 | s = GNUNET_NETWORK_socket_create (af_family, SOCK_STREAM, 0); |
857 | if (s == NULL) | 889 | if (NULL == s) |
858 | { | 890 | { |
859 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "socket"); | 891 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "socket"); |
860 | return NULL; | 892 | return NULL; |
861 | } | 893 | } |
862 | if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (s, serv_addr, addrlen)) && | 894 | if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (s, serv_addr, addrlen)) && |
863 | (errno != EINPROGRESS)) | 895 | (EINPROGRESS != errno)) |
864 | { | 896 | { |
865 | /* maybe refused / unsupported address, try next */ | 897 | /* maybe refused / unsupported address, try next */ |
866 | LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect"); | 898 | LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect"); |
@@ -890,9 +922,9 @@ GNUNET_CONNECTION_create_from_sockaddr (int af_family, | |||
890 | int | 922 | int |
891 | GNUNET_CONNECTION_check (struct GNUNET_CONNECTION_Handle *connection) | 923 | GNUNET_CONNECTION_check (struct GNUNET_CONNECTION_Handle *connection) |
892 | { | 924 | { |
893 | if ((connection->ap_head != NULL) || (connection->dns_active != NULL)) | 925 | if ((NULL != connection->ap_head) || (NULL != connection->dns_active)) |
894 | return GNUNET_YES; /* still trying to connect */ | 926 | return GNUNET_YES; /* still trying to connect */ |
895 | return (connection->sock == NULL) ? GNUNET_NO : GNUNET_YES; | 927 | return (NULL == connection->sock) ? GNUNET_NO : GNUNET_YES; |
896 | } | 928 | } |
897 | 929 | ||
898 | 930 | ||
@@ -911,19 +943,18 @@ GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection) | |||
911 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connection (%p)\n", connection); | 943 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connection (%p)\n", connection); |
912 | GNUNET_assert (NULL == connection->nth.notify_ready); | 944 | GNUNET_assert (NULL == connection->nth.notify_ready); |
913 | GNUNET_assert (NULL == connection->receiver); | 945 | GNUNET_assert (NULL == connection->receiver); |
914 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->read_task); | 946 | if (GNUNET_SCHEDULER_NO_TASK != connection->write_task) |
915 | if (connection->write_task != GNUNET_SCHEDULER_NO_TASK) | ||
916 | { | 947 | { |
917 | GNUNET_SCHEDULER_cancel (connection->write_task); | 948 | GNUNET_SCHEDULER_cancel (connection->write_task); |
918 | connection->write_task = GNUNET_SCHEDULER_NO_TASK; | 949 | connection->write_task = GNUNET_SCHEDULER_NO_TASK; |
919 | connection->write_buffer_off = 0; | 950 | connection->write_buffer_off = 0; |
920 | } | 951 | } |
921 | if (connection->read_task != GNUNET_SCHEDULER_NO_TASK) | 952 | if (GNUNET_SCHEDULER_NO_TASK != connection->read_task) |
922 | { | 953 | { |
923 | GNUNET_SCHEDULER_cancel (connection->read_task); | 954 | GNUNET_SCHEDULER_cancel (connection->read_task); |
924 | connection->read_task = GNUNET_SCHEDULER_NO_TASK; | 955 | connection->read_task = GNUNET_SCHEDULER_NO_TASK; |
925 | } | 956 | } |
926 | if (connection->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK) | 957 | if (GNUNET_SCHEDULER_NO_TASK != connection->nth.timeout_task) |
927 | { | 958 | { |
928 | GNUNET_SCHEDULER_cancel (connection->nth.timeout_task); | 959 | GNUNET_SCHEDULER_cancel (connection->nth.timeout_task); |
929 | connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; | 960 | connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; |
@@ -942,16 +973,16 @@ GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection) | |||
942 | GNUNET_free (pos); | 973 | GNUNET_free (pos); |
943 | } | 974 | } |
944 | if ( (NULL != connection->sock) && | 975 | if ( (NULL != connection->sock) && |
945 | (connection->persist != GNUNET_YES) ) | 976 | (GNUNET_YES != connection->persist) ) |
946 | { | 977 | { |
947 | if ((GNUNET_YES != GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR)) && | 978 | if ((GNUNET_YES != GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR)) && |
948 | (errno != ENOTCONN) && | 979 | (ENOTCONN != errno) && |
949 | (errno != ECONNRESET) ) | 980 | (ECONNRESET != errno) ) |
950 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "shutdown"); | 981 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "shutdown"); |
951 | } | 982 | } |
952 | if (connection->sock != NULL) | 983 | if (NULL != connection->sock) |
953 | { | 984 | { |
954 | if (connection->persist != GNUNET_YES) | 985 | if (GNUNET_YES != connection->persist) |
955 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock)); | 986 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock)); |
956 | else | 987 | else |
957 | GNUNET_free (connection->sock); /* at least no memory leak (we deliberately | 988 | GNUNET_free (connection->sock); /* at least no memory leak (we deliberately |
@@ -965,92 +996,54 @@ GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection) | |||
965 | 996 | ||
966 | 997 | ||
967 | /** | 998 | /** |
968 | * Tell the receiver callback that a timeout was reached. | ||
969 | */ | ||
970 | static void | ||
971 | signal_timeout (struct GNUNET_CONNECTION_Handle *connection) | ||
972 | { | ||
973 | GNUNET_CONNECTION_Receiver receiver; | ||
974 | |||
975 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Network signals time out to receiver (%p)!\n", | ||
976 | connection); | ||
977 | GNUNET_assert (NULL != (receiver = connection->receiver)); | ||
978 | connection->receiver = NULL; | ||
979 | receiver (connection->receiver_cls, NULL, 0, NULL, 0, 0); | ||
980 | } | ||
981 | |||
982 | |||
983 | /** | ||
984 | * Tell the receiver callback that we had an IO error. | ||
985 | */ | ||
986 | static void | ||
987 | signal_error (struct GNUNET_CONNECTION_Handle *connection, int errcode) | ||
988 | { | ||
989 | GNUNET_CONNECTION_Receiver receiver; | ||
990 | |||
991 | GNUNET_assert (NULL != (receiver = connection->receiver)); | ||
992 | connection->receiver = NULL; | ||
993 | receiver (connection->receiver_cls, NULL, 0, connection->addr, connection->addrlen, errcode); | ||
994 | } | ||
995 | |||
996 | |||
997 | /** | ||
998 | * This function is called once we either timeout | 999 | * This function is called once we either timeout |
999 | * or have data ready to read. | 1000 | * or have data ready to read. |
1001 | * | ||
1002 | * @param cls connection to read from | ||
1003 | * @param tc scheduler context | ||
1000 | */ | 1004 | */ |
1001 | static void | 1005 | static void |
1002 | receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 1006 | receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
1003 | { | 1007 | { |
1004 | struct GNUNET_CONNECTION_Handle *connection = cls; | 1008 | struct GNUNET_CONNECTION_Handle *connection = cls; |
1005 | struct GNUNET_TIME_Absolute now; | ||
1006 | char buffer[connection->max]; | 1009 | char buffer[connection->max]; |
1007 | ssize_t ret; | 1010 | ssize_t ret; |
1008 | GNUNET_CONNECTION_Receiver receiver; | 1011 | GNUNET_CONNECTION_Receiver receiver; |
1009 | 1012 | ||
1010 | connection->read_task = GNUNET_SCHEDULER_NO_TASK; | 1013 | connection->read_task = GNUNET_SCHEDULER_NO_TASK; |
1011 | if ((GNUNET_YES == connection->ignore_shutdown) && | 1014 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
1012 | (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))) | ||
1013 | { | 1015 | { |
1014 | /* ignore shutdown request, go again immediately */ | 1016 | /* ignore shutdown request, go again immediately */ |
1015 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1016 | "Ignoring shutdown signal per configuration\n"); | ||
1017 | connection->read_task = | 1017 | connection->read_task = |
1018 | GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining | 1018 | GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining |
1019 | (connection->receive_timeout), connection->sock, | 1019 | (connection->receive_timeout), connection->sock, |
1020 | &receive_ready, connection); | 1020 | &receive_ready, connection); |
1021 | return; | 1021 | return; |
1022 | } | 1022 | } |
1023 | now = GNUNET_TIME_absolute_get (); | 1023 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) |
1024 | if ((now.abs_value > connection->receive_timeout.abs_value) || | ||
1025 | (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) || | ||
1026 | (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))) | ||
1027 | { | 1024 | { |
1028 | if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | 1025 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1029 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1026 | "Receive from `%s' encounters error: timeout (%p)\n", |
1030 | "Receive from `%s' encounters error: time out by %llums... (%p)\n", | 1027 | GNUNET_a2s (connection->addr, connection->addrlen), |
1031 | GNUNET_a2s (connection->addr, connection->addrlen), | 1028 | GNUNET_TIME_absolute_get_duration (connection->receive_timeout).rel_value, |
1032 | GNUNET_TIME_absolute_get_duration (connection->receive_timeout).rel_value, | 1029 | connection); |
1033 | connection); | 1030 | signal_receive_timeout (connection); |
1034 | signal_timeout (connection); | ||
1035 | return; | 1031 | return; |
1036 | } | 1032 | } |
1037 | if (connection->sock == NULL) | 1033 | if (NULL == connection->sock) |
1038 | { | 1034 | { |
1039 | /* connect failed for good */ | 1035 | /* connect failed for good */ |
1040 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1036 | signal_receive_error (connection, ECONNREFUSED); |
1041 | "Receive encounters error, connection closed... (%p)\n", connection); | ||
1042 | signal_error (connection, ECONNREFUSED); | ||
1043 | return; | 1037 | return; |
1044 | } | 1038 | } |
1045 | GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, connection->sock)); | 1039 | GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, connection->sock)); |
1046 | RETRY: | 1040 | RETRY: |
1047 | ret = GNUNET_NETWORK_socket_recv (connection->sock, buffer, connection->max); | 1041 | ret = GNUNET_NETWORK_socket_recv (connection->sock, buffer, connection->max); |
1048 | if (ret == -1) | 1042 | if (-1 == ret) |
1049 | { | 1043 | { |
1050 | if (errno == EINTR) | 1044 | if (EINTR == errno) |
1051 | goto RETRY; | 1045 | goto RETRY; |
1052 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Error receiving: %s\n", STRERROR (errno)); | 1046 | signal_receive_error (connection, errno); |
1053 | signal_error (connection, errno); | ||
1054 | return; | 1047 | return; |
1055 | } | 1048 | } |
1056 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1049 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
@@ -1063,49 +1056,6 @@ RETRY: | |||
1063 | 1056 | ||
1064 | 1057 | ||
1065 | /** | 1058 | /** |
1066 | * This function is called after establishing a connection either has | ||
1067 | * succeeded or timed out. Note that it is possible that the attempt | ||
1068 | * timed out and that we're immediately retrying. If we are retrying, | ||
1069 | * we need to wait again (or timeout); if we succeeded, we need to | ||
1070 | * wait for data (or timeout). | ||
1071 | * | ||
1072 | * @param cls our connection handle | ||
1073 | * @param tc task context describing why we are here | ||
1074 | */ | ||
1075 | static void | ||
1076 | receive_again (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1077 | { | ||
1078 | struct GNUNET_CONNECTION_Handle *connection = cls; | ||
1079 | struct GNUNET_TIME_Absolute now; | ||
1080 | |||
1081 | connection->read_task = GNUNET_SCHEDULER_NO_TASK; | ||
1082 | if (connection->sock == NULL) | ||
1083 | { | ||
1084 | /* not connected and no longer trying */ | ||
1085 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1086 | "Receive encounters error, connection closed (%p)...\n", connection); | ||
1087 | signal_error (connection, ECONNREFUSED); | ||
1088 | return; | ||
1089 | } | ||
1090 | now = GNUNET_TIME_absolute_get (); | ||
1091 | if ((now.abs_value > connection->receive_timeout.abs_value) || | ||
1092 | (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))) | ||
1093 | { | ||
1094 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1095 | "Receive encounters error: time out (%p)...\n", connection); | ||
1096 | signal_timeout (connection); | ||
1097 | return; | ||
1098 | } | ||
1099 | GNUNET_assert (connection->sock != NULL); | ||
1100 | /* connect succeeded, wait for data! */ | ||
1101 | connection->read_task = | ||
1102 | GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining | ||
1103 | (connection->receive_timeout), connection->sock, | ||
1104 | &receive_ready, connection); | ||
1105 | } | ||
1106 | |||
1107 | |||
1108 | /** | ||
1109 | * Receive data from the given connection. Note that this function will | 1059 | * Receive data from the given connection. Note that this function will |
1110 | * call "receiver" asynchronously using the scheduler. It will | 1060 | * call "receiver" asynchronously using the scheduler. It will |
1111 | * "immediately" return. Note that there MUST only be one active | 1061 | * "immediately" return. Note that there MUST only be one active |
@@ -1124,42 +1074,25 @@ GNUNET_CONNECTION_receive (struct GNUNET_CONNECTION_Handle *connection, size_t m | |||
1124 | GNUNET_CONNECTION_Receiver receiver, | 1074 | GNUNET_CONNECTION_Receiver receiver, |
1125 | void *receiver_cls) | 1075 | void *receiver_cls) |
1126 | { | 1076 | { |
1127 | struct GNUNET_SCHEDULER_TaskContext tc; | 1077 | GNUNET_assert ((GNUNET_SCHEDULER_NO_TASK == connection->read_task) && |
1128 | 1078 | (NULL == connection->receiver)); | |
1129 | GNUNET_assert ((connection->read_task == GNUNET_SCHEDULER_NO_TASK) && | ||
1130 | (0 == (connection->ccs & COCO_RECEIVE_AGAIN)) && | ||
1131 | (connection->receiver == NULL)); | ||
1132 | connection->receiver = receiver; | 1079 | connection->receiver = receiver; |
1133 | connection->receiver_cls = receiver_cls; | 1080 | connection->receiver_cls = receiver_cls; |
1134 | connection->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout); | 1081 | connection->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout); |
1135 | connection->max = max; | 1082 | connection->max = max; |
1136 | if (connection->sock != NULL) | 1083 | if (NULL != connection->sock) |
1137 | { | 1084 | { |
1138 | memset (&tc, 0, sizeof (tc)); | 1085 | connection->read_task = |
1139 | tc.reason = GNUNET_SCHEDULER_REASON_PREREQ_DONE; | 1086 | GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining |
1140 | receive_again (connection, &tc); | 1087 | (connection->receive_timeout), connection->sock, |
1088 | &receive_ready, connection); | ||
1141 | return; | 1089 | return; |
1142 | } | 1090 | } |
1143 | if ((connection->dns_active == NULL) && (connection->ap_head == NULL)) | 1091 | if ((NULL == connection->dns_active) && (NULL == connection->ap_head)) |
1144 | { | 1092 | { |
1145 | receiver (receiver_cls, NULL, 0, NULL, 0, ETIMEDOUT); | 1093 | receiver (receiver_cls, NULL, 0, NULL, 0, ETIMEDOUT); |
1146 | return; | 1094 | return; |
1147 | } | 1095 | } |
1148 | connection->ccs += COCO_RECEIVE_AGAIN; | ||
1149 | } | ||
1150 | |||
1151 | |||
1152 | /** | ||
1153 | * Configure this connection to ignore shutdown signals. | ||
1154 | * | ||
1155 | * @param connection connection handle | ||
1156 | * @param do_ignore GNUNET_YES to ignore, GNUNET_NO to restore default | ||
1157 | */ | ||
1158 | void | ||
1159 | GNUNET_CONNECTION_ignore_shutdown (struct GNUNET_CONNECTION_Handle *connection, | ||
1160 | int do_ignore) | ||
1161 | { | ||
1162 | connection->ignore_shutdown = do_ignore; | ||
1163 | } | 1096 | } |
1164 | 1097 | ||
1165 | 1098 | ||
@@ -1174,16 +1107,11 @@ GNUNET_CONNECTION_ignore_shutdown (struct GNUNET_CONNECTION_Handle *connection, | |||
1174 | void * | 1107 | void * |
1175 | GNUNET_CONNECTION_receive_cancel (struct GNUNET_CONNECTION_Handle *connection) | 1108 | GNUNET_CONNECTION_receive_cancel (struct GNUNET_CONNECTION_Handle *connection) |
1176 | { | 1109 | { |
1177 | if (connection->read_task != GNUNET_SCHEDULER_NO_TASK) | 1110 | if (GNUNET_SCHEDULER_NO_TASK == connection->read_task) |
1178 | { | 1111 | { |
1179 | GNUNET_assert (connection == GNUNET_SCHEDULER_cancel (connection->read_task)); | 1112 | GNUNET_assert (connection == GNUNET_SCHEDULER_cancel (connection->read_task)); |
1180 | connection->read_task = GNUNET_SCHEDULER_NO_TASK; | 1113 | connection->read_task = GNUNET_SCHEDULER_NO_TASK; |
1181 | } | 1114 | } |
1182 | else | ||
1183 | { | ||
1184 | GNUNET_assert (0 != (connection->ccs & COCO_RECEIVE_AGAIN)); | ||
1185 | connection->ccs -= COCO_RECEIVE_AGAIN; | ||
1186 | } | ||
1187 | connection->receiver = NULL; | 1115 | connection->receiver = NULL; |
1188 | return connection->receiver_cls; | 1116 | return connection->receiver_cls; |
1189 | } | 1117 | } |
@@ -1204,7 +1132,7 @@ process_notify (struct GNUNET_CONNECTION_Handle *connection) | |||
1204 | size_t size; | 1132 | size_t size; |
1205 | GNUNET_CONNECTION_TransmitReadyNotify notify; | 1133 | GNUNET_CONNECTION_TransmitReadyNotify notify; |
1206 | 1134 | ||
1207 | GNUNET_assert (connection->write_task == GNUNET_SCHEDULER_NO_TASK); | 1135 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task); |
1208 | if (NULL == (notify = connection->nth.notify_ready)) | 1136 | if (NULL == (notify = connection->nth.notify_ready)) |
1209 | return GNUNET_NO; | 1137 | return GNUNET_NO; |
1210 | used = connection->write_buffer_off - connection->write_buffer_pos; | 1138 | used = connection->write_buffer_off - connection->write_buffer_pos; |
@@ -1255,9 +1183,8 @@ transmit_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1255 | "Transmit to `%s:%u/%s' fails, time out reached (%p).\n", | 1183 | "Transmit to `%s:%u/%s' fails, time out reached (%p).\n", |
1256 | connection->hostname, | 1184 | connection->hostname, |
1257 | connection->port, GNUNET_a2s (connection->addr, connection->addrlen), connection); | 1185 | connection->port, GNUNET_a2s (connection->addr, connection->addrlen), connection); |
1258 | GNUNET_assert (0 != (connection->ccs & COCO_TRANSMIT_READY)); | ||
1259 | connection->ccs -= COCO_TRANSMIT_READY; /* remove request */ | ||
1260 | notify = connection->nth.notify_ready; | 1186 | notify = connection->nth.notify_ready; |
1187 | GNUNET_assert (NULL != notify); | ||
1261 | connection->nth.notify_ready = NULL; | 1188 | connection->nth.notify_ready = NULL; |
1262 | notify (connection->nth.notify_ready_cls, 0, NULL); | 1189 | notify (connection->nth.notify_ready_cls, 0, NULL); |
1263 | } | 1190 | } |
@@ -1289,41 +1216,7 @@ connect_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1289 | 1216 | ||
1290 | 1217 | ||
1291 | /** | 1218 | /** |
1292 | * FIXME | 1219 | * We are ready to transmit (or got a timeout). |
1293 | * | ||
1294 | * @param connection FIXME | ||
1295 | */ | ||
1296 | static void | ||
1297 | transmit_error (struct GNUNET_CONNECTION_Handle *connection) | ||
1298 | { | ||
1299 | GNUNET_CONNECTION_TransmitReadyNotify notify; | ||
1300 | |||
1301 | if (NULL != connection->sock) | ||
1302 | { | ||
1303 | GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR); | ||
1304 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock)); | ||
1305 | connection->sock = NULL; | ||
1306 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task); | ||
1307 | } | ||
1308 | if (connection->read_task != GNUNET_SCHEDULER_NO_TASK) | ||
1309 | { | ||
1310 | GNUNET_SCHEDULER_cancel (connection->read_task); | ||
1311 | connection->read_task = GNUNET_SCHEDULER_NO_TASK; | ||
1312 | signal_timeout (connection); | ||
1313 | return; | ||
1314 | } | ||
1315 | if (connection->nth.notify_ready == NULL) | ||
1316 | return; /* nobody to tell about it */ | ||
1317 | notify = connection->nth.notify_ready; | ||
1318 | connection->nth.notify_ready = NULL; | ||
1319 | notify (connection->nth.notify_ready_cls, 0, NULL); | ||
1320 | } | ||
1321 | |||
1322 | |||
1323 | /** | ||
1324 | * See if we are now connected. If not, wait longer for | ||
1325 | * connect to succeed. If connected, we should be able | ||
1326 | * to write now as well, unless we timed out. | ||
1327 | * | 1220 | * |
1328 | * @param cls our connection handle | 1221 | * @param cls our connection handle |
1329 | * @param tc task context describing why we are here | 1222 | * @param tc task context describing why we are here |
@@ -1337,12 +1230,12 @@ transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1337 | size_t have; | 1230 | size_t have; |
1338 | 1231 | ||
1339 | LOG (GNUNET_ERROR_TYPE_DEBUG, "transmit_ready running (%p).\n", connection); | 1232 | LOG (GNUNET_ERROR_TYPE_DEBUG, "transmit_ready running (%p).\n", connection); |
1340 | GNUNET_assert (connection->write_task != GNUNET_SCHEDULER_NO_TASK); | 1233 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != connection->write_task); |
1341 | connection->write_task = GNUNET_SCHEDULER_NO_TASK; | 1234 | connection->write_task = GNUNET_SCHEDULER_NO_TASK; |
1342 | GNUNET_assert (connection->nth.timeout_task == GNUNET_SCHEDULER_NO_TASK); | 1235 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->nth.timeout_task); |
1343 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | 1236 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
1344 | { | 1237 | { |
1345 | if ((connection->ignore_shutdown == GNUNET_YES) && (NULL != connection->sock)) | 1238 | if (NULL != connection->sock) |
1346 | goto SCHEDULE_WRITE; /* ignore shutdown, go again immediately */ | 1239 | goto SCHEDULE_WRITE; /* ignore shutdown, go again immediately */ |
1347 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1240 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1348 | "Transmit to `%s' fails, shutdown happened (%p).\n", | 1241 | "Transmit to `%s' fails, shutdown happened (%p).\n", |
@@ -1367,25 +1260,22 @@ transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1367 | return; | 1260 | return; |
1368 | } | 1261 | } |
1369 | GNUNET_assert (NULL != connection->sock); | 1262 | GNUNET_assert (NULL != connection->sock); |
1370 | if (tc->write_ready == NULL) | 1263 | if (NULL == tc->write_ready) |
1371 | { | 1264 | { |
1372 | /* special circumstances (in particular, | 1265 | /* special circumstances (in particular, PREREQ_DONE after |
1373 | * PREREQ_DONE after connect): not yet ready to write, | 1266 | * connect): not yet ready to write, but no "fatal" error either. |
1374 | * but no "fatal" error either. Hence retry. */ | 1267 | * Hence retry. */ |
1375 | goto SCHEDULE_WRITE; | 1268 | goto SCHEDULE_WRITE; |
1376 | } | 1269 | } |
1377 | if (!GNUNET_NETWORK_fdset_isset (tc->write_ready, connection->sock)) | 1270 | if (!GNUNET_NETWORK_fdset_isset (tc->write_ready, connection->sock)) |
1378 | { | 1271 | { |
1379 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1380 | _ | ||
1381 | ("Could not satisfy pending transmission request, socket closed or connect failed (%p).\n"), | ||
1382 | connection); | ||
1383 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task); | 1272 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task); |
1384 | transmit_error (connection); | 1273 | /* special circumstances (in particular, shutdown): not yet ready |
1385 | return; /* connect failed for good, we're finished */ | 1274 | * to write, but no "fatal" error either. Hence retry. */ |
1275 | goto SCHEDULE_WRITE; | ||
1386 | } | 1276 | } |
1387 | GNUNET_assert (connection->write_buffer_off >= connection->write_buffer_pos); | 1277 | GNUNET_assert (connection->write_buffer_off >= connection->write_buffer_pos); |
1388 | if ((connection->nth.notify_ready != NULL) && | 1278 | if ((NULL != connection->nth.notify_ready) && |
1389 | (connection->write_buffer_size < connection->nth.notify_size)) | 1279 | (connection->write_buffer_size < connection->nth.notify_size)) |
1390 | { | 1280 | { |
1391 | connection->write_buffer = | 1281 | connection->write_buffer = |
@@ -1394,7 +1284,7 @@ transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1394 | } | 1284 | } |
1395 | process_notify (connection); | 1285 | process_notify (connection); |
1396 | have = connection->write_buffer_off - connection->write_buffer_pos; | 1286 | have = connection->write_buffer_off - connection->write_buffer_pos; |
1397 | if (have == 0) | 1287 | if (0 == have) |
1398 | { | 1288 | { |
1399 | /* no data ready for writing, terminate write loop */ | 1289 | /* no data ready for writing, terminate write loop */ |
1400 | return; | 1290 | return; |
@@ -1407,21 +1297,20 @@ RETRY: | |||
1407 | GNUNET_NETWORK_socket_send (connection->sock, | 1297 | GNUNET_NETWORK_socket_send (connection->sock, |
1408 | &connection->write_buffer[connection->write_buffer_pos], | 1298 | &connection->write_buffer[connection->write_buffer_pos], |
1409 | have); | 1299 | have); |
1410 | if (ret == -1) | 1300 | if (-1 == ret) |
1411 | { | 1301 | { |
1412 | if (errno == EINTR) | 1302 | if (EINTR == errno) |
1413 | goto RETRY; | 1303 | goto RETRY; |
1414 | LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "send"); | ||
1415 | if (GNUNET_SCHEDULER_NO_TASK != connection->write_task) | 1304 | if (GNUNET_SCHEDULER_NO_TASK != connection->write_task) |
1416 | { | 1305 | { |
1417 | GNUNET_SCHEDULER_cancel (connection->write_task); | 1306 | GNUNET_SCHEDULER_cancel (connection->write_task); |
1418 | connection->write_task = GNUNET_SCHEDULER_NO_TASK; | 1307 | connection->write_task = GNUNET_SCHEDULER_NO_TASK; |
1419 | } | 1308 | } |
1420 | transmit_error (connection); | 1309 | signal_transmit_error (connection, errno); |
1421 | return; | 1310 | return; |
1422 | } | 1311 | } |
1423 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1312 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1424 | "transmit_ready transmitted %u/%u bytes to `%s' (%p)\n", | 1313 | "Connection transmitted %u/%u bytes to `%s' (%p)\n", |
1425 | (unsigned int) ret, have, GNUNET_a2s (connection->addr, connection->addrlen), connection); | 1314 | (unsigned int) ret, have, GNUNET_a2s (connection->addr, connection->addrlen), connection); |
1426 | connection->write_buffer_pos += ret; | 1315 | connection->write_buffer_pos += ret; |
1427 | if (connection->write_buffer_pos == connection->write_buffer_off) | 1316 | if (connection->write_buffer_pos == connection->write_buffer_off) |
@@ -1430,15 +1319,15 @@ RETRY: | |||
1430 | connection->write_buffer_pos = 0; | 1319 | connection->write_buffer_pos = 0; |
1431 | connection->write_buffer_off = 0; | 1320 | connection->write_buffer_off = 0; |
1432 | } | 1321 | } |
1433 | if ((connection->write_buffer_off == 0) && (NULL == connection->nth.notify_ready)) | 1322 | if ((0 == connection->write_buffer_off) && (NULL == connection->nth.notify_ready)) |
1434 | return; /* all data sent! */ | 1323 | return; /* all data sent! */ |
1435 | /* not done writing, schedule more */ | 1324 | /* not done writing, schedule more */ |
1436 | SCHEDULE_WRITE: | 1325 | SCHEDULE_WRITE: |
1437 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1326 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1438 | "Re-scheduling transmit_ready (more to do) (%p).\n", connection); | 1327 | "Re-scheduling transmit_ready (more to do) (%p).\n", connection); |
1439 | have = connection->write_buffer_off - connection->write_buffer_pos; | 1328 | have = connection->write_buffer_off - connection->write_buffer_pos; |
1440 | GNUNET_assert ((connection->nth.notify_ready != NULL) || (have > 0)); | 1329 | GNUNET_assert ((NULL != connection->nth.notify_ready) || (have > 0)); |
1441 | if (connection->write_task == GNUNET_SCHEDULER_NO_TASK) | 1330 | if (GNUNET_SCHEDULER_NO_TASK == connection->write_task) |
1442 | connection->write_task = | 1331 | connection->write_task = |
1443 | GNUNET_SCHEDULER_add_write_net ((connection->nth.notify_ready == | 1332 | GNUNET_SCHEDULER_add_write_net ((connection->nth.notify_ready == |
1444 | NULL) ? GNUNET_TIME_UNIT_FOREVER_REL : | 1333 | NULL) ? GNUNET_TIME_UNIT_FOREVER_REL : |
@@ -1469,12 +1358,12 @@ GNUNET_CONNECTION_notify_transmit_ready (struct GNUNET_CONNECTION_Handle *connec | |||
1469 | GNUNET_CONNECTION_TransmitReadyNotify | 1358 | GNUNET_CONNECTION_TransmitReadyNotify |
1470 | notify, void *notify_cls) | 1359 | notify, void *notify_cls) |
1471 | { | 1360 | { |
1472 | if (connection->nth.notify_ready != NULL) | 1361 | if (NULL != connection->nth.notify_ready) |
1473 | { | 1362 | { |
1474 | GNUNET_assert (0); | 1363 | GNUNET_assert (0); |
1475 | return NULL; | 1364 | return NULL; |
1476 | } | 1365 | } |
1477 | GNUNET_assert (notify != NULL); | 1366 | GNUNET_assert (NULL != notify); |
1478 | GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE); | 1367 | GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE); |
1479 | GNUNET_assert (connection->write_buffer_off <= connection->write_buffer_size); | 1368 | GNUNET_assert (connection->write_buffer_off <= connection->write_buffer_size); |
1480 | GNUNET_assert (connection->write_buffer_pos <= connection->write_buffer_size); | 1369 | GNUNET_assert (connection->write_buffer_pos <= connection->write_buffer_size); |
@@ -1485,32 +1374,32 @@ GNUNET_CONNECTION_notify_transmit_ready (struct GNUNET_CONNECTION_Handle *connec | |||
1485 | connection->nth.notify_size = size; | 1374 | connection->nth.notify_size = size; |
1486 | connection->nth.transmit_timeout = GNUNET_TIME_relative_to_absolute (timeout); | 1375 | connection->nth.transmit_timeout = GNUNET_TIME_relative_to_absolute (timeout); |
1487 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->nth.timeout_task); | 1376 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->nth.timeout_task); |
1488 | if ((connection->sock == NULL) && (connection->ap_head == NULL) && | 1377 | if ((NULL == connection->sock) && |
1489 | (connection->dns_active == NULL)) | 1378 | (NULL == connection->ap_head) && |
1379 | (NULL == connection->dns_active)) | ||
1490 | { | 1380 | { |
1491 | if (connection->write_task != GNUNET_SCHEDULER_NO_TASK) | 1381 | if (GNUNET_SCHEDULER_NO_TASK != connection->write_task) |
1492 | GNUNET_SCHEDULER_cancel (connection->write_task); | 1382 | GNUNET_SCHEDULER_cancel (connection->write_task); |
1493 | connection->write_task = GNUNET_SCHEDULER_add_now (&connect_error, connection); | 1383 | connection->write_task = GNUNET_SCHEDULER_add_now (&connect_error, connection); |
1494 | return &connection->nth; | 1384 | return &connection->nth; |
1495 | } | 1385 | } |
1496 | if (GNUNET_SCHEDULER_NO_TASK != connection->write_task) | 1386 | if (GNUNET_SCHEDULER_NO_TASK != connection->write_task) |
1497 | return &connection->nth; | 1387 | return &connection->nth; /* previous transmission still in progress */ |
1498 | if (connection->sock != NULL) | 1388 | if (NULL != connection->sock) |
1499 | { | 1389 | { |
1500 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling transmit_ready (%p).\n", connection); | 1390 | /* connected, try to transmit now */ |
1391 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling transmission (%p).\n", connection); | ||
1501 | connection->write_task = | 1392 | connection->write_task = |
1502 | GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining | 1393 | GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining |
1503 | (connection->nth.transmit_timeout), | 1394 | (connection->nth.transmit_timeout), |
1504 | connection->sock, &transmit_ready, connection); | 1395 | connection->sock, &transmit_ready, connection); |
1396 | return &connection->nth; | ||
1505 | } | 1397 | } |
1506 | else | 1398 | /* not yet connected, wait for connection */ |
1507 | { | 1399 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1508 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1400 | "Need to wait to schedule transmission for connection, adding timeout task (%p).\n", connection); |
1509 | "CCS-Scheduling transmit_ready, adding timeout task (%p).\n", connection); | 1401 | connection->nth.timeout_task = |
1510 | connection->ccs |= COCO_TRANSMIT_READY; | 1402 | GNUNET_SCHEDULER_add_delayed (timeout, &transmit_timeout, connection); |
1511 | connection->nth.timeout_task = | ||
1512 | GNUNET_SCHEDULER_add_delayed (timeout, &transmit_timeout, connection); | ||
1513 | } | ||
1514 | return &connection->nth; | 1403 | return &connection->nth; |
1515 | } | 1404 | } |
1516 | 1405 | ||
@@ -1525,24 +1414,18 @@ GNUNET_CONNECTION_notify_transmit_ready_cancel (struct | |||
1525 | GNUNET_CONNECTION_TransmitHandle | 1414 | GNUNET_CONNECTION_TransmitHandle |
1526 | *th) | 1415 | *th) |
1527 | { | 1416 | { |
1528 | GNUNET_assert (th->notify_ready != NULL); | 1417 | GNUNET_assert (NULL != th->notify_ready); |
1529 | if (0 != (th->connection->ccs & COCO_TRANSMIT_READY)) | 1418 | th->notify_ready = NULL; |
1419 | if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task) | ||
1530 | { | 1420 | { |
1531 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1532 | "notify_transmit_ready_cancel cancels timeout_task (%p)\n", th); | ||
1533 | GNUNET_SCHEDULER_cancel (th->timeout_task); | 1421 | GNUNET_SCHEDULER_cancel (th->timeout_task); |
1534 | th->timeout_task = GNUNET_SCHEDULER_NO_TASK; | 1422 | th->timeout_task = GNUNET_SCHEDULER_NO_TASK; |
1535 | th->connection->ccs -= COCO_TRANSMIT_READY; | ||
1536 | } | 1423 | } |
1537 | else | 1424 | if (GNUNET_SCHEDULER_NO_TASK != th->connection->write_task) |
1538 | { | 1425 | { |
1539 | if (th->connection->write_task != GNUNET_SCHEDULER_NO_TASK) | 1426 | GNUNET_SCHEDULER_cancel (th->connection->write_task); |
1540 | { | 1427 | th->connection->write_task = GNUNET_SCHEDULER_NO_TASK; |
1541 | GNUNET_SCHEDULER_cancel (th->connection->write_task); | ||
1542 | th->connection->write_task = GNUNET_SCHEDULER_NO_TASK; | ||
1543 | } | ||
1544 | } | 1428 | } |
1545 | th->notify_ready = NULL; | ||
1546 | } | 1429 | } |
1547 | 1430 | ||
1548 | /* end of connection.c */ | 1431 | /* end of connection.c */ |