use long long
[oweals/gnunet.git] / src / dht / gnunet-service-dht_clients.c
index 13102a9981165015443cf1a7419df5fe9956b4e8..1a4e71314a8f21a8593a895ac01487443a06787a 100644 (file)
  */
 
 #include "platform.h"
+#include "gnunet_constants.h"
 #include "gnunet_protocols.h"
 #include "gnunet_statistics_service.h"
 #include "gnunet-service-dht.h"
 #include "gnunet-service-dht_clients.h"
 #include "gnunet-service-dht_datacache.h"
 #include "gnunet-service-dht_neighbours.h"
-#include "dht_new.h"
+#include "dht.h"
 
 
 /**
@@ -250,10 +251,11 @@ remove_client_records (void *cls, const GNUNET_HashCode * key, void *value)
   GNUNET_assert (GNUNET_YES ==
                 GNUNET_CONTAINER_multihashmap_remove (forward_map,
                                                       key, record));
-  GNUNET_CONTAINER_heap_remove_node (record->hnode);
-  GNUNET_array_append (record->seen_replies,
-                      record->seen_replies_count,
-                      *key);
+  if (NULL != record->hnode)
+    GNUNET_CONTAINER_heap_remove_node (record->hnode);
+  GNUNET_array_grow (record->seen_replies,
+                    record->seen_replies_count,
+                    0);
   GNUNET_free (record);
   return GNUNET_YES;
 }
@@ -302,12 +304,19 @@ transmit_request (struct ClientQueryRecord *cqr)
 {
   int32_t reply_bf_mutator;
   struct GNUNET_CONTAINER_BloomFilter *reply_bf;
+  struct GNUNET_CONTAINER_BloomFilter *peer_bf;
 
+  GNUNET_STATISTICS_update (GDS_stats,
+                            gettext_noop ("# GET requests from clients injected"), 1,
+                            GNUNET_NO);
   reply_bf_mutator = (int32_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
                                                         UINT32_MAX);
   reply_bf = GNUNET_BLOCK_construct_bloomfilter (reply_bf_mutator,
                                                 cqr->seen_replies,
                                                 cqr->seen_replies_count);
+  peer_bf = GNUNET_CONTAINER_bloomfilter_init (NULL,
+                                              DHT_BLOOM_SIZE,
+                                              GNUNET_CONSTANTS_BLOOMFILTER_K);
   GDS_NEIGHBOURS_handle_get (cqr->type,
                             cqr->msg_options,
                             cqr->replication,
@@ -317,12 +326,13 @@ transmit_request (struct ClientQueryRecord *cqr)
                             cqr->xquery_size,
                             reply_bf,
                             reply_bf_mutator,
-                            NULL /* no peers blocked initially */);
+                            peer_bf);
   GNUNET_CONTAINER_bloomfilter_free (reply_bf);
+  GNUNET_CONTAINER_bloomfilter_free (peer_bf);
 
   /* exponential back-off for retries, max 1h */
   cqr->retry_frequency = 
-    GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_HOURS,
+    GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_HOURS,
                              GNUNET_TIME_relative_multiply (cqr->retry_frequency, 2));
   cqr->retry_time = GNUNET_TIME_relative_to_absolute (cqr->retry_frequency);
 }
@@ -360,6 +370,8 @@ transmit_next_request_task (void *cls,
          return;
        }
       transmit_request (cqr);
+      cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap, cqr,
+                                                cqr->retry_time.abs_value);
     }
 }
 
@@ -376,6 +388,7 @@ handle_dht_local_put (void *cls, struct GNUNET_SERVER_Client *client,
                      const struct GNUNET_MessageHeader *message)
 {
   const struct GNUNET_DHT_ClientPutMessage *dht_msg;
+  struct GNUNET_CONTAINER_BloomFilter *peer_bf;
   uint16_t size;
   
   size = ntohs (message->size);
@@ -383,7 +396,11 @@ handle_dht_local_put (void *cls, struct GNUNET_SERVER_Client *client,
     {
       GNUNET_break (0);
       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+      return;
     }
+  GNUNET_STATISTICS_update (GDS_stats,
+                            gettext_noop ("# PUT requests received from clients"), 1,
+                            GNUNET_NO);
   dht_msg = (const struct GNUNET_DHT_ClientPutMessage *) message;
   /* give to local clients */
   GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
@@ -401,16 +418,20 @@ handle_dht_local_put (void *cls, struct GNUNET_SERVER_Client *client,
                            size - sizeof (struct GNUNET_DHT_ClientPutMessage),
                            &dht_msg[1]);
   /* route to other peers */
+  peer_bf = GNUNET_CONTAINER_bloomfilter_init (NULL,
+                                              DHT_BLOOM_SIZE,
+                                              GNUNET_CONSTANTS_BLOOMFILTER_K);
   GDS_NEIGHBOURS_handle_put (ntohl (dht_msg->type),
                             ntohl (dht_msg->options),
                             ntohl (dht_msg->desired_replication_level),
                             GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
                             0 /* hop count */,
-                            NULL /* peer bloom filter */,
+                            peer_bf,
                             &dht_msg->key,
                             0, NULL,
                             &dht_msg[1],
                             size - sizeof (struct GNUNET_DHT_ClientPutMessage));
+  GNUNET_CONTAINER_bloomfilter_free (peer_bf);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }
 
@@ -444,7 +465,9 @@ handle_dht_local_get (void *cls, struct GNUNET_SERVER_Client *client,
   xquery_size = size - sizeof (struct GNUNET_DHT_ClientGetMessage);
   get = (const struct GNUNET_DHT_ClientGetMessage *) message;
   xquery = (const char*) &get[1];
-
+  GNUNET_STATISTICS_update (GDS_stats,
+                            gettext_noop ("# GET requests received from clients"), 1,
+                            GNUNET_NO);
   
   cqr = GNUNET_malloc (sizeof (struct ClientQueryRecord) + xquery_size);
   cqr->key = get->key;
@@ -530,6 +553,9 @@ handle_dht_local_get_stop (void *cls, struct GNUNET_SERVER_Client *client,
     (const struct GNUNET_DHT_ClientGetStopMessage *) message;
   struct RemoveByUniqueIdContext ctx;
   
+  GNUNET_STATISTICS_update (GDS_stats,
+                            gettext_noop ("# GET STOP requests received from clients"), 1,
+                            GNUNET_NO);
   ctx.client = find_active_client (client);
   ctx.unique_id = dht_stop_msg->unique_id;
   GNUNET_CONTAINER_multihashmap_get_multiple (forward_map,
@@ -685,7 +711,12 @@ forward_reply (void *cls, const GNUNET_HashCode * key, void *value)
   
   if ( (record->type != GNUNET_BLOCK_TYPE_ANY) &&
        (record->type != frc->type) )
-    return GNUNET_YES; /* type mismatch */
+    {
+      GNUNET_STATISTICS_update (GDS_stats,
+                               gettext_noop ("# Key match, type mismatches in REPLY to CLIENT"), 1,
+                               GNUNET_NO);
+      return GNUNET_YES; /* type mismatch */
+    }
   GNUNET_CRYPTO_hash (frc->data,
                      frc->data_size,
                      &ch);
@@ -693,7 +724,12 @@ forward_reply (void *cls, const GNUNET_HashCode * key, void *value)
     if (0 == memcmp (&record->seen_replies[i],
                     &ch,
                     sizeof (GNUNET_HashCode)))
-      return GNUNET_YES; /* duplicate */             
+      {
+       GNUNET_STATISTICS_update (GDS_stats,
+                                 gettext_noop ("# Duplicate REPLIES to CLIENT request dropped"), 1,
+                                 GNUNET_NO);
+       return GNUNET_YES; /* duplicate */             
+      }
   eval =
     GNUNET_BLOCK_evaluate (GDS_block_context, 
                           record->type, key, 
@@ -728,9 +764,12 @@ forward_reply (void *cls, const GNUNET_HashCode * key, void *value)
     return GNUNET_NO;
   case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Unsupported block type (%u) in request!\n",
+                _("Unsupported block type (%u) in request!\n"),
                 record->type);
     return GNUNET_NO;
+  default:
+    GNUNET_break (0);
+    return GNUNET_NO;
   }
   if (GNUNET_NO == frc->do_copy)
     {
@@ -747,6 +786,9 @@ forward_reply (void *cls, const GNUNET_HashCode * key, void *value)
              sizeof (struct PendingMessage) + ntohs (frc->pm->msg->size));
       pm->next = pm->prev = NULL;
     }
+  GNUNET_STATISTICS_update (GDS_stats,
+                            gettext_noop ("# RESULTS queued for clients"), 1,
+                            GNUNET_NO);
   reply = (struct GNUNET_DHT_ClientResultMessage*) &pm[1];  
   reply->unique_id = record->unique_id;
   add_pending_message (record->client, pm);
@@ -790,7 +832,12 @@ GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration,
 
   if (NULL ==
       GNUNET_CONTAINER_multihashmap_get (forward_map, key))
+  {
+    GNUNET_STATISTICS_update (GDS_stats,
+                             gettext_noop ("# REPLIES ignored for CLIENTS (no match)"), 1,
+                             GNUNET_NO);
     return; /* no matching request, fast exit! */
+  }
   msize = sizeof(struct GNUNET_DHT_ClientResultMessage) + data_size + 
     (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity);
   if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
@@ -811,10 +858,10 @@ GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration,
   reply->expiration = GNUNET_TIME_absolute_hton (expiration);
   reply->key = *key;
   paths = (struct GNUNET_PeerIdentity*) &reply[1];
-  memcpy (paths, get_path, 
-         sizeof (struct GNUNET_PeerIdentity) * get_path_length);
-  memcpy (&paths[get_path_length], 
-         put_path, sizeof (struct GNUNET_PeerIdentity) * put_path_length);
+  memcpy (paths, put_path, 
+         sizeof (struct GNUNET_PeerIdentity) * put_path_length);
+  memcpy (&paths[put_path_length], 
+         get_path, sizeof (struct GNUNET_PeerIdentity) * get_path_length);
   memcpy (&paths[get_path_length + put_path_length],
          data, 
          data_size);
@@ -829,6 +876,9 @@ GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration,
   if (GNUNET_NO == frc.do_copy)
     {
       /* did not match any of the requests, free! */
+      GNUNET_STATISTICS_update (GDS_stats,
+                               gettext_noop ("# REPLIES ignored for CLIENTS (no match)"), 1,
+                               GNUNET_NO);
       GNUNET_free (pm);
     }
 }