-doxygen
[oweals/gnunet.git] / src / fs / gnunet-service-fs_mesh_client.c
index e785a507dda124ccebc053f76bdc432b4f96aeec..95e3702741527b2215cc97efd31c4026a861a096 100644 (file)
@@ -92,8 +92,8 @@ struct GSF_MeshRequest
   enum GNUNET_BLOCK_Type type;
 
   /**
-   * Did we transmit this request already? YES if we are
-   * in the 'waiting_map', NO if we are in the 'pending' DLL.
+   * Did we transmit this request already? #GNUNET_YES if we are
+   * in the 'waiting_map', #GNUNET_NO if we are in the 'pending' DLL.
    */
   int was_transmitted;
 };
@@ -115,7 +115,7 @@ struct MeshHandle
   struct GSF_MeshRequest *pending_tail;
 
   /**
-   * Map from query to 'struct GSF_MeshRequest's waiting for
+   * Map from query to `struct GSF_MeshRequest`s waiting for
    * a reply.
    */
   struct GNUNET_CONTAINER_MultiHashMap *waiting_map;
@@ -180,10 +180,10 @@ transmit_pending (struct MeshHandle *mh);
  * Iterator called on each entry in a waiting map to
  * move it back to the pending list.
  *
- * @param cls the 'struct MeshHandle'
+ * @param cls the `struct MeshHandle`
  * @param key the key of the entry in the map (the query)
- * @param value the 'struct GSF_MeshRequest' to move to pending
- * @return GNUNET_YES (continue to iterate)
+ * @param value the `struct GSF_MeshRequest` to move to pending
+ * @return #GNUNET_YES (continue to iterate)
  */
 static int
 move_to_pending (void *cls,
@@ -213,13 +213,14 @@ move_to_pending (void *cls,
 static void
 reset_mesh (struct MeshHandle *mh)
 {
-  const struct GNUNET_MESH_Channel *channel = mh->channel;
+  struct GNUNET_MESH_Channel *channel = mh->channel;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Resetting mesh channel to %s\n",
              GNUNET_i2s (&mh->target));
   mh->channel = NULL;
-  GNUNET_MESH_channel_destroy (channel);
+  if (NULL != channel)
+    GNUNET_MESH_channel_destroy (channel);
   GNUNET_CONTAINER_multihashmap_iterate (mh->waiting_map,
                                         &move_to_pending,
                                         mh);
@@ -227,8 +228,7 @@ reset_mesh (struct MeshHandle *mh)
                                          mh,
                                          &mh->target,
                                          GNUNET_APPLICATION_TYPE_FS_BLOCK_TRANSFER,
-                                         GNUNET_NO,
-                                         GNUNET_YES);
+                                         GNUNET_MESH_OPTION_RELIABLE);
   transmit_pending (mh);
 }
 
@@ -236,7 +236,7 @@ reset_mesh (struct MeshHandle *mh)
 /**
  * Task called when it is time to destroy an inactive mesh channel.
  *
- * @param cls the 'struct MeshHandle' to tear down
+ * @param cls the `struct MeshHandle` to tear down
  * @param tc scheduler context, unused
  */
 static void
@@ -259,7 +259,7 @@ mesh_timeout (void *cls,
 /**
  * Task called when it is time to reset an mesh.
  *
- * @param cls the 'struct MeshHandle' to tear down
+ * @param cls the `struct MeshHandle` to tear down
  * @param tc scheduler context, unused
  */
 static void
@@ -294,9 +294,9 @@ reset_mesh_async (struct MeshHandle *mh)
  * query via a mesh.
  *
  * @param cls the struct MeshHandle for which we did the write call
- * @param size the number of bytes that can be written to 'buf'
+ * @param size the number of bytes that can be written to @a buf
  * @param buf where to write the message
- * @return number of bytes written to 'buf'
+ * @return number of bytes written to @a buf
  */
 static size_t
 transmit_sqm (void *cls,
@@ -367,7 +367,7 @@ transmit_pending (struct MeshHandle *mh)
 
 
 /**
- * Closure for 'handle_reply'.
+ * Closure for handle_reply().
  */
 struct HandleReplyClosure
 {
@@ -403,10 +403,10 @@ struct HandleReplyClosure
  * Iterator called on each entry in a waiting map to
  * process a result.
  *
- * @param cls the 'struct HandleReplyClosure'
+ * @param cls the `struct HandleReplyClosure`
  * @param key the key of the entry in the map (the query)
- * @param value the 'struct GSF_MeshRequest' to handle result for
- * @return GNUNET_YES (continue to iterate)
+ * @param value the `struct GSF_MeshRequest` to handle result for
+ * @return #GNUNET_YES (continue to iterate)
  */
 static int
 handle_reply (void *cls,
@@ -421,6 +421,7 @@ handle_reply (void *cls,
            hrc->expiration,
            hrc->data_size,
            hrc->data);
+  sr->proc = NULL;
   GSF_mesh_query_cancel (sr);
   hrc->found = GNUNET_YES;
   return GNUNET_YES;
@@ -431,11 +432,11 @@ handle_reply (void *cls,
  * Functions with this signature are called whenever a complete reply
  * is received.
  *
- * @param cls closure with the 'struct MeshHandle'
+ * @param cls closure with the `struct MeshHandle`
  * @param channel channel handle
  * @param channel_ctx channel context
  * @param message the actual message
- * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
  */
 static int
 reply_cb (void *cls,
@@ -466,6 +467,11 @@ reply_cb (void *cls,
                            &srm[1], msize, &query))
   {
     GNUNET_break_op (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Received bogus reply of type %u with %u bytes via mesh from peer %s\n",
+                type,
+                msize,
+                GNUNET_i2s (&mh->target));
     reset_mesh_async (mh);
     return GNUNET_SYSERR;
   }
@@ -527,17 +533,19 @@ get_mesh (const struct GNUNET_PeerIdentity *target)
                                                 mh);
   mh->waiting_map = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_YES);
   mh->target = *target;
-  mh->channel = GNUNET_MESH_channel_create (mesh_handle,
-                                         mh,
-                                         &mh->target,
-                                         GNUNET_APPLICATION_TYPE_FS_BLOCK_TRANSFER,
-                                         GNUNET_NO,
-                                         GNUNET_YES);
   GNUNET_assert (GNUNET_OK ==
                 GNUNET_CONTAINER_multipeermap_put (mesh_map,
                                                    &mh->target,
                                                    mh,
                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  mh->channel = GNUNET_MESH_channel_create (mesh_handle,
+                                            mh,
+                                            &mh->target,
+                                            GNUNET_APPLICATION_TYPE_FS_BLOCK_TRANSFER,
+                                            GNUNET_MESH_OPTION_RELIABLE);
+  GNUNET_assert (mh ==
+                 GNUNET_CONTAINER_multipeermap_get (mesh_map,
+                                                    target));
   return mh;
 }
 
@@ -549,7 +557,7 @@ get_mesh (const struct GNUNET_PeerIdentity *target)
  * @param query hash to query for the block
  * @param type desired type for the block
  * @param proc function to call with result
- * @param proc_cls closure for 'proc'
+ * @param proc_cls closure for @a proc
  * @return handle to cancel the operation
  */
 struct GSF_MeshRequest *
@@ -590,7 +598,17 @@ void
 GSF_mesh_query_cancel (struct GSF_MeshRequest *sr)
 {
   struct MeshHandle *mh = sr->mh;
+  GSF_MeshReplyProcessor p;
 
+  p = sr->proc;
+  sr->proc = NULL;
+  if (NULL != p)
+  {
+    /* signal failure / cancellation to callback */
+    p (sr->proc_cls, GNUNET_BLOCK_TYPE_ANY,
+       GNUNET_TIME_UNIT_ZERO_ABS,
+       0, NULL);
+  }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Cancelled query for %s via mesh to %s\n",
              GNUNET_h2s (&sr->query),
@@ -618,10 +636,10 @@ GSF_mesh_query_cancel (struct GSF_MeshRequest *sr)
  * call the 'proc' continuation and release associated
  * resources.
  *
- * @param cls the 'struct MeshHandle'
+ * @param cls the `struct MeshHandle`
  * @param key the key of the entry in the map (the query)
- * @param value the 'struct GSF_MeshRequest' to clean up
- * @return GNUNET_YES (continue to iterate)
+ * @param value the `struct GSF_MeshRequest` to clean up
+ * @return #GNUNET_YES (continue to iterate)
  */
 static int
 free_waiting_entry (void *cls,
@@ -630,9 +648,6 @@ free_waiting_entry (void *cls,
 {
   struct GSF_MeshRequest *sr = value;
 
-  sr->proc (sr->proc_cls, GNUNET_BLOCK_TYPE_ANY,
-           GNUNET_TIME_UNIT_FOREVER_ABS,
-           0, NULL);
   GSF_mesh_query_cancel (sr);
   return GNUNET_YES;
 }
@@ -640,7 +655,7 @@ free_waiting_entry (void *cls,
 
 /**
  * Function called by mesh when a client disconnects.
- * Cleans up our 'struct MeshClient' of that channel.
+ * Cleans up our `struct MeshClient` of that channel.
  *
  * @param cls NULL
  * @param channel channel of the disconnecting client
@@ -659,12 +674,15 @@ cleaner_cb (void *cls,
   GNUNET_assert (channel == mh->channel);
   mh->channel = NULL;
   while (NULL != (sr = mh->pending_head))
-  {
-    sr->proc (sr->proc_cls, GNUNET_BLOCK_TYPE_ANY,
-             GNUNET_TIME_UNIT_FOREVER_ABS,
-             0, NULL);
     GSF_mesh_query_cancel (sr);
-  }
+  /* first remove `mh` from the `mesh_map`, so that if the
+     callback from `free_waiting_entry()` happens to re-issue
+     the request, we don't immediately have it back in the
+     `waiting_map`. */
+  GNUNET_assert (GNUNET_OK ==
+                GNUNET_CONTAINER_multipeermap_remove (mesh_map,
+                                                      &mh->target,
+                                                      mh));
   GNUNET_CONTAINER_multihashmap_iterate (mh->waiting_map,
                                         &free_waiting_entry,
                                         mh);
@@ -674,10 +692,8 @@ cleaner_cb (void *cls,
     GNUNET_SCHEDULER_cancel (mh->timeout_task);
   if (GNUNET_SCHEDULER_NO_TASK != mh->reset_task)
     GNUNET_SCHEDULER_cancel (mh->reset_task);
-  GNUNET_assert (GNUNET_OK ==
-                GNUNET_CONTAINER_multipeermap_remove (mesh_map,
-                                                      &mh->target,
-                                                      mh));
+  GNUNET_assert (0 ==
+                 GNUNET_CONTAINER_multihashmap_size (mh->waiting_map));
   GNUNET_CONTAINER_multihashmap_destroy (mh->waiting_map);
   GNUNET_free (mh);
 }
@@ -718,15 +734,12 @@ release_meshs (void *cls,
               void *value)
 {
   struct MeshHandle *mh = value;
-  struct GNUNET_MESH_Channel *tun;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Timeout on mesh channel to %s\n",
              GNUNET_i2s (&mh->target));
-  tun = mh->channel;
-  mh->channel = NULL;
-  if (NULL != tun)
-    GNUNET_MESH_channel_destroy (tun);
+  if (NULL != mh->channel)
+    GNUNET_MESH_channel_destroy (mh->channel);
   return GNUNET_YES;
 }