diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-04-19 11:55:40 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-04-19 11:55:40 +0000 |
commit | 50c4e060fc721dfe2af9115639a4d47e88e04f00 (patch) | |
tree | 5ba39a3f1335c65bd750261cc78db9f39bb076fc /src/util/connection.c | |
parent | 93a5401e858e978aa2d7fc090fc1f6612c15dc3f (diff) | |
download | gnunet-50c4e060fc721dfe2af9115639a4d47e88e04f00.tar.gz gnunet-50c4e060fc721dfe2af9115639a4d47e88e04f00.zip |
-simplifying destruction of connections, cleaning up server API -- all for #2274
Diffstat (limited to 'src/util/connection.c')
-rw-r--r-- | src/util/connection.c | 187 |
1 files changed, 55 insertions, 132 deletions
diff --git a/src/util/connection.c b/src/util/connection.c index 8d0042b7b..4473b7bb5 100644 --- a/src/util/connection.c +++ b/src/util/connection.c | |||
@@ -62,12 +62,8 @@ enum ConnectContinuations | |||
62 | /** | 62 | /** |
63 | * Call "transmit_ready". | 63 | * Call "transmit_ready". |
64 | */ | 64 | */ |
65 | COCO_TRANSMIT_READY = 2, | 65 | COCO_TRANSMIT_READY = 2 |
66 | 66 | ||
67 | /** | ||
68 | * Call "destroy_continuation". | ||
69 | */ | ||
70 | COCO_DESTROY_CONTINUATION = 4 | ||
71 | }; | 67 | }; |
72 | 68 | ||
73 | 69 | ||
@@ -243,11 +239,6 @@ struct GNUNET_CONNECTION_Handle | |||
243 | GNUNET_SCHEDULER_TaskIdentifier write_task; | 239 | GNUNET_SCHEDULER_TaskIdentifier write_task; |
244 | 240 | ||
245 | /** | 241 | /** |
246 | * Destroy task (if already scheduled). | ||
247 | */ | ||
248 | GNUNET_SCHEDULER_TaskIdentifier destroy_task; | ||
249 | |||
250 | /** | ||
251 | * Handle to a pending DNS lookup request. | 242 | * Handle to a pending DNS lookup request. |
252 | */ | 243 | */ |
253 | struct GNUNET_RESOLVER_RequestHandle *dns_active; | 244 | struct GNUNET_RESOLVER_RequestHandle *dns_active; |
@@ -515,96 +506,6 @@ receive_again (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | |||
515 | 506 | ||
516 | 507 | ||
517 | /** | 508 | /** |
518 | * Scheduler let us know that the connect task is finished (or was | ||
519 | * cancelled due to shutdown). Now really clean up. | ||
520 | * | ||
521 | * @param cls our "struct GNUNET_CONNECTION_Handle *" | ||
522 | * @param tc unused | ||
523 | */ | ||
524 | static void | ||
525 | destroy_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
526 | { | ||
527 | struct GNUNET_CONNECTION_Handle *connection = cls; | ||
528 | GNUNET_CONNECTION_TransmitReadyNotify notify; | ||
529 | struct AddressProbe *pos; | ||
530 | |||
531 | connection->destroy_task = GNUNET_SCHEDULER_NO_TASK; | ||
532 | GNUNET_assert (connection->dns_active == NULL); | ||
533 | if (0 != (connection->ccs & COCO_TRANSMIT_READY)) | ||
534 | { | ||
535 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroy waits for CCS-TR to be done (%p)\n", | ||
536 | connection); | ||
537 | connection->ccs |= COCO_DESTROY_CONTINUATION; | ||
538 | return; | ||
539 | } | ||
540 | if (connection->write_task != GNUNET_SCHEDULER_NO_TASK) | ||
541 | { | ||
542 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
543 | "Destroy waits for write_task to be done (%p)\n", connection); | ||
544 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->destroy_task); | ||
545 | connection->destroy_task = | ||
546 | GNUNET_SCHEDULER_add_after (connection->write_task, &destroy_continuation, | ||
547 | connection); | ||
548 | return; | ||
549 | } | ||
550 | if (0 != (connection->ccs & COCO_RECEIVE_AGAIN)) | ||
551 | { | ||
552 | connection->ccs |= COCO_DESTROY_CONTINUATION; | ||
553 | return; | ||
554 | } | ||
555 | if (connection->sock != NULL) | ||
556 | { | ||
557 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connection (%p)\n", connection); | ||
558 | if (connection->persist != GNUNET_YES) | ||
559 | { | ||
560 | if ((GNUNET_YES != GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR)) | ||
561 | && (errno != ENOTCONN) && (errno != ECONNRESET)) | ||
562 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "shutdown"); | ||
563 | } | ||
564 | } | ||
565 | if (connection->read_task != GNUNET_SCHEDULER_NO_TASK) | ||
566 | { | ||
567 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->destroy_task); | ||
568 | connection->destroy_task = | ||
569 | GNUNET_SCHEDULER_add_after (connection->read_task, &destroy_continuation, | ||
570 | connection); | ||
571 | return; | ||
572 | } | ||
573 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroy actually runs (%p)!\n", connection); | ||
574 | while (NULL != (pos = connection->ap_head)) | ||
575 | { | ||
576 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock)); | ||
577 | GNUNET_SCHEDULER_cancel (pos->task); | ||
578 | GNUNET_CONTAINER_DLL_remove (connection->ap_head, connection->ap_tail, pos); | ||
579 | GNUNET_free (pos); | ||
580 | } | ||
581 | GNUNET_assert (connection->nth.timeout_task == GNUNET_SCHEDULER_NO_TASK); | ||
582 | GNUNET_assert (connection->ccs == COCO_NONE); | ||
583 | if (NULL != (notify = connection->nth.notify_ready)) | ||
584 | { | ||
585 | connection->nth.notify_ready = NULL; | ||
586 | notify (connection->nth.notify_ready_cls, 0, NULL); | ||
587 | } | ||
588 | |||
589 | if (connection->sock != NULL) | ||
590 | { | ||
591 | if (connection->persist != GNUNET_YES) | ||
592 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock)); | ||
593 | else | ||
594 | GNUNET_free (connection->sock); /* at least no memory leak (we deliberately | ||
595 | * leak the socket in this special case) ... */ | ||
596 | } | ||
597 | GNUNET_free_non_null (connection->addr); | ||
598 | GNUNET_free_non_null (connection->hostname); | ||
599 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->destroy_task); | ||
600 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Freeing memory of connection %p.\n", connection); | ||
601 | GNUNET_free (connection->write_buffer); | ||
602 | GNUNET_free (connection); | ||
603 | } | ||
604 | |||
605 | |||
606 | |||
607 | /** | ||
608 | * See if we are now connected. If not, wait longer for | 509 | * See if we are now connected. If not, wait longer for |
609 | * connect to succeed. If connected, we should be able | 510 | * connect to succeed. If connected, we should be able |
610 | * to write now as well, unless we timed out. | 511 | * to write now as well, unless we timed out. |
@@ -654,14 +555,6 @@ connect_fail_continuation (struct GNUNET_CONNECTION_Handle *h) | |||
654 | GNUNET_assert (h->write_task == GNUNET_SCHEDULER_NO_TASK); | 555 | GNUNET_assert (h->write_task == GNUNET_SCHEDULER_NO_TASK); |
655 | h->write_task = GNUNET_SCHEDULER_add_now (&transmit_ready, h); | 556 | h->write_task = GNUNET_SCHEDULER_add_now (&transmit_ready, h); |
656 | } | 557 | } |
657 | if (0 != (h->ccs & COCO_DESTROY_CONTINUATION)) | ||
658 | { | ||
659 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
660 | "connect_fail_continuation runs destroy_continuation (%p)\n", h); | ||
661 | h->ccs -= COCO_DESTROY_CONTINUATION; | ||
662 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->destroy_task); | ||
663 | h->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_continuation, h); | ||
664 | } | ||
665 | } | 558 | } |
666 | 559 | ||
667 | 560 | ||
@@ -699,14 +592,6 @@ connect_success_continuation (struct GNUNET_CONNECTION_Handle *connection) | |||
699 | (connection->nth.transmit_timeout), connection->sock, | 592 | (connection->nth.transmit_timeout), connection->sock, |
700 | &transmit_ready, connection); | 593 | &transmit_ready, connection); |
701 | } | 594 | } |
702 | if (0 != (connection->ccs & COCO_DESTROY_CONTINUATION)) | ||
703 | { | ||
704 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
705 | "connect_success_continuation runs destroy_continuation (%p)\n", connection); | ||
706 | connection->ccs -= COCO_DESTROY_CONTINUATION; | ||
707 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->destroy_task); | ||
708 | connection->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_continuation, connection); | ||
709 | } | ||
710 | } | 595 | } |
711 | 596 | ||
712 | 597 | ||
@@ -1012,16 +897,19 @@ GNUNET_CONNECTION_check (struct GNUNET_CONNECTION_Handle *sock) | |||
1012 | 897 | ||
1013 | 898 | ||
1014 | /** | 899 | /** |
1015 | * Close the connection and free associated resources. A pending | 900 | * Close the connection and free associated resources. There must |
1016 | * request for transmission is automatically cancelled (we might | 901 | * not be any pending requests for reading or writing to the |
1017 | * want to change this in the future). We require that there | 902 | * connection at this time. |
1018 | * are no active pending requests for reading from the connection. | ||
1019 | * | 903 | * |
1020 | * @param connection connection to destroy | 904 | * @param connection connection to destroy |
1021 | */ | 905 | */ |
1022 | void | 906 | void |
1023 | GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection) | 907 | GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection) |
1024 | { | 908 | { |
909 | struct AddressProbe *pos; | ||
910 | |||
911 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connection (%p)\n", connection); | ||
912 | GNUNET_assert (NULL == connection->nth.notify_ready); | ||
1025 | GNUNET_assert (NULL == connection->receiver); | 913 | GNUNET_assert (NULL == connection->receiver); |
1026 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->read_task); | 914 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->read_task); |
1027 | if (connection->write_task != GNUNET_SCHEDULER_NO_TASK) | 915 | if (connection->write_task != GNUNET_SCHEDULER_NO_TASK) |
@@ -1030,14 +918,49 @@ GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection) | |||
1030 | connection->write_task = GNUNET_SCHEDULER_NO_TASK; | 918 | connection->write_task = GNUNET_SCHEDULER_NO_TASK; |
1031 | connection->write_buffer_off = 0; | 919 | connection->write_buffer_off = 0; |
1032 | } | 920 | } |
921 | if (connection->read_task != GNUNET_SCHEDULER_NO_TASK) | ||
922 | { | ||
923 | GNUNET_SCHEDULER_cancel (connection->read_task); | ||
924 | connection->read_task = GNUNET_SCHEDULER_NO_TASK; | ||
925 | } | ||
926 | if (connection->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK) | ||
927 | { | ||
928 | GNUNET_SCHEDULER_cancel (connection->nth.timeout_task); | ||
929 | connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
930 | } | ||
1033 | connection->nth.notify_ready = NULL; | 931 | connection->nth.notify_ready = NULL; |
1034 | if (connection->dns_active != NULL) | 932 | if (NULL != connection->dns_active) |
1035 | { | 933 | { |
1036 | GNUNET_RESOLVER_request_cancel (connection->dns_active); | 934 | GNUNET_RESOLVER_request_cancel (connection->dns_active); |
1037 | connection->dns_active = NULL; | 935 | connection->dns_active = NULL; |
1038 | } | 936 | } |
1039 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->destroy_task); | 937 | while (NULL != (pos = connection->ap_head)) |
1040 | connection->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_continuation, connection); | 938 | { |
939 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock)); | ||
940 | GNUNET_SCHEDULER_cancel (pos->task); | ||
941 | GNUNET_CONTAINER_DLL_remove (connection->ap_head, connection->ap_tail, pos); | ||
942 | GNUNET_free (pos); | ||
943 | } | ||
944 | if ( (NULL != connection->sock) && | ||
945 | (connection->persist != GNUNET_YES) ) | ||
946 | { | ||
947 | if ((GNUNET_YES != GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR)) && | ||
948 | (errno != ENOTCONN) && | ||
949 | (errno != ECONNRESET) ) | ||
950 | LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "shutdown"); | ||
951 | } | ||
952 | if (connection->sock != NULL) | ||
953 | { | ||
954 | if (connection->persist != GNUNET_YES) | ||
955 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock)); | ||
956 | else | ||
957 | GNUNET_free (connection->sock); /* at least no memory leak (we deliberately | ||
958 | * leak the socket in this special case) ... */ | ||
959 | } | ||
960 | GNUNET_free_non_null (connection->addr); | ||
961 | GNUNET_free_non_null (connection->hostname); | ||
962 | GNUNET_free (connection->write_buffer); | ||
963 | GNUNET_free (connection); | ||
1041 | } | 964 | } |
1042 | 965 | ||
1043 | 966 | ||
@@ -1045,15 +968,15 @@ GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection) | |||
1045 | * Tell the receiver callback that a timeout was reached. | 968 | * Tell the receiver callback that a timeout was reached. |
1046 | */ | 969 | */ |
1047 | static void | 970 | static void |
1048 | signal_timeout (struct GNUNET_CONNECTION_Handle *sh) | 971 | signal_timeout (struct GNUNET_CONNECTION_Handle *connection) |
1049 | { | 972 | { |
1050 | GNUNET_CONNECTION_Receiver receiver; | 973 | GNUNET_CONNECTION_Receiver receiver; |
1051 | 974 | ||
1052 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Network signals time out to receiver (%p)!\n", | 975 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Network signals time out to receiver (%p)!\n", |
1053 | sh); | 976 | connection); |
1054 | GNUNET_assert (NULL != (receiver = sh->receiver)); | 977 | GNUNET_assert (NULL != (receiver = connection->receiver)); |
1055 | sh->receiver = NULL; | 978 | connection->receiver = NULL; |
1056 | receiver (sh->receiver_cls, NULL, 0, NULL, 0, 0); | 979 | receiver (connection->receiver_cls, NULL, 0, NULL, 0, 0); |
1057 | } | 980 | } |
1058 | 981 | ||
1059 | 982 | ||
@@ -1061,13 +984,13 @@ signal_timeout (struct GNUNET_CONNECTION_Handle *sh) | |||
1061 | * Tell the receiver callback that we had an IO error. | 984 | * Tell the receiver callback that we had an IO error. |
1062 | */ | 985 | */ |
1063 | static void | 986 | static void |
1064 | signal_error (struct GNUNET_CONNECTION_Handle *sh, int errcode) | 987 | signal_error (struct GNUNET_CONNECTION_Handle *connection, int errcode) |
1065 | { | 988 | { |
1066 | GNUNET_CONNECTION_Receiver receiver; | 989 | GNUNET_CONNECTION_Receiver receiver; |
1067 | 990 | ||
1068 | GNUNET_assert (NULL != (receiver = sh->receiver)); | 991 | GNUNET_assert (NULL != (receiver = connection->receiver)); |
1069 | sh->receiver = NULL; | 992 | connection->receiver = NULL; |
1070 | receiver (sh->receiver_cls, NULL, 0, sh->addr, sh->addrlen, errcode); | 993 | receiver (connection->receiver_cls, NULL, 0, connection->addr, connection->addrlen, errcode); |
1071 | } | 994 | } |
1072 | 995 | ||
1073 | 996 | ||