Merge branch 'master' of ssh://gnunet.org/gnunet
[oweals/gnunet.git] / src / revocation / gnunet-service-revocation.c
index d4194d9520f60efd2a2cbabe0fb310229d696cfd..9d077f874dd3e7176cefcc9ba9a5105f0856e5f4 100644 (file)
@@ -1,6 +1,6 @@
 /*
   This file is part of GNUnet.
-  Copyright (C) 2013, 2014 Christian Grothoff (and other contributing authors)
+  Copyright (C) 2013, 2014, 2016 GNUnet e.V.
 
   GNUnet is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public Licerevocation as published
@@ -38,6 +38,7 @@
 #include "platform.h"
 #include <math.h>
 #include "gnunet_util_lib.h"
+#include "gnunet_block_lib.h"
 #include "gnunet_constants.h"
 #include "gnunet_protocols.h"
 #include "gnunet_signatures.h"
@@ -68,7 +69,7 @@ struct PeerEntry
   /**
    * Tasked used to trigger the set union operation.
    */
-  struct GNUNET_SCHEDULER_Task * transmit_task;
+  struct GNUNET_SCHEDULER_Task *transmit_task;
 
   /**
    * Handle to active set union operation (over revocation sets).
@@ -114,16 +115,6 @@ static struct GNUNET_CONTAINER_MultiPeerMap *peers;
  */
 static struct GNUNET_PeerIdentity my_identity;
 
-/**
- * Handle to this serivce's server.
- */
-static struct GNUNET_SERVER_Handle *srv;
-
-/**
- * Notification context for convenient sending of replies to the clients.
- */
-static struct GNUNET_SERVER_NotificationContext *nc;
-
 /**
  * File handle for the revocation database.
  */
@@ -164,43 +155,10 @@ new_peer_entry(const struct GNUNET_PeerIdentity *peer)
                                                     &peer_entry->id,
                                                     peer_entry,
                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-  peer_entry->mq = GNUNET_CORE_mq_create (core_api, peer);
   return peer_entry;
 }
 
 
-/**
- * Delete a PeerEntry for the given peer
- *
- * @param peer the identity of the peer to delete
- */
-static void
-delete_peer_entry(const struct GNUNET_PeerIdentity *peer)
-{
-  struct PeerEntry *peer_entry;
-
-  peer_entry = GNUNET_CONTAINER_multipeermap_get (peers,
-                                                  peer);
-  GNUNET_assert (NULL != peer_entry);
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multipeermap_remove (peers,
-                                                       peer,
-                                                       peer_entry));
-  GNUNET_MQ_destroy (peer_entry->mq);
-  if (NULL != peer_entry->transmit_task)
-  {
-    GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
-    peer_entry->transmit_task = NULL;
-  }
-  if (NULL != peer_entry->so)
-  {
-    GNUNET_SET_operation_cancel (peer_entry->so);
-    peer_entry->so = NULL;
-  }
-  GNUNET_free (peer_entry);
-}
-
-
 /**
  * An revoke message has been received, check that it is well-formed.
  *
@@ -234,20 +192,52 @@ verify_revoke_message (const struct RevokeMessage *rm)
 }
 
 
+/**
+ * Handle client connecting to the service.
+ *
+ * @param cls NULL
+ * @param client the new client
+ * @param mq the message queue of @a client
+ * @return @a client
+ */
+static void *
+client_connect_cb (void *cls,
+                  struct GNUNET_SERVICE_Client *client,
+                  struct GNUNET_MQ_Handle *mq)
+{
+  return client;
+}
+
+
+/**
+ * Handle client connecting to the service.
+ *
+ * @param cls NULL
+ * @param client the new client
+ * @param app_cls must alias @a client
+ */
+static void
+client_disconnect_cb (void *cls,
+                     struct GNUNET_SERVICE_Client *client,
+                     void *app_cls)
+{
+  GNUNET_assert (client == app_cls);
+}
+
+
 /**
  * Handle QUERY message from client.
  *
- * @param cls unused
- * @param client who sent the message
- * @param message the message received
+ * @param cls client who sent the message
+ * @param qm the message received
  */
 static void
 handle_query_message (void *cls,
-                     struct GNUNET_SERVER_Client *client,
-                      const struct GNUNET_MessageHeader *message)
+                      const struct QueryMessage *qm)
 {
-  const struct QueryMessage *qm = (const struct QueryMessage *) message;
-  struct QueryResponseMessage qrm;
+  struct GNUNET_SERVICE_Client *client = cls;
+  struct GNUNET_MQ_Envelope *env;
+  struct QueryResponseMessage *qrm;
   struct GNUNET_HashCode hc;
   int res;
 
@@ -261,17 +251,12 @@ handle_query_message (void *cls,
              ? "Received revocation check for valid key `%s' from client\n"
               : "Received revocation check for revoked key `%s' from client\n",
               GNUNET_h2s (&hc));
-  qrm.header.size = htons (sizeof (struct QueryResponseMessage));
-  qrm.header.type = htons (GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE);
-  qrm.is_valid = htonl ((GNUNET_YES == res) ? GNUNET_NO : GNUNET_YES);
-  GNUNET_SERVER_notification_context_add (nc,
-                                          client);
-  GNUNET_SERVER_notification_context_unicast (nc,
-                                              client,
-                                              &qrm.header,
-                                              GNUNET_NO);
-  GNUNET_SERVER_receive_done (client,
-                              GNUNET_OK);
+  env = GNUNET_MQ_msg (qrm,
+                      GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE);
+  qrm->is_valid = htonl ((GNUNET_YES == res) ? GNUNET_NO : GNUNET_YES);
+  GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
+                 env);
+  GNUNET_SERVICE_client_continue (client);
 }
 
 
@@ -293,6 +278,10 @@ do_flood (void *cls,
   struct GNUNET_MQ_Envelope *e;
   struct RevokeMessage *cp;
 
+  if (NULL == pe->mq)
+    return GNUNET_OK; /* peer connected to us via SET,
+                        but we have no direct CORE
+                        connection for flooding */
   e = GNUNET_MQ_msg (cp,
                      GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE);
   *cp = *rm;
@@ -364,7 +353,7 @@ publicize_rm (const struct RevokeMessage *rm)
                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
   /* add to set for future connections */
   e.size = htons (rm->header.size);
-  e.element_type = 0;
+  e.element_type = GNUNET_BLOCK_TYPE_REVOCATION;
   e.data = rm;
   if (GNUNET_OK !=
       GNUNET_SET_add_element (revocation_set,
@@ -391,40 +380,32 @@ publicize_rm (const struct RevokeMessage *rm)
 /**
  * Handle REVOKE message from client.
  *
- * @param cls unused
- * @param client who sent the message
- * @param message the message received
+ * @param cls client who sent the message
+ * @param rm the message received
  */
 static void
 handle_revoke_message (void *cls,
-                       struct GNUNET_SERVER_Client *client,
-                       const struct GNUNET_MessageHeader *message)
+                       const struct RevokeMessage *rm)
 {
-  const struct RevokeMessage *rm;
-  struct RevocationResponseMessage rrm;
+  struct GNUNET_SERVICE_Client *client = cls;
+  struct GNUNET_MQ_Envelope *env;
+  struct RevocationResponseMessage *rrm;
   int ret;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received REVOKE message from client\n");
-  rm = (const struct RevokeMessage *) message;
   if (GNUNET_SYSERR == (ret = publicize_rm (rm)))
   {
     GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client,
-                                GNUNET_SYSERR);
+    GNUNET_SERVICE_client_drop (client);
     return;
   }
-  rrm.header.size = htons (sizeof (struct RevocationResponseMessage));
-  rrm.header.type = htons (GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE);
-  rrm.is_valid = htonl ((GNUNET_OK == ret) ? GNUNET_NO : GNUNET_YES);
-  GNUNET_SERVER_notification_context_add (nc,
-                                          client);
-  GNUNET_SERVER_notification_context_unicast (nc,
-                                              client,
-                                              &rrm.header,
-                                              GNUNET_NO);
-  GNUNET_SERVER_receive_done (client,
-                              GNUNET_OK);
+  env = GNUNET_MQ_msg (rrm,
+                      GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE);
+  rrm->is_valid = htonl ((GNUNET_OK == ret) ? GNUNET_NO : GNUNET_YES);
+  GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
+                 env);
+  GNUNET_SERVICE_client_continue (client);
 }
 
 
@@ -432,21 +413,16 @@ handle_revoke_message (void *cls,
  * Core handler for flooded revocation messages.
  *
  * @param cls closure unused
- * @param message message
- * @param peer peer identity this message is from (ignored)
+ * @param rm revocation message
  */
-static int
-handle_p2p_revoke_message (void *cls,
-                          const struct GNUNET_PeerIdentity *peer,
-                          const struct GNUNET_MessageHeader *message)
+static void
+handle_p2p_revoke (void *cls,
+                  const struct RevokeMessage *rm)
 {
-  const struct RevokeMessage *rm;
-
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Received REVOKE message from peer\n");
-  rm = (const struct RevokeMessage *) message;
-  GNUNET_break_op (GNUNET_SYSERR != publicize_rm (rm));
-  return GNUNET_OK;
+             "Received REVOKE message\n");
+  GNUNET_break_op (GNUNET_SYSERR !=
+                  publicize_rm (rm));
 }
 
 
@@ -457,11 +433,13 @@ handle_p2p_revoke_message (void *cls,
  *
  * @param cls closure
  * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
+ * @param current_size current set size
  * @param status see `enum GNUNET_SET_Status`
  */
 static void
 add_revocation (void *cls,
                 const struct GNUNET_SET_Element *element,
+                uint64_t current_size,
                 enum GNUNET_SET_Status status)
 {
   struct PeerEntry *peer_entry = cls;
@@ -475,17 +453,17 @@ add_revocation (void *cls,
       GNUNET_break_op (0);
       return;
     }
-    if (0 != element->element_type)
+    if (GNUNET_BLOCK_TYPE_REVOCATION != element->element_type)
     {
       GNUNET_STATISTICS_update (stats,
                                 gettext_noop ("# unsupported revocations received via set union"),
-                                1, GNUNET_NO);
+                                1,
+                                GNUNET_NO);
       return;
     }
     rm = element->data;
-    (void) handle_p2p_revoke_message (NULL,
-                                      &peer_entry->id,
-                                      &rm->header);
+    (void) handle_p2p_revoke (NULL,
+                             rm);
     GNUNET_STATISTICS_update (stats,
                               gettext_noop ("# revocation messages received via set union"),
                               1, GNUNET_NO);
@@ -521,11 +499,9 @@ add_revocation (void *cls,
  * run the set operation on the revocation certificates.
  *
  * @param cls NULL
- * @param tc scheduler context (unused)
  */
 static void
-transmit_task_cb (void *cls,
-                  const struct GNUNET_SCHEDULER_TaskContext *tc)
+transmit_task_cb (void *cls)
 {
   struct PeerEntry *peer_entry = cls;
 
@@ -537,6 +513,7 @@ transmit_task_cb (void *cls,
                                        &revocation_set_union_app_id,
                                        NULL,
                                        GNUNET_SET_RESULT_ADDED,
+                                       (struct GNUNET_SET_Option[]) {{ 0 }},
                                        &add_revocation,
                                        peer_entry);
   if (GNUNET_OK !=
@@ -558,9 +535,10 @@ transmit_task_cb (void *cls,
  * @param cls closure
  * @param peer peer identity this notification is about
  */
-static void
+static void *
 handle_core_connect (void *cls,
-                    const struct GNUNET_PeerIdentity *peer)
+                    const struct GNUNET_PeerIdentity *peer,
+                    struct GNUNET_MQ_Handle *mq)
 {
   struct PeerEntry *peer_entry;
   struct GNUNET_HashCode my_hash;
@@ -570,7 +548,7 @@ handle_core_connect (void *cls,
                    &my_identity,
                    sizeof (my_identity)))
   {
-    return;
+    return NULL;
   }
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -588,9 +566,11 @@ handle_core_connect (void *cls,
        and CADET+SET were faster and already produced a
        #handle_revocation_union_request() for us to deal
        with.  This should be rare, but isn't impossible. */
-    return;
+    peer_entry->mq = mq;
+    return peer_entry;
   }
-  peer_entry = new_peer_entry(peer);
+  peer_entry = new_peer_entry (peer);
+  peer_entry->mq = mq;
   GNUNET_CRYPTO_hash (&my_identity,
                       sizeof (my_identity),
                       &my_hash);
@@ -608,6 +588,7 @@ handle_core_connect (void *cls,
                                     &transmit_task_cb,
                                     peer_entry);
   }
+  return peer_entry;
 }
 
 
@@ -617,22 +598,38 @@ handle_core_connect (void *cls,
  *
  * @param cls closure
  * @param peer peer identity this notification is about
+ * @param internal_cls our `struct PeerEntry` for this peer
  */
 static void
 handle_core_disconnect (void *cls,
-                       const struct GNUNET_PeerIdentity *peer)
+                       const struct GNUNET_PeerIdentity *peer,
+                       void *internal_cls)
 {
+  struct PeerEntry *peer_entry = internal_cls;
+
   if (0 == memcmp (peer,
                    &my_identity,
                    sizeof (my_identity)))
-  {
     return;
-  }
-
+  GNUNET_assert (NULL != peer_entry);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Peer `%s' disconnected from us\n",
               GNUNET_i2s (peer));
-  delete_peer_entry(peer);
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multipeermap_remove (peers,
+                                                       peer,
+                                                       peer_entry));
+  if (NULL != peer_entry->transmit_task)
+  {
+    GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
+    peer_entry->transmit_task = NULL;
+  }
+  if (NULL != peer_entry->so)
+  {
+    GNUNET_SET_operation_cancel (peer_entry->so);
+    peer_entry->so = NULL;
+  }
+  GNUNET_free (peer_entry);
   GNUNET_STATISTICS_update (stats,
                             "# peers connected",
                             -1,
@@ -662,11 +659,9 @@ free_entry (void *cls,
  * Task run during shutdown.
  *
  * @param cls unused
- * @param tc unused
  */
 static void
-shutdown_task (void *cls,
-              const struct GNUNET_SCHEDULER_TaskContext *tc)
+shutdown_task (void *cls)
 {
   if (NULL != revocation_set)
   {
@@ -693,11 +688,6 @@ shutdown_task (void *cls,
     GNUNET_CONTAINER_multipeermap_destroy (peers);
     peers = NULL;
   }
-  if (NULL != nc)
-  {
-    GNUNET_SERVER_notification_context_destroy (nc);
-    nc = NULL;
-  }
   if (NULL != revocation_db)
   {
     GNUNET_DISK_file_close (revocation_db);
@@ -766,10 +756,11 @@ handle_revocation_union_request (void *cls,
                                                   other_peer);
   if (NULL == peer_entry)
   {
-    peer_entry = new_peer_entry(other_peer);
+    peer_entry = new_peer_entry (other_peer);
   }
   peer_entry->so = GNUNET_SET_accept (request,
                                       GNUNET_SET_RESULT_ADDED,
+                                      (struct GNUNET_SET_Option[]) {{ 0 }},
                                       &add_revocation,
                                       peer_entry);
   if (GNUNET_OK !=
@@ -793,26 +784,24 @@ handle_revocation_union_request (void *cls,
  */
 static void
 run (void *cls,
-     struct GNUNET_SERVER_Handle *server,
-     const struct GNUNET_CONFIGURATION_Handle *c)
+     const struct GNUNET_CONFIGURATION_Handle *c,
+     struct GNUNET_SERVICE_Handle *service)
 {
-  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
-    {&handle_query_message, NULL, GNUNET_MESSAGE_TYPE_REVOCATION_QUERY,
-     sizeof (struct QueryMessage)},
-    {&handle_revoke_message, NULL, GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
-     sizeof (struct RevokeMessage)},
-    {NULL, NULL, 0, 0}
-  };
-  static const struct GNUNET_CORE_MessageHandler core_handlers[] = {
-    {&handle_p2p_revoke_message, GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
-     sizeof (struct RevokeMessage)},
-    {NULL, 0, 0}
+  struct GNUNET_MQ_MessageHandler core_handlers[] = {
+    GNUNET_MQ_hd_fixed_size (p2p_revoke,
+                             GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
+                             struct RevokeMessage,
+                             NULL),
+    GNUNET_MQ_handler_end ()
   };
   char *fn;
   uint64_t left;
   struct RevokeMessage *rm;
   struct GNUNET_HashCode hc;
 
+  GNUNET_CRYPTO_hash ("revocation-set-union-application-id",
+                      strlen ("revocation-set-union-application-id"),
+                      &revocation_set_union_app_id);
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_filename (c,
                                                "REVOCATION",
@@ -826,11 +815,12 @@ run (void *cls,
     return;
   }
   cfg = c;
-  srv = server;
-  revocation_map = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO);
-  nc = GNUNET_SERVER_notification_context_create (server, 1);
+  revocation_map = GNUNET_CONTAINER_multihashmap_create (16,
+                                                        GNUNET_NO);
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (cfg, "REVOCATION", "WORKBITS",
+      GNUNET_CONFIGURATION_get_value_number (cfg,
+                                            "REVOCATION",
+                                            "WORKBITS",
                                             &revocation_work_required))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
@@ -905,69 +895,62 @@ run (void *cls,
   }
   GNUNET_free (fn);
 
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
-                                &shutdown_task,
-                                NULL);
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+                                NULL);
   peers = GNUNET_CONTAINER_multipeermap_create (128,
                                                 GNUNET_YES);
-  GNUNET_SERVER_add_handlers (srv, handlers);
-   /* Connect to core service and register core handlers */
+  /* Connect to core service and register core handlers */
   core_api = GNUNET_CORE_connect (cfg,   /* Main configuration */
-                                 NULL,       /* Closure passed to functions */
-                                 &core_init,    /* Call core_init once connected */
-                                 &handle_core_connect,  /* Handle connects */
-                                 &handle_core_disconnect,       /* Handle disconnects */
-                                 NULL,  /* Don't want notified about all incoming messages */
-                                 GNUNET_NO,     /* For header only inbound notification */
-                                 NULL,  /* Don't want notified about all outbound messages */
-                                 GNUNET_NO,     /* For header only outbound notification */
-                                 core_handlers);        /* Register these handlers */
+                                 NULL,       /* Closure passed to functions */
+                                 &core_init,    /* Call core_init once connected */
+                                 &handle_core_connect,  /* Handle connects */
+                                 &handle_core_disconnect,       /* Handle disconnects */
+                                 core_handlers);        /* Register these handlers */
   if (NULL == core_api)
   {
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-  stats = GNUNET_STATISTICS_create ("revocation", cfg);
+  stats = GNUNET_STATISTICS_create ("revocation",
+                                   cfg);
 }
 
 
 /**
- * The main function for the network size estimation service.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
+ * Define "main" method using service macro.
  */
-int
-main (int argc,
-      char *const *argv)
-{
-  GNUNET_CRYPTO_hash ("revocation-set-union-application-id",
-                      strlen ("revocation-set-union-application-id"),
-                      &revocation_set_union_app_id);
-  return (GNUNET_OK ==
-          GNUNET_SERVICE_run (argc,
-                              argv,
-                              "revocation",
-                              GNUNET_SERVICE_OPTION_NONE,
-                              &run, NULL)) ? 0 : 1;
-}
+GNUNET_SERVICE_MAIN
+("revocation",
+ GNUNET_SERVICE_OPTION_NONE,
+ &run,
+ &client_connect_cb,
+ &client_disconnect_cb,
+ NULL,
+ GNUNET_MQ_hd_fixed_size (query_message,
+                         GNUNET_MESSAGE_TYPE_REVOCATION_QUERY,
+                         struct QueryMessage,
+                         NULL),
+ GNUNET_MQ_hd_fixed_size (revoke_message,
+                         GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
+                         struct RevokeMessage,
+                         NULL),
+ GNUNET_MQ_handler_end ());
 
 
 #if defined(LINUX) && defined(__GLIBC__)
 #include <malloc.h>
 
-
 /**
  * MINIMIZE heap size (way below 128k) since this process doesn't need much.
  */
 void __attribute__ ((constructor))
-GNUNET_ARM_memory_init ()
+GNUNET_REVOCATION_memory_init ()
 {
   mallopt (M_TRIM_THRESHOLD, 4 * 1024);
   mallopt (M_TOP_PAD, 1 * 1024);
   malloc_trim (0);
 }
+
 #endif