gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r25047 - gnunet/src/stream


From: gnunet
Subject: [GNUnet-SVN] r25047 - gnunet/src/stream
Date: Mon, 19 Nov 2012 14:07:04 +0100

Author: harsha
Date: 2012-11-19 14:07:04 +0100 (Mon, 19 Nov 2012)
New Revision: 25047

Modified:
   gnunet/src/stream/stream_api.c
Log:
- towards cleaner shutdowns

Modified: gnunet/src/stream/stream_api.c
===================================================================
--- gnunet/src/stream/stream_api.c      2012-11-19 13:01:07 UTC (rev 25046)
+++ gnunet/src/stream/stream_api.c      2012-11-19 13:07:04 UTC (rev 25047)
@@ -302,6 +302,16 @@
   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 @@
   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 @@
 
 
 /**
+ * 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 @@
   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 @@
   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 @@
     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 @@
   default:
     break;
   }
-
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "%s: Received CLOSE from %s\n",
        GNUNET_i2s (&socket->other_peer),
@@ -1979,9 +2013,10 @@
   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 @@
   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 @@
 
 
 /**
- * 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 @@
 {
   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);
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]