-added STREAM_shutdown & test case for shutdown
authorSree Harsha Totakura <totakura@in.tum.de>
Sat, 7 Apr 2012 13:00:46 +0000 (13:00 +0000)
committerSree Harsha Totakura <totakura@in.tum.de>
Sat, 7 Apr 2012 13:00:46 +0000 (13:00 +0000)
src/stream/stream_api.c
src/stream/test_stream_local.c

index 92c1093f777ba19fccf502dd7c0883edf5a96314..535850de2a02cf1d49462cca150eb6af03d1c412 100644 (file)
@@ -231,6 +231,11 @@ struct GNUNET_STREAM_Socket
    */
   struct GNUNET_STREAM_IOReadHandle *read_handle;
 
+  /**
+   * The shutdown handle associated with this socket
+   */
+  struct GNUNET_STREAM_ShutdownHandle *shutdown_handle;
+
   /**
    * Buffer for storing received messages
    */
@@ -443,6 +448,16 @@ struct GNUNET_STREAM_ShutdownHandle
    * Which operation to shutdown? SHUT_RD, SHUT_WR or SHUT_RDWR
    */
   int operation;
+
+  /**
+   * Shutdown completion callback
+   */
+  GNUNET_STREAM_ShutdownCompletion completion_cb;
+
+  /**
+   * Closure for completion callback
+   */
+  void *completion_cls;
 };
 
 
@@ -1559,6 +1574,10 @@ handle_close (struct GNUNET_STREAM_Socket *socket,
 {
   struct GNUNET_STREAM_MessageHeader *close_ack;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "%x: Received CLOSE from %x\n",
+              socket->our_id,
+              socket->other_peer);
   close_ack = GNUNET_malloc (sizeof (struct GNUNET_STREAM_MessageHeader));
   close_ack->header.size = htons (sizeof (struct GNUNET_STREAM_MessageHeader));
   close_ack->header.type = htons (GNUNET_MESSAGE_TYPE_STREAM_CLOSE_ACK);
@@ -1625,10 +1644,30 @@ handle_close_ack (struct GNUNET_STREAM_Socket *socket,
                   const struct GNUNET_STREAM_MessageHeader *message,
                   const struct GNUNET_ATS_Information*atsi)
 {
+  struct GNUNET_STREAM_ShutdownHandle *shutdown_handle;
+
+  shutdown_handle = socket->shutdown_handle;
   switch (socket->state)
     {
     case STATE_CLOSE_WAIT:
       socket->state = STATE_CLOSED;
+      if ( (NULL == shutdown_handle) ||
+           (SHUT_RDWR != shutdown_handle->operation) )
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                      "%x: Received CLOSE_ACK when shutdown handle is NULL or "
+                      "not for SHUT_RDWR\n",
+                      socket->our_id);
+          return GNUNET_OK;
+        }
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "%x: Received CLOSE_ACK from %x\n",
+                  socket->our_id,
+                  socket->other_peer);
+      if (NULL != shutdown_handle->completion_cb) /* Shutdown completion */
+        shutdown_handle->completion_cb(shutdown_handle->completion_cls,
+                                       SHUT_RDWR);
+      GNUNET_free (shutdown_handle); /* Free shutdown handle */
       break;
     default:
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2515,16 +2554,25 @@ GNUNET_STREAM_shutdown (struct GNUNET_STREAM_Socket *socket,
 {
   struct GNUNET_STREAM_ShutdownHandle *handle;
   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;
+
   msg = GNUNET_malloc (sizeof (struct GNUNET_STREAM_MessageHeader));
   msg->header.size = htons (sizeof (struct GNUNET_STREAM_MessageHeader));
   switch (operation)
     {
     case SHUT_RD:
       handle->operation = SHUT_RD;
-
+      if (NULL != socket->read_handle)
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Existing read handle should be cancelled before shutting"
+                    " down reading\n");
       break;
     case SHUT_WR:
       handle->operation = SHUT_WR;
index c3fcc649264194b4c75ac9c469d9ff29e6519e05..125873acf65a564932c6d2fc596b6be62e1f6f87 100644 (file)
@@ -59,6 +59,11 @@ struct PeerData
    */
   struct GNUNET_STREAM_IOReadHandle *io_read_handle;
 
+  /**
+   * Peer's shutdown handle
+   */
+  struct GNUNET_STREAM_ShutdownHandle *shutdown_handle;
+
   /**
    * Our Peer id
    */
@@ -109,7 +114,7 @@ static int reading_success;
  * Check whether peers successfully shut down.
  */
 static void
-shutdown_callback (void *cls, const char *emsg)
+peergroup_shutdown_callback (void *cls, const char *emsg)
 {
   if (emsg != NULL)
   {
@@ -126,10 +131,10 @@ shutdown_callback (void *cls, const char *emsg)
 
 
 /**
- * Shutdown nicely
+ * Close sockets and stop testing deamons nicely
  */
 static void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_close (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   if (NULL != peer1.socket)
     GNUNET_STREAM_close (peer1.socket);
@@ -149,11 +154,43 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   GNUNET_TESTING_daemons_stop (pg,
                                GNUNET_TIME_relative_multiply
                                (GNUNET_TIME_UNIT_SECONDS, 5),
-                               &shutdown_callback,
+                               &peergroup_shutdown_callback,
                                NULL);
 }
 
 
+/**
+ * Completion callback for shutdown
+ *
+ * @param cls the closure from GNUNET_STREAM_shutdown call
+ * @param operation the operation that was shutdown (SHUT_RD, SHUT_WR,
+ *          SHUT_RDWR) 
+ */
+static void 
+shutdown_completion (void *cls,
+                     int operation)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "STREAM shutdown successful\n");
+  GNUNET_SCHEDULER_add_now (&do_close,
+                            cls);
+}
+
+
+
+/**
+ * Shutdown sockets gracefully
+ */
+static void
+do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  peer1.shutdown_handle = GNUNET_STREAM_shutdown (peer1.socket, 
+                                                  SHUT_RDWR,
+                                                  &shutdown_completion,
+                                                  cls);
+}
+
+
 /**
  * Something went wrong and timed out. Kill everything and set error flag
  */
@@ -167,7 +204,7 @@ do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     }
   result = GNUNET_SYSERR;
   abort_task = 0;
-  do_shutdown (cls, tc);
+  do_close (cls, tc);  
 }
 
 /**
@@ -237,7 +274,7 @@ write_completion (void *cls,
       else
         {
           writing_success = GNUNET_YES;
-          if (GNUNET_YES == reading_success) 
+          if (GNUNET_YES == reading_success)
             GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
         }
     }