gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r33354 - in gnunet/src: include multicast psyc


From: gnunet
Subject: [GNUnet-SVN] r33354 - in gnunet/src: include multicast psyc
Date: Fri, 23 May 2014 01:05:28 +0200

Author: tg
Date: 2014-05-23 01:05:27 +0200 (Fri, 23 May 2014)
New Revision: 33354

Added:
   gnunet/src/multicast/test_multicast.c
Removed:
   gnunet/src/multicast/test_multicast_api.c
Modified:
   gnunet/src/include/gnunet_multicast_service.h
   gnunet/src/include/gnunet_protocols.h
   gnunet/src/include/gnunet_psyc_service.h
   gnunet/src/multicast/Makefile.am
   gnunet/src/multicast/gnunet-service-multicast.c
   gnunet/src/multicast/multicast.h
   gnunet/src/multicast/multicast_api.c
   gnunet/src/psyc/gnunet-service-psyc.c
   gnunet/src/psyc/psyc.h
   gnunet/src/psyc/psyc_api.c
   gnunet/src/psyc/psyc_common.c
   gnunet/src/psyc/test_psyc.c
Log:
psyc, multicast: join decision

Modified: gnunet/src/include/gnunet_multicast_service.h
===================================================================
--- gnunet/src/include/gnunet_multicast_service.h       2014-05-22 09:29:38 UTC 
(rev 33353)
+++ gnunet/src/include/gnunet_multicast_service.h       2014-05-22 23:05:27 UTC 
(rev 33354)
@@ -253,7 +253,7 @@
  *        be the multicast origin) is a good candidate for building the
  *        multicast tree.  Note that it is unnecessary to specify our own
  *        peer identity in this array.
- * @param join_response Message to send in response to the joining peer;
+ * @param join_resp  Message to send in response to the joining peer;
  *        can also be used to redirect the peer to a different group at the
  *        application layer; this response is to be transmitted to the
  *        peer that issued the request even if admission is denied.
@@ -263,7 +263,7 @@
                                 int is_admitted,
                                 unsigned int relay_count,
                                 const struct GNUNET_PeerIdentity *relays,
-                                const struct GNUNET_MessageHeader 
*join_response);
+                                const struct GNUNET_MessageHeader *join_resp);
 
 
 /**
@@ -272,18 +272,16 @@
  * Implementations of this function must call GNUNET_MULTICAST_join_decision()
  * with the decision.
  *
- * @param cls Closure.
- * @param peer Identity of the member that wants to join.
- * @param join_req Application-dependent join message from the new member
- *        (might, for example, contain a user,
- *        bind user identity/pseudonym to peer identity, application-level
- *        message to origin, etc.).
- * @param jh Join handle to pass to GNUNET_MULTICAST_join_decison().
+ * @param cls  Closure.
+ * @param peer  Identity of the member that wants to join.
+ * @param member_key  Requesting member's public key.
+ * @param join_msg  Application-dependent join message from the new member.
+ * @param jh  Join handle to pass to GNUNET_MULTICAST_join_decison().
  */
 typedef void
 (*GNUNET_MULTICAST_JoinCallback) (void *cls,
                                   const struct GNUNET_CRYPTO_EddsaPublicKey 
*member_key,
-                                  const struct GNUNET_MessageHeader *join_req,
+                                  const struct GNUNET_MessageHeader *join_msg,
                                   struct GNUNET_MULTICAST_JoinHandle *jh);
 
 
@@ -652,7 +650,7 @@
  * Join a multicast group.
  *
  * The entity joining is always the local peer.  Further information about the
- * candidate can be provided in the @a join_request message.  If the join 
fails, the
+ * candidate can be provided in @a join_msg.  If the join fails, the
  * @a message_cb is invoked with a (failure) response and then with NULL.  If
  * the join succeeds, outstanding (state) messages and ongoing multicast
  * messages will be given to the @a message_cb until the member decides to part
@@ -671,10 +669,8 @@
  * @param relays Peer identities of members of the group, which serve as relays
  *        and can be used to join the group at. and send the @a join_request 
to.
  *        If empty, the @a join_request is sent directly to the @a origin.
- * @param join_request  Application-dependent join request to be passed to the 
peer
- *        @a relay (might, for example, contain a user, bind user
- *        identity/pseudonym to peer identity, application-level message to
- *        origin, etc.).
+ * @param join_msg  Application-dependent join message to be passed to the
+ *        @a origin.
  * @param join_cb Function called to approve / disapprove joining of a peer.
  * @param mem_test_cb Function multicast can use to test group membership.
  * @param replay_frag_cb Function that can be called to replay message 
fragments

Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h       2014-05-22 09:29:38 UTC (rev 
33353)
+++ gnunet/src/include/gnunet_protocols.h       2014-05-22 23:05:27 UTC (rev 
33354)
@@ -2398,8 +2398,18 @@
  */
 #define GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST_CANCEL 760
 
+/**
+ * S->C: Membership test request.
+ */
+#define GNUNET_MESSAGE_TYPE_MULTICAST_MEMBERSHIP_TEST 761
 
+/**
+ * C->S: Membership test result.
+ */
+#define GNUNET_MESSAGE_TYPE_MULTICAST_MEMBERSHIP_TEST_RESULT 762
 
+
+
 
/*******************************************************************************
  * SECRETSHARING message types
  
******************************************************************************/

Modified: gnunet/src/include/gnunet_psyc_service.h
===================================================================
--- gnunet/src/include/gnunet_psyc_service.h    2014-05-22 09:29:38 UTC (rev 
33353)
+++ gnunet/src/include/gnunet_psyc_service.h    2014-05-22 23:05:27 UTC (rev 
33354)
@@ -327,23 +327,14 @@
  *
  * @param cls Closure.
  * @param slave  requesting to join.
- * @param method_name Method name in the join request.
- * @param variable_count Number of elements in the @a variables array.
- * @param variables Transient variables for the join request.
- * @param data Data stream given to the method (might not be zero-terminated
- *             if data is binary).
- * @param data_size Number of bytes in @a data.
+ * @param join_msg  Join message sent along with the request.
  * @param jh Join handle to use with GNUNET_PSYC_join_decision()
  */
 typedef void
 (*GNUNET_PSYC_JoinCallback) (void *cls,
                              const struct GNUNET_CRYPTO_EddsaPublicKey
                              *slave_key,
-                             const char *method_name,
-                             size_t variable_count,
-                             const struct GNUNET_ENV_Modifier *variables,
-                             const void *data,
-                             size_t data_size,
+                             const struct GNUNET_PSYC_MessageHeader *join_msg,
                              struct GNUNET_PSYC_JoinHandle *jh);
 
 

Modified: gnunet/src/multicast/Makefile.am
===================================================================
--- gnunet/src/multicast/Makefile.am    2014-05-22 09:29:38 UTC (rev 33353)
+++ gnunet/src/multicast/Makefile.am    2014-05-22 23:05:27 UTC (rev 33354)
@@ -54,15 +54,15 @@
 
 
 check_PROGRAMS = \
- test_multicast_api
+ test_multicast
 
 if ENABLE_TEST_RUN
 AM_TESTS_ENVIRONMENT=export 
GNUNET_PREFIX=$${GNUNET_PREFIX:address@hidden@};export 
PATH=$${GNUNET_PREFIX:address@hidden@}/bin:$$PATH;
 TESTS = $(check_PROGRAMS)
 endif
 
-test_multicast_api_SOURCES = \
- test_multicast_api.c
-test_multicast_api_LDADD = \
+test_multicast_SOURCES = \
+ test_multicast.c
+test_multicast_LDADD = \
   $(top_builddir)/src/util/libgnunetutil.la
 

Modified: gnunet/src/multicast/gnunet-service-multicast.c
===================================================================
--- gnunet/src/multicast/gnunet-service-multicast.c     2014-05-22 09:29:38 UTC 
(rev 33353)
+++ gnunet/src/multicast/gnunet-service-multicast.c     2014-05-22 23:05:27 UTC 
(rev 33354)
@@ -147,7 +147,7 @@
   /**
    * Join request sent to the origin / members.
    */
-  struct GNUNET_MULTICAST_JoinRequest *join_request;
+  struct MulticastJoinRequestMessage *join_request;
 
   /**
    * Join decision sent in reply to our request.
@@ -206,6 +206,8 @@
                                           grp_mem);
     GNUNET_CONTAINER_multihashmap_destroy (grp_mem);
   }
+  if (NULL != mem->join_decision)
+    GNUNET_free (mem->join_decision);
   GNUNET_CONTAINER_multihashmap_remove (members, &grp->pub_key_hash, mem);
 }
 
@@ -425,8 +427,8 @@
 handle_member_join (void *cls, struct GNUNET_SERVER_Client *client,
                      const struct GNUNET_MessageHeader *m)
 {
-  struct MulticastMemberJoinMessage *
-    msg = (struct MulticastMemberJoinMessage *) m;
+  const struct MulticastMemberJoinMessage *
+    msg = (const struct MulticastMemberJoinMessage *) m;
 
   struct GNUNET_CRYPTO_EddsaPublicKey mem_pub_key;
   struct GNUNET_HashCode pub_key_hash, mem_pub_key_hash;
@@ -440,17 +442,10 @@
   struct Member *mem = NULL;
   struct Group *grp;
 
-  if (NULL == grp_mem)
+  if (NULL != grp_mem)
   {
-    grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
-    GNUNET_CONTAINER_multihashmap_put (group_members, &pub_key_hash, grp_mem,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-  }
-  else
-  {
     mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &mem_pub_key_hash);
   }
-
   if (NULL == mem)
   {
     mem = GNUNET_new (struct Member);
@@ -463,7 +458,13 @@
     grp->pub_key = msg->group_key;
     grp->pub_key_hash = pub_key_hash;
 
-    GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem_pub_key_hash, mem,
+    if (NULL == grp_mem)
+    {
+      grp_mem = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
+      GNUNET_CONTAINER_multihashmap_put (group_members, &grp->pub_key_hash, 
grp_mem,
+                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+    }
+    GNUNET_CONTAINER_multihashmap_put (grp_mem, &mem->pub_key_hash, mem,
                                        
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
     GNUNET_CONTAINER_multihashmap_put (members, &grp->pub_key_hash, mem,
                                        
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
@@ -478,8 +479,11 @@
   GNUNET_CONTAINER_DLL_insert (grp->clients_head, grp->clients_tail, cl);
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "%p Client connected as member to group %s.\n",
+              "%p Client connected to group %s..\n",
               mem, GNUNET_h2s (&grp->pub_key_hash));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "%p ..as member %s.\n",
+              mem, GNUNET_h2s (&mem_pub_key_hash));
 
   GNUNET_SERVER_client_set_user_context (client, grp);
 
@@ -496,19 +500,19 @@
     struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) 
&msg[1];
     uint32_t relay_count = ntohs (msg->relay_count);
     struct GNUNET_MessageHeader *
-      join_req = ((struct GNUNET_MessageHeader *)
+      join_msg = ((struct GNUNET_MessageHeader *)
                   ((char *) &msg[1]) + relay_count * sizeof (*relays));
-    uint16_t join_req_size = ntohs (join_req->size);
+    uint16_t join_msg_size = ntohs (join_msg->size);
 
     struct MulticastJoinRequestMessage *
-      req = GNUNET_malloc (sizeof (*req) + join_req_size);
-    req->header.size = htons (sizeof (*req) + join_req_size);
+      req = GNUNET_malloc (sizeof (*req) + join_msg_size);
+    req->header.size = htons (sizeof (*req) + join_msg_size);
     req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST);
     req->group_key = grp->pub_key;
     GNUNET_CRYPTO_eddsa_key_get_public (&mem->priv_key, &req->member_key);
-    memcpy (&req[1], join_req, join_req_size);
+    memcpy (&req[1], join_msg, join_msg_size);
 
-    req->purpose.size = htonl (sizeof (*req) + join_req_size
+    req->purpose.size = htonl (sizeof (*req) + join_msg_size
                                - sizeof (req->header)
                                - sizeof (req->signature));
     req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_REQUEST);
@@ -531,7 +535,7 @@
     }
     else
     {
-      /* FIXME: send join request to remote origin / members */
+      /* FIXME: send join request to remote peers */
     }
   }
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -539,6 +543,85 @@
 
 
 /**
+ * Join decision from client.
+ */
+static void
+handle_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
+                      const struct GNUNET_MessageHeader *m)
+{
+  struct Group *
+    grp = GNUNET_SERVER_client_get_user_context (client, struct Group);
+  const struct MulticastClientJoinDecisionMessage *
+    cl_dcsn = (const struct MulticastClientJoinDecisionMessage *) m;
+
+  struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) 
&cl_dcsn[1];
+  uint32_t relay_count = ntohs (cl_dcsn->relay_count);
+
+  struct GNUNET_MessageHeader *join_msg = NULL;
+  uint16_t join_msg_size = 0;
+  if (sizeof (*cl_dcsn) + relay_count * sizeof (*relays) + sizeof (*m)
+      <= ntohs (m->size))
+  {
+    join_msg = ((struct GNUNET_MessageHeader *)
+                ((char *) &cl_dcsn[1]) + relay_count * sizeof (*relays));
+    join_msg_size = ntohs (join_msg->size);
+  }
+
+  struct MulticastJoinDecisionMessage *
+    dcsn = GNUNET_malloc (sizeof (*dcsn) + join_msg_size);
+  dcsn->header.size = htons (sizeof (*dcsn) + join_msg_size);
+  dcsn->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION);
+  dcsn->is_admitted = cl_dcsn->is_admitted;
+  memcpy (&dcsn[1], join_msg, join_msg_size);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "%p Got join decision from client for group %s..\n",
+              grp, GNUNET_h2s (&grp->pub_key_hash));
+
+  if (GNUNET_YES
+      == GNUNET_CONTAINER_multihashmap_contains (origins, &grp->pub_key_hash))
+  { /* Local origin */
+    struct GNUNET_CONTAINER_MultiHashMap *
+      grp_mem = GNUNET_CONTAINER_multihashmap_get (group_members,
+                                                   &grp->pub_key_hash);
+    if (NULL != grp_mem)
+    {
+      struct GNUNET_HashCode member_key_hash;
+      GNUNET_CRYPTO_hash (&cl_dcsn->member_key, sizeof (cl_dcsn->member_key),
+                          &member_key_hash);
+      struct Member *
+        mem = GNUNET_CONTAINER_multihashmap_get (grp_mem, &member_key_hash);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "%p ..and member %s: %p\n",
+                  grp, GNUNET_h2s (&member_key_hash), mem);
+      if (NULL != mem)
+      {
+        message_to_clients (grp, (struct GNUNET_MessageHeader *) dcsn);
+        if (GNUNET_YES == dcsn->is_admitted)
+        { /* Member admitted, store join_decision. */
+          mem->join_decision = dcsn;
+        }
+        else
+        { /* Refused entry, disconnect clients. */
+          GNUNET_free (dcsn);
+          struct ClientList *cl = mem->grp.clients_head;
+          while (NULL != cl)
+          {
+            GNUNET_SERVER_client_disconnect (cl->client);
+            cl = cl->next;
+          }
+        }
+      }
+    }
+  }
+  else
+  {
+    /* FIXME: send join decision to remote peers */
+  }
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+/**
  * Incoming message from a client.
  */
 static void
@@ -633,6 +716,9 @@
     { &handle_member_join, NULL,
       GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN, 0 },
 
+    { &handle_join_decision, NULL,
+      GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION, 0 },
+
     { &handle_multicast_message, NULL,
       GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 },
 

Modified: gnunet/src/multicast/multicast.h
===================================================================
--- gnunet/src/multicast/multicast.h    2014-05-22 09:29:38 UTC (rev 33353)
+++ gnunet/src/multicast/multicast.h    2014-05-22 23:05:27 UTC (rev 33354)
@@ -36,11 +36,16 @@
 struct MulticastJoinRequestMessage
 {
   /**
-   * Header for the join request.
+   * Type: GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST
    */
   struct GNUNET_MessageHeader header;
 
   /**
+   * Always zero.
+   */
+  uint32_t reserved;
+
+  /**
    * ECC signature of the rest of the fields of the join request.
    *
    * Signature must match the public key of the joining member.
@@ -72,31 +77,55 @@
 
 
 /**
- * Message sent from the client to the service to notify the service
- * about a join decision.
+ * Header of a join decision sent to a remote peer.
  */
 struct MulticastJoinDecisionMessage
 {
   /**
-   *
+   * Type: GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION
    */
   struct GNUNET_MessageHeader header;
 
   /**
-   * Unique ID that identifies the associated join test.
+   * #GNUNET_YES if the peer was admitted.
    */
-  uint32_t uid;
+  uint8_t is_admitted;
 
+  /* Followed by the join response message */
+};
+
+
+/**
+ * Message sent from the client to the service to notify the service
+ * about a join decision.
+ */
+struct MulticastClientJoinDecisionMessage
+{
   /**
-   * #GNUNET_YES if the peer was admitted.
+   * Type: GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION
    */
-  int32_t is_admitted;
+  struct GNUNET_MessageHeader header;
 
   /**
    * Number of relays given.
    */
   uint32_t relay_count;
 
+  /**
+   * Public key of the joining member.
+   */
+  struct GNUNET_CRYPTO_EddsaPublicKey member_key;
+
+  /**
+   * Peer identity of the joining member.
+   */
+  struct GNUNET_PeerIdentity member_peer;
+
+  /**
+   * #GNUNET_YES if the peer was admitted.
+   */
+  uint8_t is_admitted;
+
   /* Followed by relay_count peer identities */
 
   /* Followed by the join response message */
@@ -108,11 +137,11 @@
  * Message sent from the client to the service to notify the service
  * about the result of a membership test.
  */
-struct MulticastMembershipTestResponseMessage
+struct MulticastMembershipTestResultMessage
 {
 
   /**
-   *
+   * Type: GNUNET_MESSAGE_TYPE_MULTICAST_MEMBERSHIP_TEST_RESULT
    */
   struct GNUNET_MessageHeader header;
 

Modified: gnunet/src/multicast/multicast_api.c
===================================================================
--- gnunet/src/multicast/multicast_api.c        2014-05-22 09:29:38 UTC (rev 
33353)
+++ gnunet/src/multicast/multicast_api.c        2014-05-22 23:05:27 UTC (rev 
33354)
@@ -182,8 +182,6 @@
   struct GNUNET_PeerIdentity relays;
   uint32_t relay_count;
 
-  struct GNUNET_MessageHeader *join_request;
-
   uint64_t next_fragment_id;
 };
 
@@ -501,7 +499,7 @@
 
   const struct GNUNET_MessageHeader *msg = NULL;
   if (sizeof (*req) + sizeof (*msg) <= ntohs (req->header.size))
-    msg =(const struct GNUNET_MessageHeader *) &req[1];
+    msg = (const struct GNUNET_MessageHeader *) &req[1];
 
   grp->join_cb (grp->cb_cls, &req->member_key, msg, jh);
   return GNUNET_YES;
@@ -509,6 +507,25 @@
 
 
 /**
+ * Iterator callback for calling join decision callbacks of members.
+ */
+static int
+join_decision_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
+                  void *member)
+{
+  const struct MulticastJoinDecisionMessage *dcsn = cls;
+  struct GNUNET_MULTICAST_Member *mem = member;
+  struct GNUNET_MULTICAST_Group *grp = &mem->grp;
+
+  const struct GNUNET_MessageHeader *msg = NULL;
+  if (sizeof (*dcsn) + sizeof (*msg) <= ntohs (dcsn->header.size))
+    msg = (const struct GNUNET_MessageHeader *) &dcsn[1];
+
+  // FIXME: grp->join_decision_cb (grp->cb_cls, msg);
+  return GNUNET_YES;
+}
+
+/**
  * Function called when we receive a message from the service.
  *
  * @param cls  struct GNUNET_MULTICAST_Group
@@ -549,6 +566,10 @@
     size_min = sizeof (struct MulticastJoinRequestMessage);
     break;
 
+  case GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION:
+    size_min = sizeof (struct MulticastJoinDecisionMessage);
+    break;
+
   default:
     GNUNET_break_op (0);
     type = 0;
@@ -592,6 +613,15 @@
       GNUNET_CONTAINER_multihashmap_get_multiple (members, &grp->pub_key_hash,
                                                   join_request_cb, (void *) 
msg);
     break;
+
+  case GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION:
+    if (NULL != origins)
+      GNUNET_CONTAINER_multihashmap_get_multiple (origins, &grp->pub_key_hash,
+                                                  join_decision_cb, (void *) 
msg);
+    if (NULL != members)
+      GNUNET_CONTAINER_multihashmap_get_multiple (members, &grp->pub_key_hash,
+                                                  join_decision_cb, (void *) 
msg);
+    break;
   }
 
   if (NULL != grp->client)
@@ -619,7 +649,7 @@
  *        be the multicast origin) is a good candidate for building the
  *        multicast tree.  Note that it is unnecessary to specify our own
  *        peer identity in this array.
- * @param join_response Message to send in response to the joining peer;
+ * @param join_resp  Message to send in response to the joining peer;
  *        can also be used to redirect the peer to a different group at the
  *        application layer; this response is to be transmitted to the
  *        peer that issued the request even if admission is denied.
@@ -629,8 +659,29 @@
                                 int is_admitted,
                                 unsigned int relay_count,
                                 const struct GNUNET_PeerIdentity *relays,
-                                const struct GNUNET_MessageHeader 
*join_response)
+                                const struct GNUNET_MessageHeader *join_resp)
 {
+  struct GNUNET_MULTICAST_Group *grp = jh->group;
+  uint16_t join_resp_size = (NULL != join_resp) ? ntohs (join_resp->size) : 0;
+  uint16_t relay_size = relay_count * sizeof (*relays);
+  struct MulticastClientJoinDecisionMessage * dcsn;
+  struct MessageQueue *
+    mq = GNUNET_malloc (sizeof (*mq) + sizeof (*dcsn)
+                        + relay_size + join_resp_size);
+
+  dcsn = (struct MulticastClientJoinDecisionMessage *) &mq[1];
+  dcsn->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION);
+  dcsn->header.size = htons (sizeof (*dcsn) + relay_size + join_resp_size);
+  dcsn->member_key = jh->member_key;
+  dcsn->member_peer = jh->member_peer;
+  dcsn->is_admitted = is_admitted;
+  dcsn->relay_count = relay_count;
+  memcpy (&dcsn[1], relays, relay_size);
+  memcpy (((char *) &dcsn[1]) + relay_size, join_resp, join_resp_size);
+
+  GNUNET_CONTAINER_DLL_insert_tail (grp->tmit_head, grp->tmit_tail, mq);
+  transmit_next (grp);
+
   GNUNET_free (jh);
   return NULL;
 }
@@ -908,10 +959,8 @@
  * @param relays Peer identities of members of the group, which serve as relays
  *        and can be used to join the group at. and send the @a join_request 
to.
  *        If empty, the @a join_request is sent directly to the @a origin.
- * @param join_req  Application-dependent join request to be passed to the peer
- *        @a relay (might, for example, contain a user, bind user
- *        identity/pseudonym to peer identity, application-level message to
- *        origin, etc.).
+ * @param join_msg  Application-dependent join message to be passed to the peer
+ *        @a origin.
  * @param join_cb Function called to approve / disapprove joining of a peer.
  * @param member_test_cb Function multicast can use to test group membership.
  * @param replay_frag_cb Function that can be called to replay message 
fragments
@@ -933,7 +982,7 @@
                               const struct GNUNET_PeerIdentity *origin,
                               uint32_t relay_count,
                               const struct GNUNET_PeerIdentity *relays,
-                              const struct GNUNET_MessageHeader *join_req,
+                              const struct GNUNET_MessageHeader *join_msg,
                               GNUNET_MULTICAST_JoinCallback join_cb,
                               GNUNET_MULTICAST_MembershipTestCallback 
member_test_cb,
                               GNUNET_MULTICAST_ReplayFragmentCallback 
replay_frag_cb,
@@ -945,16 +994,16 @@
   struct GNUNET_MULTICAST_Group *grp = &mem->grp;
 
   uint16_t relay_size = relay_count * sizeof (*relays);
-  uint16_t join_req_size = (NULL != join_req) ? ntohs (join_req->size) : 0;
+  uint16_t join_msg_size = (NULL != join_msg) ? ntohs (join_msg->size) : 0;
   struct MulticastMemberJoinMessage *
-    join = GNUNET_malloc (sizeof (*join) + relay_size + join_req_size);
+    join = GNUNET_malloc (sizeof (*join) + relay_size + join_msg_size);
   join->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN);
-  join->header.size = htons (sizeof (*join) + relay_size + join_req_size);
+  join->header.size = htons (sizeof (*join) + relay_size + join_msg_size);
   join->group_key = *group_key;
   join->member_key = *member_key;
   join->origin = *origin;
   memcpy (&join[1], relays, relay_size);
-  memcpy (((char *) &join[1]) + relay_size, join_req, join_req_size);
+  memcpy (((char *) &join[1]) + relay_size, join_msg, join_msg_size);
 
   grp->reconnect_msg = (struct GNUNET_MessageHeader *) join;
   grp->is_origin = GNUNET_NO;

Copied: gnunet/src/multicast/test_multicast.c (from rev 33353, 
gnunet/src/multicast/test_multicast_api.c)
===================================================================
--- gnunet/src/multicast/test_multicast.c                               (rev 0)
+++ gnunet/src/multicast/test_multicast.c       2014-05-22 23:05:27 UTC (rev 
33354)
@@ -0,0 +1,44 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file multicast/test_multicast.c
+ * @brief testcase for multicast_api.c
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+
+static int
+check ()
+{
+  return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+
+  ret = check ();
+
+  return ret;
+}
+
+/* end of test_multicast.c */

Deleted: gnunet/src/multicast/test_multicast_api.c
===================================================================
--- gnunet/src/multicast/test_multicast_api.c   2014-05-22 09:29:38 UTC (rev 
33353)
+++ gnunet/src/multicast/test_multicast_api.c   2014-05-22 23:05:27 UTC (rev 
33354)
@@ -1,44 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file multicast/test_multicast_api.c
- * @brief testcase for multicast.c
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-
-static int
-check ()
-{
-  return 0;
-}
-
-int
-main (int argc, char *argv[])
-{
-  int ret;
-
-  ret = check ();
-
-  return ret;
-}
-
-/* end of test_multicast_api.c */

Modified: gnunet/src/psyc/gnunet-service-psyc.c
===================================================================
--- gnunet/src/psyc/gnunet-service-psyc.c       2014-05-22 09:29:38 UTC (rev 
33353)
+++ gnunet/src/psyc/gnunet-service-psyc.c       2014-05-22 23:05:27 UTC (rev 
33354)
@@ -194,6 +194,11 @@
   struct TransmitMessage *tmit_tail;
 
   /**
+   * Current PSYCstore operation.
+   */
+  struct GNUNET_PSYCSTORE_OperationHandle *store_op;
+
+  /**
    * Received fragments not yet sent to the client.
    * message_id -> FragmentQueue
    */
@@ -277,7 +282,7 @@
   /**
    * Channel struct common for Master and Slave
    */
-  struct Channel channel;
+  struct Channel ch;
 
   /**
    * Private key of the channel.
@@ -295,6 +300,12 @@
   struct GNUNET_MULTICAST_OriginTransmitHandle *tmit_handle;
 
   /**
+   * Incoming join requests from multicast.
+   * member_key -> struct GNUNET_MULTICAST_JoinHandle *
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *join_reqs;
+
+  /**
    * Last message ID transmitted to this channel.
    *
    * Incremented before sending a message, thus the message_id in messages sent
@@ -328,7 +339,7 @@
   /**
    * Channel struct common for Master and Slave
    */
-  struct Channel channel;
+  struct Channel ch;
 
   /**
    * Private key of the slave.
@@ -414,10 +425,11 @@
 static void
 cleanup_master (struct Master *mst)
 {
-  struct Channel *ch = &mst->channel;
+  struct Channel *ch = &mst->ch;
 
   if (NULL != mst->origin)
     GNUNET_MULTICAST_origin_stop (mst->origin);
+  GNUNET_CONTAINER_multihashmap_destroy (mst->join_reqs);
   GNUNET_CONTAINER_multihashmap_remove (masters, &ch->pub_key_hash, ch);
 }
 
@@ -428,7 +440,7 @@
 static void
 cleanup_slave (struct Slave *slv)
 {
-  struct Channel *ch = &slv->channel;
+  struct Channel *ch = &slv->ch;
   struct GNUNET_CONTAINER_MultiHashMap *
     ch_slv = GNUNET_CONTAINER_multihashmap_get (channel_slaves,
                                                 &ch->pub_key_hash);
@@ -461,6 +473,9 @@
 {
   /* FIXME: fragment_cache_clear */
 
+  if (NULL != ch->store_op)
+    GNUNET_PSYCSTORE_operation_cancel (ch->store_op);
+
   (GNUNET_YES == ch->is_master)
     ? cleanup_master ((struct Master *) ch)
     : cleanup_slave ((struct Slave *) ch);
@@ -481,8 +496,8 @@
   if (NULL == client)
     return;
 
-  struct Channel *ch
-    = GNUNET_SERVER_client_get_user_context (client, struct Channel);
+  struct Channel *
+    ch = GNUNET_SERVER_client_get_user_context (client, struct Channel);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "%p Client (%s) disconnected from channel %s\n",
               ch, (GNUNET_YES == ch->is_master) ? "master" : "slave",
@@ -545,8 +560,9 @@
 /**
  * Closure for join_mem_test_cb()
  */
-struct JoinMemTestCls
+struct JoinMemTestClosure
 {
+  struct GNUNET_CRYPTO_EddsaPublicKey slave_key;
   struct Channel *ch;
   struct GNUNET_MULTICAST_JoinHandle *jh;
   struct MasterJoinRequest *master_join_req;
@@ -559,17 +575,23 @@
 static void
 join_mem_test_cb (void *cls, int64_t result, const char *err_msg)
 {
-  struct JoinMemTestCls *jcls = cls;
+  struct JoinMemTestClosure *jcls = cls;
 
   if (GNUNET_NO == result && GNUNET_YES == jcls->ch->is_master)
   { /* Pass on join request to client if this is a master channel */
+    struct Master *mst = (struct Master *) jcls->ch;
+    struct GNUNET_HashCode slave_key_hash;
+    GNUNET_CRYPTO_hash (&jcls->slave_key, sizeof (jcls->slave_key),
+                        &slave_key_hash);
+    GNUNET_CONTAINER_multihashmap_put (mst->join_reqs, &slave_key_hash, 
jcls->jh,
+                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
     msg_to_clients (jcls->ch,
                     (struct GNUNET_MessageHeader *) jcls->master_join_req);
   }
   else
   {
-    // FIXME: relays
-    GNUNET_MULTICAST_join_decision(jcls->jh, result, 0, NULL, NULL);
+    // FIXME: add relays
+    GNUNET_MULTICAST_join_decision (jcls->jh, result, 0, NULL, NULL);
   }
   GNUNET_free (jcls->master_join_req);
   GNUNET_free (jcls);
@@ -581,20 +603,35 @@
  */
 static void
 join_cb (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key,
-         const struct GNUNET_MessageHeader *join_req,
+         const struct GNUNET_MessageHeader *join_msg,
          struct GNUNET_MULTICAST_JoinHandle *jh)
 {
   struct Channel *ch = cls;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Got join request.\n", ch);
 
-  uint16_t join_req_size = (NULL != join_req) ? ntohs (join_req->size) : 0;
-  struct MasterJoinRequest *req = GNUNET_malloc (sizeof (*req) + 
join_req_size);
-  req->header.size = htons (sizeof (*req) + join_req_size);
+  uint16_t join_msg_size = 0;
+  if (NULL != join_msg)
+  {
+    if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE == ntohs (join_msg->type))
+    {
+      join_msg_size = ntohs (join_msg->size);
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "%p Got join message with invalid type %u.\n",
+                  ch, ntohs (join_msg->type));
+    }
+  }
+
+  struct MasterJoinRequest *req = GNUNET_malloc (sizeof (*req) + 
join_msg_size);
+  req->header.size = htons (sizeof (*req) + join_msg_size);
   req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST);
   req->slave_key = *slave_key;
-  memcpy (&req[1], join_req, join_req_size);
+  memcpy (&req[1], join_msg, join_msg_size);
 
-  struct JoinMemTestCls *jcls = GNUNET_malloc (sizeof (*jcls));
+  struct JoinMemTestClosure *jcls = GNUNET_malloc (sizeof (*jcls));
+  jcls->slave_key = *slave_key;
   jcls->ch = ch;
   jcls->jh = jh;
   jcls->master_join_req = req;
@@ -1108,7 +1145,7 @@
             enum GNUNET_MULTICAST_MessageFlags flags)
 {
   struct Master *mst = cls;
-  struct Channel *ch = &mst->channel;
+  struct Channel *ch = &mst->ch;
 
   uint16_t type = ntohs (msg->type);
   uint16_t size = ntohs (msg->size);
@@ -1167,7 +1204,8 @@
                     uint64_t max_state_message_id)
 {
   struct Master *mst = cls;
-  struct Channel *ch = &mst->channel;
+  struct Channel *ch = &mst->ch;
+  ch->store_op = NULL;
 
   struct CountersResult res;
   res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MASTER_START_ACK);
@@ -1210,7 +1248,8 @@
                    uint64_t max_state_message_id)
 {
   struct Slave *slv = cls;
-  struct Channel *ch = &slv->channel;
+  struct Channel *ch = &slv->ch;
+  ch->store_op = NULL;
 
   struct CountersResult res;
   res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK);
@@ -1278,8 +1317,9 @@
     mst = GNUNET_new (struct Master);
     mst->policy = ntohl (req->policy);
     mst->priv_key = req->channel_key;
+    mst->join_reqs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
 
-    ch = &mst->channel;
+    ch = &mst->ch;
     ch->is_master = GNUNET_YES;
     ch->pub_key = pub_key;
     ch->pub_key_hash = pub_key_hash;
@@ -1287,11 +1327,12 @@
 
     GNUNET_CONTAINER_multihashmap_put (masters, &ch->pub_key_hash, ch,
                                        
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-    GNUNET_PSYCSTORE_counters_get (store, &ch->pub_key, master_counters_cb, 
mst);
+    ch->store_op = GNUNET_PSYCSTORE_counters_get (store, &ch->pub_key,
+                                                  master_counters_cb, mst);
   }
   else
   {
-    ch = &mst->channel;
+    ch = &mst->ch;
 
     struct CountersResult res;
     res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MASTER_START_ACK);
@@ -1339,17 +1380,10 @@
   struct Slave *slv = NULL;
   struct Channel *ch;
 
-  if (NULL == ch_slv)
+  if (NULL != ch_slv)
   {
-    ch_slv = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
-    GNUNET_CONTAINER_multihashmap_put (channel_slaves, &pub_key_hash, ch_slv,
-                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-  }
-  else
-  {
     slv = GNUNET_CONTAINER_multihashmap_get (ch_slv, &slv_pub_key_hash);
   }
-
   if (NULL == slv)
   {
     slv = GNUNET_new (struct Slave);
@@ -1367,21 +1401,28 @@
         memcpy (&slv->relays[i], &relays[i], sizeof (*relays));
     }
 
-    ch = &slv->channel;
+    ch = &slv->ch;
     ch->is_master = GNUNET_NO;
     ch->pub_key = req->channel_key;
     ch->pub_key_hash = pub_key_hash;
     channel_init (ch);
 
+    if (NULL == ch_slv)
+    {
+      ch_slv = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES);
+      GNUNET_CONTAINER_multihashmap_put (channel_slaves, &pub_key_hash, ch_slv,
+                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+    }
     GNUNET_CONTAINER_multihashmap_put (ch_slv, &slv_pub_key_hash, ch,
                                        
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
     GNUNET_CONTAINER_multihashmap_put (slaves, &ch->pub_key_hash, ch,
                                        
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-    GNUNET_PSYCSTORE_counters_get (store, &ch->pub_key, slave_counters_cb, 
slv);
+    ch->store_op = GNUNET_PSYCSTORE_counters_get (store, &ch->pub_key,
+                                                  slave_counters_cb, slv);
   }
   else
   {
-    ch = &slv->channel;
+    ch = &slv->ch;
 
     struct CountersResult res;
     res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK);
@@ -1402,12 +1443,63 @@
   cl->client = client;
   GNUNET_CONTAINER_DLL_insert (ch->clients_head, ch->clients_tail, cl);
 
-  GNUNET_SERVER_client_set_user_context (client, &slv->channel);
+  GNUNET_SERVER_client_set_user_context (client, &slv->ch);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }
 
 
+struct JoinDecisionClosure
+{
+  uint8_t is_admitted;
+  struct GNUNET_MessageHeader *msg;
+};
+
+
 /**
+ * Iterator callback for responding to join requests of a slave.
+ */
+static int
+join_decision_cb (void *cls, const struct GNUNET_HashCode *pub_key_hash,
+                  void *jh)
+{
+  struct JoinDecisionClosure *jcls = cls;
+  // FIXME: add relays
+  GNUNET_MULTICAST_join_decision (jh, jcls->is_admitted, 0, NULL, jcls->msg);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Join decision from client.
+ */
+static void
+handle_join_decision (void *cls, struct GNUNET_SERVER_Client *client,
+                      const struct GNUNET_MessageHeader *msg)
+{
+  struct Channel *
+    ch = GNUNET_SERVER_client_get_user_context (client, struct Channel);
+  GNUNET_assert (GNUNET_YES == ch->is_master);
+  struct Master *mst = (struct Master *) ch;
+
+  struct MasterJoinDecision *dcsn = (struct MasterJoinDecision *) msg;
+  struct JoinDecisionClosure jcls;
+  jcls.is_admitted = dcsn->is_admitted;
+  jcls.msg
+    = (sizeof (*dcsn) + sizeof (struct GNUNET_PSYC_MessageHeader)
+       <= ntohs (msg->size))
+    ? (struct GNUNET_MessageHeader *) &dcsn[1]
+    : NULL;
+
+  struct GNUNET_HashCode slave_key_hash;
+  GNUNET_CRYPTO_hash (&dcsn->slave_key, sizeof (dcsn->slave_key),
+                      &slave_key_hash);
+  GNUNET_CONTAINER_multihashmap_get_multiple (mst->join_reqs, &slave_key_hash,
+                                              &join_decision_cb, &jcls);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
  * Send acknowledgement to a client.
  *
  * Sent after a message fragment has been passed on to multicast.
@@ -1515,7 +1607,7 @@
 master_transmit_message (struct Master *mst)
 {
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p master_transmit_message()\n", mst);
-  mst->channel.tmit_task = 0;
+  mst->ch.tmit_task = 0;
   if (NULL == mst->tmit_handle)
   {
     mst->tmit_handle
@@ -1536,7 +1628,7 @@
 static void
 slave_transmit_message (struct Slave *slv)
 {
-  slv->channel.tmit_task = 0;
+  slv->ch.tmit_task = 0;
   if (NULL == slv->tmit_handle)
   {
     slv->tmit_handle
@@ -1654,8 +1746,8 @@
 handle_psyc_message (void *cls, struct GNUNET_SERVER_Client *client,
                      const struct GNUNET_MessageHeader *msg)
 {
-  struct Channel *ch
-    = GNUNET_SERVER_client_get_user_context (client, struct Channel);
+  struct Channel *
+    ch = GNUNET_SERVER_client_get_user_context (client, struct Channel);
   GNUNET_assert (NULL != ch);
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1775,6 +1867,9 @@
     { &handle_slave_join, NULL,
       GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN, 0 },
 
+    { &handle_join_decision, NULL,
+      GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION, 0 },
+
     { &handle_psyc_message, NULL,
       GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 0 },
 

Modified: gnunet/src/psyc/psyc.h
===================================================================
--- gnunet/src/psyc/psyc.h      2014-05-22 09:29:38 UTC (rev 33353)
+++ gnunet/src/psyc/psyc.h      2014-05-22 23:05:27 UTC (rev 33354)
@@ -230,8 +230,7 @@
 struct MasterJoinRequest
 {
   /**
-   * Types:
-   * - GNUNET_MESSAGE_TYPE_PSYC_MASTER_JOIN_REQUEST
+   * Type: GNUNET_MESSAGE_TYPE_PSYC_MASTER_JOIN_REQUEST
    */
   struct GNUNET_MessageHeader header;
   /**
@@ -242,6 +241,28 @@
   /* Followed by struct GNUNET_MessageHeader join_request */
 };
 
+
+struct MasterJoinDecision
+{
+  /**
+   * Type: GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Public key of the joining slave.
+   */
+  struct GNUNET_CRYPTO_EddsaPublicKey slave_key;
+
+  /**
+   * #GNUNET_YES if the slave was admitted.
+   */
+  uint8_t is_admitted;
+
+  /* Followed by struct GNUNET_MessageHeader join_response */
+};
+
+
 GNUNET_NETWORK_STRUCT_END
 
 #endif

Modified: gnunet/src/psyc/psyc_api.c
===================================================================
--- gnunet/src/psyc/psyc_api.c  2014-05-22 09:29:38 UTC (rev 33353)
+++ gnunet/src/psyc/psyc_api.c  2014-05-22 23:05:27 UTC (rev 33354)
@@ -45,6 +45,7 @@
 {
   struct MessageQueue *prev;
   struct MessageQueue *next;
+  /* Followed by struct GNUNET_MessageHeader msg */
 };
 
 
@@ -222,7 +223,8 @@
  */
 struct GNUNET_PSYC_JoinHandle
 {
-
+  struct GNUNET_PSYC_Master *mst;
+  struct GNUNET_CRYPTO_EddsaPublicKey slave_key;
 };
 
 
@@ -912,11 +914,15 @@
 handle_psyc_join_request (struct GNUNET_PSYC_Master *mst,
                           const struct MasterJoinRequest *req)
 {
-  // FIXME: extract join message from req[1]
-  const char *method_name = "_fixme";
+  struct GNUNET_PSYC_MessageHeader *msg = NULL;
+  if (ntohs (req->header.size) <= sizeof (*req) + sizeof (*msg))
+    msg = (struct GNUNET_PSYC_MessageHeader *) &req[1];
+
   struct GNUNET_PSYC_JoinHandle *jh = GNUNET_malloc (sizeof (*jh));
-  mst->join_cb (mst->ch.cb_cls, &req->slave_key, method_name,
-                0, NULL, NULL, 0, jh);
+  jh->mst = mst;
+  jh->slave_key = req->slave_key;
+
+  mst->join_cb (mst->ch.cb_cls, &req->slave_key, msg, jh);
 }
 
 
@@ -931,7 +937,6 @@
 message_handler (void *cls,
                  const struct GNUNET_MessageHeader *msg)
 {
-  // YUCK! => please have disjoint message handlers...
   struct GNUNET_PSYC_Channel *ch = cls;
   struct GNUNET_PSYC_Master *mst = cls;
   struct GNUNET_PSYC_Slave *slv = cls;
@@ -1264,7 +1269,33 @@
                            const void *data,
                            size_t data_size)
 {
+  struct GNUNET_PSYC_Channel *ch = &jh->mst->ch;
 
+  struct MasterJoinDecision *dcsn;
+  struct GNUNET_PSYC_MessageHeader *pmsg;
+  uint16_t pmsg_size = 0;
+/* FIXME:
+  sizeof (*pmsg)
+    + sizeof (struct GNUNET_PSYC_MessageMethod)
+    + vars_size
+    + sizeof (struct GNUNET_MessageHeader) + data_size
+    + sizeof (struct GNUNET_MessageHeader);
+*/
+  uint16_t relay_size = relay_count * sizeof (*relays);
+  struct MessageQueue *
+    mq = GNUNET_malloc (sizeof (*mq) + sizeof (*dcsn) + relay_size + 
pmsg_size);
+  dcsn = (struct MasterJoinDecision *) &mq[1];
+  dcsn->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION);
+  dcsn->header.size = htons (sizeof (*mq) + sizeof (*dcsn)
+                             + relay_size + pmsg_size);
+  dcsn->is_admitted = (GNUNET_YES == is_admitted) ? GNUNET_YES : GNUNET_NO;
+  dcsn->slave_key = jh->slave_key;
+
+  /* FIXME: add message parts to pmsg */
+  memcpy (&dcsn[1], pmsg, pmsg_size);
+
+  GNUNET_CONTAINER_DLL_insert_tail (ch->tmit_head, ch->tmit_tail, mq);
+  transmit_next (ch);
 }
 
 

Modified: gnunet/src/psyc/psyc_common.c
===================================================================
--- gnunet/src/psyc/psyc_common.c       2014-05-22 09:29:38 UTC (rev 33353)
+++ gnunet/src/psyc/psyc_common.c       2014-05-22 23:05:27 UTC (rev 33354)
@@ -88,7 +88,7 @@
   {
     struct GNUNET_PSYC_MessageHeader *pmsg
       = (struct GNUNET_PSYC_MessageHeader *) msg;
-    GNUNET_log (kind, "\tID: %" PRIu64 "\tflags: %" PRIu32 "\n",
+    GNUNET_log (kind, "\tID: %" PRIu64 "\tflags: %x" PRIu32 "\n",
                 GNUNET_ntohll (pmsg->message_id), ntohl (pmsg->flags));
     break;
   }

Modified: gnunet/src/psyc/test_psyc.c
===================================================================
--- gnunet/src/psyc/test_psyc.c 2014-05-22 09:29:38 UTC (rev 33353)
+++ gnunet/src/psyc/test_psyc.c 2014-05-22 23:05:27 UTC (rev 33354)
@@ -54,7 +54,6 @@
 
 static struct GNUNET_PSYC_Master *mst;
 static struct GNUNET_PSYC_Slave *slv;
-static struct GNUNET_PSYC_Channel *ch;
 
 static struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key;
 static struct GNUNET_CRYPTO_EddsaPrivateKey *slave_key;
@@ -183,7 +182,7 @@
 
   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
               "Master got message part of type %u and size %u "
-              "belonging to message ID %llu with flags %bu\n",
+              "belonging to message ID %llu with flags %xu\n",
               type, size, message_id, flags);
 
   switch (test)
@@ -192,7 +191,7 @@
     if (GNUNET_PSYC_MESSAGE_REQUEST != flags)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Unexpected request flags: %lu\n", flags);
+                  "Unexpected request flags: %x" PRIu32 "\n", flags);
       GNUNET_assert (0);
       return;
     }
@@ -227,7 +226,7 @@
 
   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
               "Slave got message part of type %u and size %u "
-              "belonging to message ID %llu with flags %bu\n",
+              "belonging to message ID %llu with flags %xu\n",
               type, size, message_id, flags);
 
   switch (test)
@@ -245,15 +244,18 @@
 
 static void
 join_request (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key,
-              const char *method_name,
-              size_t variable_count, const struct GNUNET_ENV_Modifier 
*variables,
-              const void *data, size_t data_size,
+              const struct GNUNET_PSYC_MessageHeader *msg,
               struct GNUNET_PSYC_JoinHandle *jh)
 {
+  struct GNUNET_HashCode slave_key_hash;
+  GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash);
   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "Got join request: %s (%zu vars)", method_name, variable_count);
+              "Got join request from %s.\n",
+              GNUNET_h2s (&slave_key_hash));
+
   GNUNET_PSYC_join_decision (jh, GNUNET_YES, 0, NULL, "_notice_join", NULL,
                              "you're in", 9);
+  // FIXME: also test refusing entry
 }
 
 
@@ -425,9 +427,8 @@
   GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_ASSIGN,
                               "_foo_bar", "foo bar baz", 11);
   slv = GNUNET_PSYC_slave_join (cfg, &channel_pub_key, slave_key, &origin,
-                                16, relays, &slave_message, &join_request,
-                                &slave_joined, NULL, "_request_join", env,
-                                "some data", 9);
+                                16, relays, &slave_message, &slave_joined, 
NULL,
+                                "_request_join", env, "some data", 9);
   GNUNET_ENV_environment_destroy (env);
 }
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]