aboutsummaryrefslogtreecommitdiff
path: root/src/util/connection.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-04-19 11:55:40 +0000
committerChristian Grothoff <christian@grothoff.org>2012-04-19 11:55:40 +0000
commit50c4e060fc721dfe2af9115639a4d47e88e04f00 (patch)
tree5ba39a3f1335c65bd750261cc78db9f39bb076fc /src/util/connection.c
parent93a5401e858e978aa2d7fc090fc1f6612c15dc3f (diff)
downloadgnunet-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.c187
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 */
524static void
525destroy_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 */
1022void 906void
1023GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection) 907GNUNET_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 */
1047static void 970static void
1048signal_timeout (struct GNUNET_CONNECTION_Handle *sh) 971signal_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 */
1063static void 986static void
1064signal_error (struct GNUNET_CONNECTION_Handle *sh, int errcode) 987signal_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