+ struct GNUNET_MULTICAST_Group *grp;
+ struct GNUNET_MULTICAST_Member *mem = cls;
+ grp = &mem->grp;
+
+ if (GNUNET_YES == grp->is_disconnecting)
+ return;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got replay response.\n");
+
+ // FIXME: return result
+}
+
+
+/**
+ * Check join decision.
+ */
+static int
+check_member_join_decision (void *cls,
+ const struct MulticastJoinDecisionMessageHeader *hdcsn)
+{
+ return GNUNET_OK; // checked in handle below
+}
+
+
+/**
+ * Member receives join decision.
+ */
+static void
+handle_member_join_decision (void *cls,
+ const struct MulticastJoinDecisionMessageHeader *hdcsn)
+{
+ struct GNUNET_MULTICAST_Group *grp;
+ struct GNUNET_MULTICAST_Member *mem = cls;
+ grp = &mem->grp;
+
+ const struct MulticastJoinDecisionMessage *
+ dcsn = (const struct MulticastJoinDecisionMessage *) &hdcsn[1];
+
+ uint16_t dcsn_size = ntohs (dcsn->header.size);
+ int is_admitted = ntohl (dcsn->is_admitted);
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "%p Member got join decision from multicast: %d\n",
+ mem, is_admitted);
+
+ const struct GNUNET_MessageHeader *join_resp = NULL;
+ uint16_t join_resp_size = 0;
+
+ uint16_t relay_count = ntohl (dcsn->relay_count);
+ const struct GNUNET_PeerIdentity *relays = NULL;
+ uint16_t relay_size = relay_count * sizeof (*relays);
+ if (0 < relay_count)
+ {
+ if (dcsn_size < sizeof (*dcsn) + relay_size)
+ {
+ GNUNET_break_op (0);
+ is_admitted = GNUNET_SYSERR;
+ }
+ else
+ {
+ relays = (struct GNUNET_PeerIdentity *) &dcsn[1];
+ }
+ }
+
+ if (sizeof (*dcsn) + relay_size + sizeof (*join_resp) <= dcsn_size)
+ {
+ join_resp = (const struct GNUNET_MessageHeader *) ((char *) &dcsn[1] + relay_size);
+ join_resp_size = ntohs (join_resp->size);
+ }
+ if (dcsn_size < sizeof (*dcsn) + relay_size + join_resp_size)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received invalid join decision message from multicast: %u < %u + %u + %u\n",
+ dcsn_size , sizeof (*dcsn), relay_size, join_resp_size);
+ GNUNET_break_op (0);
+ is_admitted = GNUNET_SYSERR;
+ }
+
+ if (NULL != mem->join_dcsn_cb)
+ mem->join_dcsn_cb (grp->cb_cls, is_admitted, &hdcsn->peer,
+ relay_count, relays, join_resp);
+
+ // FIXME:
+ //if (GNUNET_YES != is_admitted)
+ // GNUNET_MULTICAST_member_part (mem);
+
+ grp->reconnect_delay = GNUNET_TIME_UNIT_MILLISECONDS;
+}
+
+
+static void
+group_cleanup (struct GNUNET_MULTICAST_Group *grp)
+{
+ if (NULL != grp->connect_env)
+ {
+ GNUNET_MQ_discard (grp->connect_env);
+ grp->connect_env = NULL;
+ }
+ if (NULL != grp->mq)
+ {
+ GNUNET_MQ_destroy (grp->mq);
+ grp->mq = NULL;
+ }
+ if (NULL != grp->disconnect_cb)
+ {
+ grp->disconnect_cb (grp->disconnect_cls);
+ grp->disconnect_cb = NULL;
+ }
+ GNUNET_free (grp);
+}
+
+
+static void
+group_disconnect (struct GNUNET_MULTICAST_Group *grp,
+ GNUNET_ContinuationCallback cb,
+ void *cls)
+{
+ grp->is_disconnecting = GNUNET_YES;
+ grp->disconnect_cb = cb;
+ grp->disconnect_cls = cls;
+
+ if (NULL != grp->mq)
+ {
+ struct GNUNET_MQ_Envelope *last = GNUNET_MQ_get_last_envelope (grp->mq);
+ if (NULL != last)
+ {
+ GNUNET_MQ_notify_sent (last,
+ (GNUNET_MQ_NotifyCallback) group_cleanup, grp);
+ }
+ else
+ {
+ group_cleanup (grp);
+ }
+ }
+ else
+ {
+ group_cleanup (grp);
+ }