aboutsummaryrefslogtreecommitdiff
path: root/src/stream
diff options
context:
space:
mode:
authorharsha <harsha@140774ce-b5e7-0310-ab8b-a85725594a96>2012-11-19 13:07:04 +0000
committerharsha <harsha@140774ce-b5e7-0310-ab8b-a85725594a96>2012-11-19 13:07:04 +0000
commit61742965a1644f990c38a04cdd76cf69a6e0c019 (patch)
tree94a6e054835205aa4cde33062d1133abb9e41424 /src/stream
parentdcdbeffffd1972fa7645f902a611560ff984914e (diff)
- towards cleaner shutdowns
git-svn-id: https://gnunet.org/svn/gnunet@25047 140774ce-b5e7-0310-ab8b-a85725594a96
Diffstat (limited to 'src/stream')
-rw-r--r--src/stream/stream_api.c71
1 files changed, 60 insertions, 11 deletions
diff --git a/src/stream/stream_api.c b/src/stream/stream_api.c
index 05d09aceda..24fd8e8f8e 100644
--- a/src/stream/stream_api.c
+++ b/src/stream/stream_api.c
@@ -302,6 +302,16 @@ struct GNUNET_STREAM_Socket
int testing_active;
/**
+ * Is receive closed
+ */
+ int receive_closed;
+
+ /**
+ * Is transmission closed
+ */
+ int transmit_closed;
+
+ /**
* The application port number (type: uint32_t)
*/
GNUNET_MESH_ApplicationType app_port;
@@ -546,6 +556,11 @@ struct GNUNET_STREAM_ShutdownHandle
GNUNET_SCHEDULER_TaskIdentifier close_msg_retransmission_task_id;
/**
+ * Task scheduled to call the shutdown continuation callback
+ */
+ GNUNET_SCHEDULER_TaskIdentifier call_cont_task_id;
+
+ /**
* Which operation to shutdown? SHUT_RD, SHUT_WR or SHUT_RDWR
*/
int operation;
@@ -1673,6 +1688,28 @@ client_handle_transmit_close (void *cls,
/**
+ * Task for calling the shutdown continuation callback
+ *
+ * @param cls the socket
+ * @param tc the scheduler task context
+ */
+static void
+call_cont_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_STREAM_Socket *socket = cls;
+
+ GNUNET_assert (NULL != socket->shutdown_handle);
+ socket->shutdown_handle->call_cont_task_id = GNUNET_SCHEDULER_NO_TASK;
+ if (NULL != socket->shutdown_handle->completion_cb)
+ socket->shutdown_handle->completion_cb
+ (socket->shutdown_handle->completion_cls,
+ socket->shutdown_handle->operation);
+ GNUNET_free (socket->shutdown_handle);
+ socket->shutdown_handle = NULL;
+}
+
+
+/**
* Generic handler for GNUNET_MESSAGE_TYPE_STREAM_*_CLOSE_ACK messages
*
* @param socket the socket
@@ -1697,6 +1734,7 @@ handle_generic_close_ack (struct GNUNET_STREAM_Socket *socket,
shutdown_handle = socket->shutdown_handle;
if (NULL == shutdown_handle)
{
+ /* This happens when the shudown handle is cancelled */
LOG (GNUNET_ERROR_TYPE_DEBUG,
"%s: Received CLOSE_ACK when shutdown handle is NULL\n",
GNUNET_i2s (&socket->other_peer));
@@ -1774,9 +1812,8 @@ handle_generic_close_ack (struct GNUNET_STREAM_Socket *socket,
default:
GNUNET_assert (0);
}
- if (NULL != shutdown_handle->completion_cb) /* Shutdown completion */
- shutdown_handle->completion_cb(shutdown_handle->completion_cls,
- operation);
+ shutdown_handle->call_cont_task_id = GNUNET_SCHEDULER_add_now
+ (&call_cont_task, socket);
if (GNUNET_SCHEDULER_NO_TASK
!= shutdown_handle->close_msg_retransmission_task_id)
{
@@ -1785,8 +1822,6 @@ handle_generic_close_ack (struct GNUNET_STREAM_Socket *socket,
shutdown_handle->close_msg_retransmission_task_id =
GNUNET_SCHEDULER_NO_TASK;
}
- GNUNET_free (shutdown_handle); /* Free shutdown handle */
- socket->shutdown_handle = NULL;
return GNUNET_OK;
}
@@ -1970,7 +2005,6 @@ handle_close (struct GNUNET_STREAM_Socket *socket,
default:
break;
}
-
LOG (GNUNET_ERROR_TYPE_DEBUG,
"%s: Received CLOSE from %s\n",
GNUNET_i2s (&socket->other_peer),
@@ -1979,9 +2013,10 @@ handle_close (struct GNUNET_STREAM_Socket *socket,
close_ack->header.size = htons (sizeof (struct GNUNET_STREAM_MessageHeader));
close_ack->header.type = htons (GNUNET_MESSAGE_TYPE_STREAM_CLOSE_ACK);
queue_message (socket, close_ack, &set_state_closed, NULL, GNUNET_NO);
- if (socket->state == STATE_CLOSED)
+ if (STATE_CLOSED == socket->state)
return GNUNET_OK;
-
+ socket->receive_closed = GNUNET_YES;
+ socket->transmit_closed = GNUNET_YES;
GNUNET_free_non_null (socket->receive_buffer); /* Free the receive buffer */
socket->receive_buffer = NULL;
socket->receive_buffer_size = 0;
@@ -3037,13 +3072,22 @@ GNUNET_STREAM_shutdown (struct GNUNET_STREAM_Socket *socket,
struct GNUNET_STREAM_MessageHeader *msg;
GNUNET_assert (NULL == socket->shutdown_handle);
-
handle = GNUNET_malloc (sizeof (struct GNUNET_STREAM_ShutdownHandle));
handle->socket = socket;
handle->completion_cb = completion_cb;
handle->completion_cls = completion_cls;
socket->shutdown_handle = handle;
-
+ if ( ((GNUNET_YES == socket->receive_closed) && (SHUT_RD == operation))
+ || ((GNUNET_YES == socket->transmit_closed) && (SHUT_WR == operation))
+ || ((GNUNET_YES == socket->transmit_closed)
+ && (GNUNET_YES == socket->receive_closed)
+ && (SHUT_RDWR == operation)) )
+ {
+ handle->operation = operation;
+ handle->call_cont_task_id = GNUNET_SCHEDULER_add_now (&call_cont_task,
+ socket);
+ return handle;
+ }
msg = GNUNET_malloc (sizeof (struct GNUNET_STREAM_MessageHeader));
msg->header.size = htons (sizeof (struct GNUNET_STREAM_MessageHeader));
switch (operation)
@@ -3098,7 +3142,10 @@ GNUNET_STREAM_shutdown (struct GNUNET_STREAM_Socket *socket,
/**
- * Cancels a pending shutdown
+ * Cancels a pending shutdown. Note that the shutdown messages may already be
+ * sent and the stream is shutdown already for the operation given to
+ * GNUNET_STREAM_shutdown(). This function only clears up any retranmissions of
+ * shutdown messages and frees the shutdown handle.
*
* @param handle the shutdown handle returned from GNUNET_STREAM_shutdown
*/
@@ -3107,6 +3154,8 @@ GNUNET_STREAM_shutdown_cancel (struct GNUNET_STREAM_ShutdownHandle *handle)
{
if (GNUNET_SCHEDULER_NO_TASK != handle->close_msg_retransmission_task_id)
GNUNET_SCHEDULER_cancel (handle->close_msg_retransmission_task_id);
+ if (GNUNET_SCHEDULER_NO_TASK != handle->call_cont_task_id)
+ GNUNET_SCHEDULER_cancel (handle->call_cont_task_id);
handle->socket->shutdown_handle = NULL;
GNUNET_free (handle);
}