+ GNUNET_CONTAINER_DLL_insert_tail (barrier->whead, barrier->wtail, wrapper);
+ wrapper->hbarrier = GNUNET_TESTBED_barrier_init_ (slave->controller,
+ barrier->name,
+ barrier->quorum,
+ &wbarrier_status_cb,
+ wrapper,
+ GNUNET_NO);
+ }
+ if (NULL == barrier->whead) /* No further propagation */
+ {
+ barrier->status = GNUNET_TESTBED_BARRIERSTATUS_INITIALISED;
+ LOG_DEBUG ("Sending GNUNET_TESTBED_BARRIERSTATUS_INITIALISED for barrier `%s'\n",
+ barrier->name);
+ send_barrier_status_msg (barrier, NULL);
+ }else
+ barrier->tout_task = GNUNET_SCHEDULER_add_delayed (MESSAGE_SEND_TIMEOUT (30),
+ &fwd_tout_barrier_init,
+ barrier);
+}
+
+
+/**
+ * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. This
+ * message should always come from a parent controller or the testbed API if we
+ * are the root controller.
+ *
+ * This handler is queued in the main service and will handle the messages sent
+ * either from the testbed driver or from a high level controller
+ *
+ * @param cls NULL
+ * @param client identification of the client
+ * @param message the actual message
+ */
+void
+GST_handle_barrier_cancel (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ const struct GNUNET_TESTBED_BarrierCancel *msg;
+ char *name;
+ struct Barrier *barrier;
+ struct GNUNET_HashCode hash;
+ size_t name_len;
+ uint16_t msize;
+
+ if (NULL == GST_context)
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ if (client != GST_context->client)
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ msize = ntohs (message->size);
+ if (msize <= sizeof (struct GNUNET_TESTBED_BarrierCancel))
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ msg = (const struct GNUNET_TESTBED_BarrierCancel *) message;
+ name_len = msize - sizeof (struct GNUNET_TESTBED_BarrierCancel);
+ name = GNUNET_malloc (name_len + 1);
+ (void) memcpy (name, msg->name, name_len);
+ GNUNET_CRYPTO_hash (name, name_len, &hash);
+ if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (barrier_map, &hash))
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, &hash);
+ GNUNET_assert (NULL != barrier);
+ cancel_wrappers (barrier);
+ remove_barrier (barrier);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages.
+ * This handler is queued in the main service and will handle the messages sent
+ * either from the testbed driver or from a high level controller
+ *
+ * @param cls NULL
+ * @param client identification of the client
+ * @param message the actual message
+ */
+void
+GST_handle_barrier_status (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ const struct GNUNET_TESTBED_BarrierStatusMsg *msg;
+ struct Barrier *barrier;
+ struct ClientCtx *client_ctx;
+ const char *name;
+ struct GNUNET_HashCode key;
+ enum GNUNET_TESTBED_BarrierStatus status;
+ uint16_t msize;
+ uint16_t name_len;
+
+ if (NULL == GST_context)
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ if (client != GST_context->client)
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ msize = ntohs (message->size);
+ if (msize <= sizeof (struct GNUNET_TESTBED_BarrierStatusMsg))
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ msg = (const struct GNUNET_TESTBED_BarrierStatusMsg *) message;
+ status = ntohs (msg->status);
+ if (GNUNET_TESTBED_BARRIERSTATUS_CROSSED != status)
+ {
+ GNUNET_break_op (0); /* current we only expect BARRIER_CROSSED
+ status message this way */
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ name = msg->data;
+ name_len = ntohs (msg->name_len);
+ if ((sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len + 1) != msize)
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ if ('\0' != name[name_len])
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ GNUNET_CRYPTO_hash (name, name_len, &key);
+ barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, &key);
+ if (NULL == barrier)
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ while (NULL != (client_ctx = barrier->head)) /* Notify peers */
+ {
+ queue_message (client_ctx, GNUNET_copy_message (message));
+ GNUNET_CONTAINER_DLL_remove (barrier->head, barrier->tail, client_ctx);