check
[oweals/gnunet.git] / src / core / gnunet-service-core.c
index 088ec8ba6dfbc7bb928e0ce28057ec51d673731c..f54e4a7a0434537530cbec2904c460ccb6c52ec6 100644 (file)
@@ -1375,6 +1375,7 @@ destroy_active_client_request (void *cls,
 
   peer.hashPubKey = *key;
   n = find_neighbour (&peer);
+  GNUNET_assert (NULL != n);
   GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
                               n->active_client_request_tail,
                               car);
@@ -1433,6 +1434,11 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
 
 /**
  * Helper function for handle_client_iterate_peers.
+ *
+ * @param cls the 'struct GNUNET_SERVER_TransmitContext' to queue replies
+ * @param key identity of the connected peer
+ * @param value the 'struct Neighbour' for the peer
+ * @return GNUNET_OK (continue to iterate)
  */
 static int
 queue_connect_message (void *cls,
@@ -1498,10 +1504,46 @@ handle_client_iterate_peers (void *cls,
 {
   struct GNUNET_MessageHeader done_msg;
   struct GNUNET_SERVER_TransmitContext *tc;
-
+  int msize;
   /* notify new client about existing neighbours */
+
+  msize = ntohs(message->size);
+  tc = GNUNET_SERVER_transmit_context_create (client);
+  if (msize == sizeof(struct GNUNET_MessageHeader))
+    GNUNET_CONTAINER_multihashmap_iterate (neighbours, &queue_connect_message, tc);
+  else
+    GNUNET_break(0);
+
+  done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
+  done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END);
+  GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
+  GNUNET_SERVER_transmit_context_run (tc,
+                                      GNUNET_TIME_UNIT_FOREVER_REL);
+}
+
+/**
+ * Handle CORE_ITERATE_PEERS request.  Notify client about existing neighbours.
+ *
+ * @param cls unused
+ * @param client client sending the iteration request
+ * @param message iteration request message
+ */
+static void
+handle_client_have_peer (void *cls,
+                             struct GNUNET_SERVER_Client *client,
+                             const struct GNUNET_MessageHeader *message)
+
+{
+  struct GNUNET_MessageHeader done_msg;
+  struct GNUNET_SERVER_TransmitContext *tc;
+  struct GNUNET_PeerIdentity *peer;
+
   tc = GNUNET_SERVER_transmit_context_create (client);
-  GNUNET_CONTAINER_multihashmap_iterate (neighbours, &queue_connect_message, tc);
+  peer = (struct GNUNET_PeerIdentity *) &message[1];
+  GNUNET_CONTAINER_multihashmap_get_multiple(neighbours,
+                                            &peer->hashPubKey, 
+                                            &queue_connect_message, 
+                                            tc);
   done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
   done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END);
   GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
@@ -1512,6 +1554,10 @@ handle_client_iterate_peers (void *cls,
 
 /**
  * Handle REQUEST_INFO request.
+ *
+ * @param cls unused
+ * @param client client sending the request
+ * @param message iteration request message
  */
 static void
 handle_client_request_info (void *cls,
@@ -1525,7 +1571,9 @@ handle_client_request_info (void *cls,
   int32_t want_reserv;
   int32_t got_reserv;
   unsigned long long old_preference;
+  struct GNUNET_TIME_Relative rdelay;
 
+  rdelay = GNUNET_TIME_relative_get_zero();
 #if DEBUG_CORE_CLIENT
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Core service receives `%s' request.\n", "REQUEST_INFO");
@@ -1575,8 +1623,9 @@ handle_client_request_info (void *cls,
         }
       else if (want_reserv > 0)
         {
-         if (GNUNET_BANDWIDTH_tracker_get_delay (&n->available_recv_window,
-                                                 want_reserv).rel_value == 0)
+         rdelay = GNUNET_BANDWIDTH_tracker_get_delay (&n->available_recv_window,
+                                                      want_reserv);
+         if (rdelay.rel_value == 0)
            got_reserv = want_reserv;
          else
             got_reserv = 0; /* all or nothing */
@@ -1601,6 +1650,7 @@ handle_client_request_info (void *cls,
                  (int) got_reserv);
 #endif
       cim.reserved_amount = htonl (got_reserv);
+      cim.reserve_delay = GNUNET_TIME_relative_hton (rdelay);
       cim.rim_id = rcm->rim_id;
       cim.bw_out = n->bw_out;
       cim.preference = n->current_preference;
@@ -2848,10 +2898,13 @@ handle_client_send (void *cls,
              GNUNET_i2s (&sm->peer),
              (unsigned int) msize);
 #endif  
+  GNUNET_break (0 == ntohl (sm->reserved));
   e = GNUNET_malloc (sizeof (struct MessageEntry) + msize);
   e->deadline = GNUNET_TIME_absolute_ntoh (sm->deadline);
   e->priority = ntohl (sm->priority);
   e->size = msize;
+  if (GNUNET_YES != (int) ntohl (sm->cork))
+    e->got_slack = GNUNET_YES;
   memcpy (&e[1], &sm[1], msize);
 
   /* insert, keep list sorted by deadline */
@@ -2908,6 +2961,10 @@ notify_transport_connect_done (void *cls,
     }
   if (buf == NULL)
     {
+      GNUNET_STATISTICS_update (stats,
+                                gettext_noop ("# connection requests timed out in transport"),
+                                1,
+                                GNUNET_NO);
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                  _("Failed to connect to `%4s': transport failed to connect\n"),
                  GNUNET_i2s (&n->peer));
@@ -2944,10 +3001,11 @@ handle_client_request_connect (void *cls,
                   &my_identity, 
                   sizeof (struct GNUNET_PeerIdentity)))
     {
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+      /* In this case a client has asked us to connect to ourselves, not really an error! */
+      GNUNET_SERVER_receive_done (client, GNUNET_OK);
       return;
     }
+  timeout = GNUNET_TIME_relative_ntoh (cm->timeout);
   GNUNET_break (ntohl (cm->reserved) == 0);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
   n = find_neighbour (&cm->peer);
@@ -2956,20 +3014,26 @@ handle_client_request_connect (void *cls,
   if ( (GNUNET_YES == n->is_connected) ||
        (n->th != NULL) )
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Core received `%s' request for `%4s', already connected!\n",
-                 "REQUEST_CONNECT",
-                 GNUNET_i2s (&cm->peer));
       if (GNUNET_YES == n->is_connected) 
        GNUNET_STATISTICS_update (stats, 
                                  gettext_noop ("# connection requests ignored (already connected)"), 
                                  1,
                                  GNUNET_NO);
       else
-       GNUNET_STATISTICS_update (stats, 
-                                 gettext_noop ("# connection requests ignored (already trying)"), 
-                                 1,
-                                 GNUNET_NO);
+        {
+          GNUNET_TRANSPORT_notify_transmit_ready_cancel(n->th);
+          n->th = GNUNET_TRANSPORT_notify_transmit_ready (transport,
+                                                          &cm->peer,
+                                                          sizeof (struct GNUNET_MessageHeader), 0,
+                                                          timeout,
+                                                          &notify_transport_connect_done,
+                                                          n);
+          GNUNET_break (NULL != n->th);
+          GNUNET_STATISTICS_update (stats,
+                                    gettext_noop ("# connection requests retried (due to repeat request connect)"),
+                                    1,
+                                    GNUNET_NO);
+        }
       return; /* already connected, or at least trying */
     }
   GNUNET_STATISTICS_update (stats, 
@@ -2977,12 +3041,13 @@ handle_client_request_connect (void *cls,
                            1,
                            GNUNET_NO);
 
+#if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Core received `%s' request for `%4s', will try to establish connection\n",
              "REQUEST_CONNECT",
              GNUNET_i2s (&cm->peer));
+#endif
 
-  timeout = GNUNET_TIME_relative_ntoh (cm->timeout);
   /* ask transport to connect to the peer */
   n->th = GNUNET_TRANSPORT_notify_transmit_ready (transport,
                                                  &cm->peer,
@@ -3014,9 +3079,9 @@ process_hello_retry_send_key (void *cls,
 
   if (err_msg != NULL)
   {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     _("Error in communication with PEERINFO service\n"));
-       /* return; */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                _("Error in communication with PEERINFO service\n"));
+    /* return; */
   }
 
   if (peer == NULL)
@@ -3336,9 +3401,9 @@ process_hello_retry_handle_set_key (void *cls,
 
   if (err_msg != NULL)
   {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     _("Error in communication with PEERINFO service\n"));
-       /* return; */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                _("Error in communication with PEERINFO service\n"));
+    /* return; */
   }
 
   if (peer == NULL)
@@ -4636,6 +4701,9 @@ run (void *cls,
     {&handle_client_iterate_peers, NULL,
      GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS,
      sizeof (struct GNUNET_MessageHeader)},
+    {&handle_client_have_peer, NULL,
+     GNUNET_MESSAGE_TYPE_CORE_PEER_CONNECTED,
+     sizeof (struct GNUNET_MessageHeader) + sizeof(struct GNUNET_PeerIdentity)},
     {&handle_client_request_info, NULL,
      GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO,
      sizeof (struct RequestInfoMessage)},