check
[oweals/gnunet.git] / src / core / core_api.c
index f5f421277527673fb12a0ed5b4f71f1b8b421010..195e94e29d0dcf56a8cda2491dbb669b2c9ab4a0 100644 (file)
@@ -82,6 +82,11 @@ struct PeerRecord
    */
   void *pcic_cls;
 
+  /**
+   * Pointer to free when we call pcic.
+   */
+  void *pcic_ptr;
+
   /**
    * Request information ID for the given pcic (needed in case a
    * request is cancelled after being submitted to core and a new
@@ -346,6 +351,11 @@ struct GNUNET_CORE_TransmitHandle
    */
   uint16_t smr_id;
 
+  /**
+   * Is corking allowed?
+   */
+  int cork;
+
 };
 
 
@@ -414,10 +424,14 @@ disconnect_and_free_peer_entry (void *cls,
   if (NULL != (pcic = pr->pcic))
     {
       pr->pcic = NULL;
+      GNUNET_free_non_null (pr->pcic_ptr);
+      pr->pcic_ptr = NULL;
       pcic (pr->pcic_cls,
            &pr->peer,
            zero,
-           0, 0);
+           0, 
+           GNUNET_TIME_UNIT_FOREVER_REL,
+           0);
     }
   if (pr->timeout_task != GNUNET_SCHEDULER_NO_TASK)
     {
@@ -707,6 +721,8 @@ transmit_message (void *cls,
       sm->priority = htonl (th->priority);
       sm->deadline = GNUNET_TIME_absolute_hton (th->timeout);
       sm->peer = pr->peer;
+      sm->cork = htonl ((uint32_t) th->cork);
+      sm->reserved = htonl (0);
       ret = th->get_message (th->get_message_cls,
                             size - sizeof (struct SendMessage),
                             &sm[1]);
@@ -720,7 +736,8 @@ transmit_message (void *cls,
 #endif
          /* client decided to send nothing! */
          request_next_transmission (pr);
-         return 0;       
+         GNUNET_free (th);
+         return 0;       
        }
 #if DEBUG_CORE
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -732,7 +749,8 @@ transmit_message (void *cls,
        {
          GNUNET_break (0);
          request_next_transmission (pr);
-         return 0;
+         GNUNET_free (th);
+         return 0;
        }
       ret += sizeof (struct SendMessage);
       sm->header.size = htons (ret);
@@ -921,7 +939,7 @@ main_notify_handler (void *cls,
                       &cnm->peer,
                       sizeof (struct GNUNET_PeerIdentity)))
        {
-         /* disconnect from self!? */
+         /* connect to self!? */
          GNUNET_break (0);
          return;
        }
@@ -987,6 +1005,7 @@ main_notify_handler (void *cls,
       if (NULL == h->status_events)
         {
           GNUNET_break (0);
+         return;
         }
       if (msize < sizeof (struct PeerStatusNotifyMessage))
         {
@@ -1240,11 +1259,14 @@ main_notify_handler (void *cls,
        }
       pcic = pr->pcic;
       pr->pcic = NULL;
+      GNUNET_free_non_null (pr->pcic_ptr);
+      pr->pcic_ptr = NULL;
       if (pcic != NULL)
        pcic (pr->pcic_cls,
              &pr->peer,
              cim->bw_out,
              ntohl (cim->reserved_amount),
+             GNUNET_TIME_relative_ntoh (cim->reserve_delay),
              GNUNET_ntohll (cim->preference));
       break;
     default:
@@ -1478,11 +1500,12 @@ GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle)
 
 /**
  * Ask the core to call "notify" once it is ready to transmit the
- * given number of bytes to the specified "target".  If we are not yet
- * connected to the specified peer, a call to this function will cause
- * us to try to establish a connection.
+ * given number of bytes to the specified "target".    Must only be
+ * called after a connection to the respective peer has been
+ * established (and the client has been informed about this).
  *
  * @param handle connection to core service
+ * @param cork is corking allowed for this transmission?
  * @param priority how important is the message?
  * @param maxdelay how long can the message wait?
  * @param target who should receive the message,
@@ -1496,6 +1519,7 @@ GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle)
  */
 struct GNUNET_CORE_TransmitHandle *
 GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
+                                  int cork,
                                    uint32_t priority,
                                    struct GNUNET_TIME_Relative maxdelay,
                                    const struct GNUNET_PeerIdentity *target,
@@ -1530,6 +1554,7 @@ GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
   th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
   th->priority = priority;
   th->msize = notify_size;
+  th->cork = cork;
   /* bound queue size */
   if (pr->queue_size == handle->queue_size)
     {
@@ -1545,8 +1570,12 @@ GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
       if (minp == NULL) 
        {
          GNUNET_break (handle->queue_size != 0);
-         GNUNET_break (pr->queue_size == 0);
+         GNUNET_break (pr->queue_size == 1);
          GNUNET_free(th);
+#if DEBUG_CORE
+         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                     "Dropping transmission request: cannot drop queue head and limit is one\n");
+#endif
          return NULL;
        }
       if (priority <= minp->priority)
@@ -1555,6 +1584,7 @@ GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                      "Dropping transmission request: priority too low\n");
 #endif
+         GNUNET_free(th);
          return NULL; /* priority too low */
        }
       GNUNET_CONTAINER_DLL_remove (pr->pending_head,
@@ -1716,7 +1746,9 @@ peer_request_connect_cont (void *cls,
  * @param peer who should we connect to
  * @param cont function to call once the request has been completed (or timed out)
  * @param cont_cls closure for cont
- * @return NULL on error (cont will not be called), otherwise handle for cancellation
+ *
+ * @return NULL on error or already connected,
+ *         otherwise handle for cancellation
  */
 struct GNUNET_CORE_PeerRequestHandle *
 GNUNET_CORE_peer_request_connect (struct GNUNET_CORE_Handle *h,
@@ -1728,6 +1760,16 @@ GNUNET_CORE_peer_request_connect (struct GNUNET_CORE_Handle *h,
   struct GNUNET_CORE_PeerRequestHandle *ret;
   struct ControlMessage *cm;
   struct ConnectMessage *msg;
+
+  if (NULL != GNUNET_CONTAINER_multihashmap_get (h->peers,
+                                          &peer->hashPubKey))
+    {
+#if DEBUG_CORE
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 
+                "Peers are already connected!\n");
+#endif
+      return NULL;
+    }
   
   cm = GNUNET_malloc (sizeof (struct ControlMessage) + 
                      sizeof (struct ConnectMessage));
@@ -1737,9 +1779,9 @@ GNUNET_CORE_peer_request_connect (struct GNUNET_CORE_Handle *h,
   msg->reserved = htonl (0);
   msg->timeout = GNUNET_TIME_relative_hton (timeout);
   msg->peer = *peer;
-  GNUNET_CONTAINER_DLL_insert (h->control_pending_head,
-                              h->control_pending_tail,
-                              cm);
+  GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head,
+                                   h->control_pending_tail,
+                                   cm);
   ret = GNUNET_malloc (sizeof (struct GNUNET_CORE_PeerRequestHandle));
   ret->h = h;
   ret->cm = cm;
@@ -1788,16 +1830,6 @@ struct GNUNET_CORE_InformationRequestContext
    */
   struct GNUNET_CORE_Handle *h;
 
-  /**
-   * Function to call with the information.
-   */
-  GNUNET_CORE_PeerConfigurationInfoCallback info;
-
-  /**
-   * Closure for info.
-   */
-  void *info_cls;
-
   /**
    * Link to control message, NULL if CM was sent.
    */ 
@@ -1882,8 +1914,6 @@ GNUNET_CORE_peer_change_preference (struct GNUNET_CORE_Handle *h,
   irc = GNUNET_malloc (sizeof (struct GNUNET_CORE_InformationRequestContext));
   irc->h = h;
   irc->pr = pr;
-  irc->info = info;
-  irc->info_cls = info_cls;
   cm = GNUNET_malloc (sizeof (struct ControlMessage) +
                      sizeof (struct RequestInfoMessage));
   cm->cont = &change_preference_send_continuation;
@@ -1901,11 +1931,12 @@ GNUNET_CORE_peer_change_preference (struct GNUNET_CORE_Handle *h,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Queueing CHANGE PREFERENCE request\n");
 #endif
-  GNUNET_CONTAINER_DLL_insert (h->control_pending_head,
-                              h->control_pending_tail,
-                              cm); 
+  GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head,
+                                   h->control_pending_tail,
+                                   cm); 
   pr->pcic = info;
   pr->pcic_cls = info_cls;
+  pr->pcic_ptr = irc; /* for free'ing irc */
   if (h->control_pending_head == cm)
     trigger_next_request (h, GNUNET_NO);
   return irc;
@@ -1929,6 +1960,7 @@ GNUNET_CORE_peer_change_preference_cancel (struct GNUNET_CORE_InformationRequest
   struct GNUNET_CORE_Handle *h = irc->h;
   struct PeerRecord *pr = irc->pr;
 
+  GNUNET_assert (pr->pcic_ptr == irc);
   if (irc->cm != NULL)
     {
       GNUNET_CONTAINER_DLL_remove (h->control_pending_head,
@@ -1938,6 +1970,7 @@ GNUNET_CORE_peer_change_preference_cancel (struct GNUNET_CORE_InformationRequest
     }
   pr->pcic = NULL;
   pr->pcic_cls = NULL;
+  pr->pcic_ptr = NULL;
   GNUNET_free (irc);
 }