- typo
[oweals/gnunet.git] / src / multicast / multicast_api.c
index b49d210323dbfa290adbe352f55944c7a0cc316e..31a02b96d67ea9e2805ae224b448a11808dd99b4 100644 (file)
      Boston, MA 02111-1307, USA.
 */
 
-/** 
+/**
  * @file multicast/multicast_api.c
  * @brief multicast service; establish tunnels to distant peers
  * @author Christian Grothoff
  * @author Gabor X Toth
  */
 #include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_signatures.h"
 #include "gnunet_multicast_service.h"
+#include "multicast.h"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "multicast-api",__VA_ARGS__)
+
 
 /** 
- * Opaque handle for a multicast group member.
+ * Handle for a request to send a message to all multicast group members
+ * (from the origin).
  */
-struct GNUNET_MULTICAST_Member
+struct GNUNET_MULTICAST_OriginMessageHandle
 {
+  GNUNET_MULTICAST_OriginTransmitNotify notify;
+  void *notify_cls;
+  struct GNUNET_MULTICAST_Origin *origin;
+
+  uint64_t message_id;
+  uint64_t group_generation;
+  uint64_t fragment_offset;
 };
 
 
-/** 
+/**
  * Handle for the origin of a multicast group.
  */
 struct GNUNET_MULTICAST_Origin
+{
+  struct GNUNET_CRYPTO_EddsaPrivateKey priv_key;
+  struct GNUNET_MULTICAST_OriginMessageHandle msg_handle;
+
+  GNUNET_MULTICAST_JoinCallback join_cb;
+  GNUNET_MULTICAST_MembershipTestCallback mem_test_cb;
+  GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb;
+  GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb;
+  GNUNET_MULTICAST_RequestCallback request_cb;
+  GNUNET_MULTICAST_MessageCallback message_cb;
+  void *cls;
+
+  uint64_t next_fragment_id;
+};
+
+
+/**
+ * Handle for a message to be delivered from a member to the origin.
+ */
+struct GNUNET_MULTICAST_MemberRequestHandle
+{
+};
+
+
+/**
+ * Opaque handle for a multicast group member.
+ */
+struct GNUNET_MULTICAST_Member
 {
 };
 
 
 GNUNET_NETWORK_STRUCT_BEGIN
 
-/** 
+/**
  * Header of a request from a member to the origin.
  */
 struct GNUNET_MULTICAST_RequestHeader
 {
-  /** 
+  /**
    * Header for all requests from a member to the origin.
    */
   struct GNUNET_MessageHeader header;
@@ -58,31 +100,31 @@ struct GNUNET_MULTICAST_RequestHeader
   /**
    * Public key of the sending member.
    */
-  struct GNUNET_CRYPTO_EccPublicSignKey member_key;
+  struct GNUNET_CRYPTO_EddsaPublicKey member_key;
 
-  /** 
+  /**
    * ECC signature of the request fragment.
    *
    * Signature must match the public key of the multicast group.
    */
-  struct GNUNET_CRYPTO_EccSignature signature;
+  struct GNUNET_CRYPTO_EddsaSignature signature;
 
-  /** 
+  /**
    * Purpose for the signature and size of the signed data.
    */
   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
 
-  /** 
+  /**
    * Number of the request fragment, monotonically increasing.
    */
   uint64_t fragment_id GNUNET_PACKED;
 
-  /** 
+  /**
    * Byte offset of this @e fragment of the @e request.
    */
   uint64_t fragment_offset GNUNET_PACKED;
 
-  /** 
+  /**
    * Number of the request this fragment belongs to.
    *
    * Set in GNUNET_MULTICAST_origin_to_all().
@@ -97,24 +139,24 @@ struct GNUNET_MULTICAST_RequestHeader
   /* Followed by request body. */
 };
 
-/** 
+/**
  * Header of a join request sent to the origin or another member.
  */
 struct GNUNET_MULTICAST_JoinRequest
 {
-  /** 
+  /**
    * Header for the join request.
    */
   struct GNUNET_MessageHeader header;
 
-  /** 
+  /**
    * ECC signature of the rest of the fields of the join request.
    *
    * Signature must match the public key of the joining member.
    */
-  struct GNUNET_CRYPTO_EccSignature signature;
+  struct GNUNET_CRYPTO_EddsaSignature signature;
 
-  /** 
+  /**
    * Purpose for the signature and size of the signed data.
    */
   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
@@ -122,12 +164,12 @@ struct GNUNET_MULTICAST_JoinRequest
   /**
    * Public key of the target group.
    */
-  struct GNUNET_CRYPTO_EccPublicSignKey group_key;
+  struct GNUNET_CRYPTO_EddsaPublicKey group_key;
 
   /**
    * Public key of the joining member.
    */
-  struct GNUNET_CRYPTO_EccPublicSignKey member_key;
+  struct GNUNET_CRYPTO_EddsaPublicKey member_key;
 
   /**
    * Peer identity of the joining member.
@@ -140,7 +182,7 @@ struct GNUNET_MULTICAST_JoinRequest
 GNUNET_NETWORK_STRUCT_END
 
 
-/** 
+/**
  * Handle that identifies a join request.
  *
  * Used to match calls to #GNUNET_MULTICAST_JoinCallback to the
@@ -151,7 +193,7 @@ struct GNUNET_MULTICAST_JoinHandle
 };
 
 
-/** 
+/**
  * Function to call with the decision made for a join request.
  *
  * Must be called once and only once in response to an invocation of the
@@ -184,7 +226,7 @@ GNUNET_MULTICAST_join_decision (struct GNUNET_MULTICAST_JoinHandle *jh,
 }
 
 
-/** 
+/**
  * Handle to pass back for the answer of a membership test.
  */
 struct GNUNET_MULTICAST_MembershipTestHandle
@@ -192,7 +234,7 @@ struct GNUNET_MULTICAST_MembershipTestHandle
 };
 
 
-/** 
+/**
  * Call informing multicast about the decision taken for a membership test.
  *
  * @param mth Handle that was given for the query.
@@ -206,7 +248,7 @@ GNUNET_MULTICAST_membership_test_result (struct GNUNET_MULTICAST_MembershipTestH
 }
 
 
-/** 
+/**
  * Opaque handle to a replay request from the multicast service.
  */
 struct GNUNET_MULTICAST_ReplayHandle
@@ -214,7 +256,7 @@ struct GNUNET_MULTICAST_ReplayHandle
 };
 
 
-/** 
+/**
  * Replay a message fragment for the multicast group.
  *
  * @param rh Replay handle identifying which replay operation was requested.
@@ -229,7 +271,7 @@ GNUNET_MULTICAST_replay_response (struct GNUNET_MULTICAST_ReplayHandle *rh,
 }
 
 
-/** 
+/**
  * Indicate the end of the replay session.
  *
  * Invalidates the replay handle.
@@ -242,7 +284,7 @@ GNUNET_MULTICAST_replay_response_end (struct GNUNET_MULTICAST_ReplayHandle *rh)
 }
 
 
-/** 
+/**
  * Replay a message for the multicast group.
  *
  * @param rh Replay handle identifying which replay operation was requested.
@@ -257,7 +299,7 @@ GNUNET_MULTICAST_replay_response2 (struct GNUNET_MULTICAST_ReplayHandle *rh,
 }
 
 
-/** 
+/**
  * Start a multicast group.
  *
  * Will advertise the origin in the P2P overlay network under the respective
@@ -272,10 +314,10 @@ GNUNET_MULTICAST_replay_response2 (struct GNUNET_MULTICAST_ReplayHandle *rh,
  * @param cfg Configuration to use.
  * @param priv_key ECC key that will be used to sign messages for this
  *        multicast session; public key is used to identify the multicast group;
- * @param last_fragment_id Last fragment ID to continue counting fragments from
+ * @param next_fragment_id Next fragment ID to continue counting fragments from
  *        when restarting the origin.  0 for a new group.
  * @param join_cb Function called to approve / disapprove joining of a peer.
- * @param test_cb Function multicast can use to test group membership.
+ * @param mem_test_cb Function multicast can use to test group membership.
  * @param replay_frag_cb Function that can be called to replay a message fragment.
  * @param replay_msg_cb Function that can be called to replay a message.
  * @param request_cb Function called with message fragments from group members.
@@ -287,30 +329,91 @@ GNUNET_MULTICAST_replay_response2 (struct GNUNET_MULTICAST_ReplayHandle *rh,
  */
 struct GNUNET_MULTICAST_Origin *
 GNUNET_MULTICAST_origin_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                               const struct GNUNET_CRYPTO_EccPrivateKey *priv_key,
-                               uint64_t last_fragment_id,
+                               const struct GNUNET_CRYPTO_EddsaPrivateKey *priv_key,
+                               uint64_t next_fragment_id,
                                GNUNET_MULTICAST_JoinCallback join_cb,
-                               GNUNET_MULTICAST_MembershipTestCallback test_cb,
+                               GNUNET_MULTICAST_MembershipTestCallback mem_test_cb,
                                GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb,
                                GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb,
                                GNUNET_MULTICAST_RequestCallback request_cb,
                                GNUNET_MULTICAST_MessageCallback message_cb,
                                void *cls)
 {
-  return NULL;
+  struct GNUNET_MULTICAST_Origin *orig = GNUNET_malloc (sizeof (*orig));
+  orig->priv_key = *priv_key;
+  orig->next_fragment_id = next_fragment_id;
+  orig->join_cb = join_cb;
+  orig->mem_test_cb = mem_test_cb;
+  orig->replay_frag_cb = replay_frag_cb;
+  orig->replay_msg_cb = replay_msg_cb;
+  orig->request_cb = request_cb;
+  orig->message_cb = message_cb;
+  orig->cls = cls;
+  return orig;
 }
 
 
-/** 
- * Handle for a request to send a message to all multicast group members
- * (from the origin).
- */
-struct GNUNET_MULTICAST_OriginMessageHandle
+/* FIXME: for now just send back to the client what it sent. */
+static void
+schedule_origin_to_all (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-};
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "schedule_origin_to_all()\n");
+  struct GNUNET_MULTICAST_Origin *orig = cls;
+  struct GNUNET_MULTICAST_OriginMessageHandle *mh = &orig->msg_handle;
+
+  size_t buf_size = GNUNET_MULTICAST_FRAGMENT_MAX_SIZE;
+  struct GNUNET_MULTICAST_MessageHeader *msg
+    = GNUNET_malloc (sizeof (*msg) + buf_size);
+  int ret = mh->notify (mh->notify_cls, &buf_size, &msg[1]);
+
+  if (! (GNUNET_YES == ret || GNUNET_NO == ret)
+      || buf_size > GNUNET_MULTICAST_FRAGMENT_MAX_SIZE)
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "MasterTransmitNotify() returned error or invalid message size.\n");
+    /* FIXME: handle error */
+    return;
+  }
+
+  if (GNUNET_NO == ret && 0 == buf_size)
+    return; /* Transmission paused. */
+
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE);
+  msg->header.size = htons (buf_size);
+  msg->message_id = mh->message_id;
+  msg->group_generation = mh->group_generation;
+
+  /* FIXME: add fragment ID and signature in the service */
+  msg->fragment_id = orig->next_fragment_id++;
+  msg->fragment_offset = mh->fragment_offset;
+  mh->fragment_offset += buf_size;
+  msg->purpose.size = htonl (buf_size
+                             - sizeof (msg->header)
+                             - sizeof (msg->hop_counter)
+                             - sizeof (msg->signature));
+  msg->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE);
+
+  if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &msg->purpose,
+                                           &msg->signature))
+  {
+    /* FIXME: handle error */
+    return;
+  }
+
+  /* FIXME: send msg to the service and only then call message_cb with the
+   *        returned signed message.
+   * FIXME: Also send to local members in this group.
+   */
+  orig->message_cb (orig->cls, (const struct GNUNET_MessageHeader *) msg);
 
+  if (GNUNET_NO == ret)
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_SECONDS, 1),
+                                  schedule_origin_to_all, orig);
 
-/** 
+}
+
+/**
  * Send a message to the multicast group.
  *
  * @param origin Handle to the multicast group.
@@ -328,11 +431,21 @@ GNUNET_MULTICAST_origin_to_all (struct GNUNET_MULTICAST_Origin *origin,
                                 GNUNET_MULTICAST_OriginTransmitNotify notify,
                                 void *notify_cls)
 {
-  return NULL;
+  struct GNUNET_MULTICAST_OriginMessageHandle *mh = &origin->msg_handle;
+  mh->origin = origin;
+  mh->message_id = message_id;
+  mh->group_generation = group_generation;
+  mh->notify = notify;
+  mh->notify_cls = notify_cls;
+
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                (GNUNET_TIME_UNIT_SECONDS, 1),
+                                schedule_origin_to_all, origin);
+  return &origin->msg_handle;
 }
 
 
-/** 
+/**
  * Resume message transmission to multicast group.
  *
  * @param mh Request to cancel.
@@ -340,11 +453,11 @@ GNUNET_MULTICAST_origin_to_all (struct GNUNET_MULTICAST_Origin *origin,
 void
 GNUNET_MULTICAST_origin_to_all_resume (struct GNUNET_MULTICAST_OriginMessageHandle *mh)
 {
-
+  GNUNET_SCHEDULER_add_now (schedule_origin_to_all, mh->origin);
 }
 
 
-/** 
+/**
  * Cancel request for message transmission to multicast group.
  *
  * @param mh Request to cancel.
@@ -355,7 +468,7 @@ GNUNET_MULTICAST_origin_to_all_cancel (struct GNUNET_MULTICAST_OriginMessageHand
 }
 
 
-/** 
+/**
  * Stop a multicast group.
  *
  * @param origin Multicast group to stop.
@@ -363,10 +476,11 @@ GNUNET_MULTICAST_origin_to_all_cancel (struct GNUNET_MULTICAST_OriginMessageHand
 void
 GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *origin)
 {
+  GNUNET_free (origin);
 }
 
 
-/** 
+/**
  * Join a multicast group.
  *
  * The entity joining is always the local peer.  Further information about the
@@ -409,8 +523,8 @@ GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *origin)
  */
 struct GNUNET_MULTICAST_Member *
 GNUNET_MULTICAST_member_join (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                              const struct GNUNET_CRYPTO_EccPublicSignKey *group_key,
-                              const struct GNUNET_CRYPTO_EccPrivateKey *member_key,
+                              const struct GNUNET_CRYPTO_EddsaPublicKey *group_key,
+                              const struct GNUNET_CRYPTO_EddsaPrivateKey *member_key,
                               const struct GNUNET_PeerIdentity *origin,
                               uint32_t relay_count,
                               const struct GNUNET_PeerIdentity *relays,
@@ -422,11 +536,13 @@ GNUNET_MULTICAST_member_join (const struct GNUNET_CONFIGURATION_Handle *cfg,
                               GNUNET_MULTICAST_MessageCallback message_cb,
                               void *cls)
 {
-  return NULL;
+  struct GNUNET_MULTICAST_Member *mem = GNUNET_malloc (sizeof (*mem));
+
+  return mem;
 }
 
 
-/** 
+/**
  * Handle for a replay request.
  */
 struct GNUNET_MULTICAST_MemberReplayHandle
@@ -434,7 +550,7 @@ struct GNUNET_MULTICAST_MemberReplayHandle
 };
 
 
-/** 
+/**
  * Request a fragment to be replayed by fragment ID.
  *
  * Useful if messages below the @e max_known_fragment_id given when joining are
@@ -457,7 +573,7 @@ GNUNET_MULTICAST_member_replay_fragment (struct GNUNET_MULTICAST_Member *member,
 }
 
 
-/** 
+/**
  * Request a message fragment to be replayed.
  *
  * Useful if messages below the @e max_known_fragment_id given when joining are
@@ -484,7 +600,7 @@ GNUNET_MULTICAST_member_replay_message (struct GNUNET_MULTICAST_Member *member,
 }
 
 
-/** 
+/**
  * Cancel a replay request.
  *
  * @param rh Request to cancel.
@@ -495,7 +611,7 @@ GNUNET_MULTICAST_member_replay_cancel (struct GNUNET_MULTICAST_MemberReplayHandl
 }
 
 
-/** 
+/**
  * Part a multicast group.
  *
  * Disconnects from all group members and invalidates the @a member handle.
@@ -508,20 +624,13 @@ GNUNET_MULTICAST_member_replay_cancel (struct GNUNET_MULTICAST_MemberReplayHandl
 void
 GNUNET_MULTICAST_member_part (struct GNUNET_MULTICAST_Member *member)
 {
+  GNUNET_free (member);
 }
 
 
-/** 
- * Handle for a message to be delivered from a member to the origin.
- */
-struct GNUNET_MULTICAST_MemberRequestHandle
-{
-};
-
-
-/** 
+/**
  * Send a message to the origin of the multicast group.
- * 
+ *
  * @param member Membership handle.
  * @param message_id Application layer ID for the message.  Opaque to multicast.
  * @param notify Callback to call to get the message.
@@ -538,7 +647,7 @@ GNUNET_MULTICAST_member_to_origin (struct GNUNET_MULTICAST_Member *member,
 }
 
 
-/** 
+/**
  * Resume message transmission to origin.
  *
  * @param rh Request to cancel.
@@ -550,7 +659,7 @@ GNUNET_MULTICAST_member_to_origin_resume (struct GNUNET_MULTICAST_MemberRequestH
 }
 
 
-/** 
+/**
  * Cancel request for message transmission to origin.
  *
  * @param rh Request to cancel.