diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2012-11-19 13:07:04 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2012-11-19 13:07:04 +0000 |
commit | c404e1af3fe0bb2521f86927b8e9e17735f7a3dc (patch) | |
tree | 94a6e054835205aa4cde33062d1133abb9e41424 /src/stream | |
parent | 203bb6f1d36b66c0ea4c81b0aaada34f336a8ae2 (diff) | |
download | gnunet-c404e1af3fe0bb2521f86927b8e9e17735f7a3dc.tar.gz gnunet-c404e1af3fe0bb2521f86927b8e9e17735f7a3dc.zip |
- towards cleaner shutdowns
Diffstat (limited to 'src/stream')
-rw-r--r-- | src/stream/stream_api.c | 71 |
1 files changed, 60 insertions, 11 deletions
diff --git a/src/stream/stream_api.c b/src/stream/stream_api.c index 05d09aced..24fd8e8f8 100644 --- a/src/stream/stream_api.c +++ b/src/stream/stream_api.c | |||
@@ -302,6 +302,16 @@ struct GNUNET_STREAM_Socket | |||
302 | int testing_active; | 302 | int testing_active; |
303 | 303 | ||
304 | /** | 304 | /** |
305 | * Is receive closed | ||
306 | */ | ||
307 | int receive_closed; | ||
308 | |||
309 | /** | ||
310 | * Is transmission closed | ||
311 | */ | ||
312 | int transmit_closed; | ||
313 | |||
314 | /** | ||
305 | * The application port number (type: uint32_t) | 315 | * The application port number (type: uint32_t) |
306 | */ | 316 | */ |
307 | GNUNET_MESH_ApplicationType app_port; | 317 | GNUNET_MESH_ApplicationType app_port; |
@@ -546,6 +556,11 @@ struct GNUNET_STREAM_ShutdownHandle | |||
546 | GNUNET_SCHEDULER_TaskIdentifier close_msg_retransmission_task_id; | 556 | GNUNET_SCHEDULER_TaskIdentifier close_msg_retransmission_task_id; |
547 | 557 | ||
548 | /** | 558 | /** |
559 | * Task scheduled to call the shutdown continuation callback | ||
560 | */ | ||
561 | GNUNET_SCHEDULER_TaskIdentifier call_cont_task_id; | ||
562 | |||
563 | /** | ||
549 | * Which operation to shutdown? SHUT_RD, SHUT_WR or SHUT_RDWR | 564 | * Which operation to shutdown? SHUT_RD, SHUT_WR or SHUT_RDWR |
550 | */ | 565 | */ |
551 | int operation; | 566 | int operation; |
@@ -1673,6 +1688,28 @@ client_handle_transmit_close (void *cls, | |||
1673 | 1688 | ||
1674 | 1689 | ||
1675 | /** | 1690 | /** |
1691 | * Task for calling the shutdown continuation callback | ||
1692 | * | ||
1693 | * @param cls the socket | ||
1694 | * @param tc the scheduler task context | ||
1695 | */ | ||
1696 | static void | ||
1697 | call_cont_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1698 | { | ||
1699 | struct GNUNET_STREAM_Socket *socket = cls; | ||
1700 | |||
1701 | GNUNET_assert (NULL != socket->shutdown_handle); | ||
1702 | socket->shutdown_handle->call_cont_task_id = GNUNET_SCHEDULER_NO_TASK; | ||
1703 | if (NULL != socket->shutdown_handle->completion_cb) | ||
1704 | socket->shutdown_handle->completion_cb | ||
1705 | (socket->shutdown_handle->completion_cls, | ||
1706 | socket->shutdown_handle->operation); | ||
1707 | GNUNET_free (socket->shutdown_handle); | ||
1708 | socket->shutdown_handle = NULL; | ||
1709 | } | ||
1710 | |||
1711 | |||
1712 | /** | ||
1676 | * Generic handler for GNUNET_MESSAGE_TYPE_STREAM_*_CLOSE_ACK messages | 1713 | * Generic handler for GNUNET_MESSAGE_TYPE_STREAM_*_CLOSE_ACK messages |
1677 | * | 1714 | * |
1678 | * @param socket the socket | 1715 | * @param socket the socket |
@@ -1697,6 +1734,7 @@ handle_generic_close_ack (struct GNUNET_STREAM_Socket *socket, | |||
1697 | shutdown_handle = socket->shutdown_handle; | 1734 | shutdown_handle = socket->shutdown_handle; |
1698 | if (NULL == shutdown_handle) | 1735 | if (NULL == shutdown_handle) |
1699 | { | 1736 | { |
1737 | /* This happens when the shudown handle is cancelled */ | ||
1700 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1738 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1701 | "%s: Received CLOSE_ACK when shutdown handle is NULL\n", | 1739 | "%s: Received CLOSE_ACK when shutdown handle is NULL\n", |
1702 | GNUNET_i2s (&socket->other_peer)); | 1740 | GNUNET_i2s (&socket->other_peer)); |
@@ -1774,9 +1812,8 @@ handle_generic_close_ack (struct GNUNET_STREAM_Socket *socket, | |||
1774 | default: | 1812 | default: |
1775 | GNUNET_assert (0); | 1813 | GNUNET_assert (0); |
1776 | } | 1814 | } |
1777 | if (NULL != shutdown_handle->completion_cb) /* Shutdown completion */ | 1815 | shutdown_handle->call_cont_task_id = GNUNET_SCHEDULER_add_now |
1778 | shutdown_handle->completion_cb(shutdown_handle->completion_cls, | 1816 | (&call_cont_task, socket); |
1779 | operation); | ||
1780 | if (GNUNET_SCHEDULER_NO_TASK | 1817 | if (GNUNET_SCHEDULER_NO_TASK |
1781 | != shutdown_handle->close_msg_retransmission_task_id) | 1818 | != shutdown_handle->close_msg_retransmission_task_id) |
1782 | { | 1819 | { |
@@ -1785,8 +1822,6 @@ handle_generic_close_ack (struct GNUNET_STREAM_Socket *socket, | |||
1785 | shutdown_handle->close_msg_retransmission_task_id = | 1822 | shutdown_handle->close_msg_retransmission_task_id = |
1786 | GNUNET_SCHEDULER_NO_TASK; | 1823 | GNUNET_SCHEDULER_NO_TASK; |
1787 | } | 1824 | } |
1788 | GNUNET_free (shutdown_handle); /* Free shutdown handle */ | ||
1789 | socket->shutdown_handle = NULL; | ||
1790 | return GNUNET_OK; | 1825 | return GNUNET_OK; |
1791 | } | 1826 | } |
1792 | 1827 | ||
@@ -1970,7 +2005,6 @@ handle_close (struct GNUNET_STREAM_Socket *socket, | |||
1970 | default: | 2005 | default: |
1971 | break; | 2006 | break; |
1972 | } | 2007 | } |
1973 | |||
1974 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2008 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1975 | "%s: Received CLOSE from %s\n", | 2009 | "%s: Received CLOSE from %s\n", |
1976 | GNUNET_i2s (&socket->other_peer), | 2010 | GNUNET_i2s (&socket->other_peer), |
@@ -1979,9 +2013,10 @@ handle_close (struct GNUNET_STREAM_Socket *socket, | |||
1979 | close_ack->header.size = htons (sizeof (struct GNUNET_STREAM_MessageHeader)); | 2013 | close_ack->header.size = htons (sizeof (struct GNUNET_STREAM_MessageHeader)); |
1980 | close_ack->header.type = htons (GNUNET_MESSAGE_TYPE_STREAM_CLOSE_ACK); | 2014 | close_ack->header.type = htons (GNUNET_MESSAGE_TYPE_STREAM_CLOSE_ACK); |
1981 | queue_message (socket, close_ack, &set_state_closed, NULL, GNUNET_NO); | 2015 | queue_message (socket, close_ack, &set_state_closed, NULL, GNUNET_NO); |
1982 | if (socket->state == STATE_CLOSED) | 2016 | if (STATE_CLOSED == socket->state) |
1983 | return GNUNET_OK; | 2017 | return GNUNET_OK; |
1984 | 2018 | socket->receive_closed = GNUNET_YES; | |
2019 | socket->transmit_closed = GNUNET_YES; | ||
1985 | GNUNET_free_non_null (socket->receive_buffer); /* Free the receive buffer */ | 2020 | GNUNET_free_non_null (socket->receive_buffer); /* Free the receive buffer */ |
1986 | socket->receive_buffer = NULL; | 2021 | socket->receive_buffer = NULL; |
1987 | socket->receive_buffer_size = 0; | 2022 | socket->receive_buffer_size = 0; |
@@ -3037,13 +3072,22 @@ GNUNET_STREAM_shutdown (struct GNUNET_STREAM_Socket *socket, | |||
3037 | struct GNUNET_STREAM_MessageHeader *msg; | 3072 | struct GNUNET_STREAM_MessageHeader *msg; |
3038 | 3073 | ||
3039 | GNUNET_assert (NULL == socket->shutdown_handle); | 3074 | GNUNET_assert (NULL == socket->shutdown_handle); |
3040 | |||
3041 | handle = GNUNET_malloc (sizeof (struct GNUNET_STREAM_ShutdownHandle)); | 3075 | handle = GNUNET_malloc (sizeof (struct GNUNET_STREAM_ShutdownHandle)); |
3042 | handle->socket = socket; | 3076 | handle->socket = socket; |
3043 | handle->completion_cb = completion_cb; | 3077 | handle->completion_cb = completion_cb; |
3044 | handle->completion_cls = completion_cls; | 3078 | handle->completion_cls = completion_cls; |
3045 | socket->shutdown_handle = handle; | 3079 | socket->shutdown_handle = handle; |
3046 | 3080 | if ( ((GNUNET_YES == socket->receive_closed) && (SHUT_RD == operation)) | |
3081 | || ((GNUNET_YES == socket->transmit_closed) && (SHUT_WR == operation)) | ||
3082 | || ((GNUNET_YES == socket->transmit_closed) | ||
3083 | && (GNUNET_YES == socket->receive_closed) | ||
3084 | && (SHUT_RDWR == operation)) ) | ||
3085 | { | ||
3086 | handle->operation = operation; | ||
3087 | handle->call_cont_task_id = GNUNET_SCHEDULER_add_now (&call_cont_task, | ||
3088 | socket); | ||
3089 | return handle; | ||
3090 | } | ||
3047 | msg = GNUNET_malloc (sizeof (struct GNUNET_STREAM_MessageHeader)); | 3091 | msg = GNUNET_malloc (sizeof (struct GNUNET_STREAM_MessageHeader)); |
3048 | msg->header.size = htons (sizeof (struct GNUNET_STREAM_MessageHeader)); | 3092 | msg->header.size = htons (sizeof (struct GNUNET_STREAM_MessageHeader)); |
3049 | switch (operation) | 3093 | switch (operation) |
@@ -3098,7 +3142,10 @@ GNUNET_STREAM_shutdown (struct GNUNET_STREAM_Socket *socket, | |||
3098 | 3142 | ||
3099 | 3143 | ||
3100 | /** | 3144 | /** |
3101 | * Cancels a pending shutdown | 3145 | * Cancels a pending shutdown. Note that the shutdown messages may already be |
3146 | * sent and the stream is shutdown already for the operation given to | ||
3147 | * GNUNET_STREAM_shutdown(). This function only clears up any retranmissions of | ||
3148 | * shutdown messages and frees the shutdown handle. | ||
3102 | * | 3149 | * |
3103 | * @param handle the shutdown handle returned from GNUNET_STREAM_shutdown | 3150 | * @param handle the shutdown handle returned from GNUNET_STREAM_shutdown |
3104 | */ | 3151 | */ |
@@ -3107,6 +3154,8 @@ GNUNET_STREAM_shutdown_cancel (struct GNUNET_STREAM_ShutdownHandle *handle) | |||
3107 | { | 3154 | { |
3108 | if (GNUNET_SCHEDULER_NO_TASK != handle->close_msg_retransmission_task_id) | 3155 | if (GNUNET_SCHEDULER_NO_TASK != handle->close_msg_retransmission_task_id) |
3109 | GNUNET_SCHEDULER_cancel (handle->close_msg_retransmission_task_id); | 3156 | GNUNET_SCHEDULER_cancel (handle->close_msg_retransmission_task_id); |
3157 | if (GNUNET_SCHEDULER_NO_TASK != handle->call_cont_task_id) | ||
3158 | GNUNET_SCHEDULER_cancel (handle->call_cont_task_id); | ||
3110 | handle->socket->shutdown_handle = NULL; | 3159 | handle->socket->shutdown_handle = NULL; |
3111 | GNUNET_free (handle); | 3160 | GNUNET_free (handle); |
3112 | } | 3161 | } |