aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-04-10 13:04:30 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-04-10 13:04:30 +0000
commitdd2b8d87339226bb3e9a04f7111561740328c40e (patch)
tree8b3911859227fe2548d7e016b48d0c226809f966
parent5c978455a6937620b4d6cfbca428c604096d7ed1 (diff)
downloadgnunet-dd2b8d87339226bb3e9a04f7111561740328c40e.tar.gz
gnunet-dd2b8d87339226bb3e9a04f7111561740328c40e.zip
- restructure
-rw-r--r--src/testbed/Makefile.am3
-rw-r--r--src/testbed/gnunet-service-testbed.c706
-rw-r--r--src/testbed/gnunet-service-testbed.h33
-rw-r--r--src/testbed/gnunet-service-testbed_links.c760
4 files changed, 799 insertions, 703 deletions
diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am
index 97e304ff3..6b8b44089 100644
--- a/src/testbed/Makefile.am
+++ b/src/testbed/Makefile.am
@@ -32,10 +32,11 @@ bin_PROGRAMS = \
32gnunet_service_testbed_SOURCES = \ 32gnunet_service_testbed_SOURCES = \
33 gnunet-service-testbed.h \ 33 gnunet-service-testbed.h \
34 gnunet-service-testbed.c \ 34 gnunet-service-testbed.c \
35 gnunet-service-testbed_links.c \
35 gnunet-service-testbed_peers.c \ 36 gnunet-service-testbed_peers.c \
36 gnunet-service-testbed_cache.c \ 37 gnunet-service-testbed_cache.c \
37 gnunet-service-testbed_oc.c \ 38 gnunet-service-testbed_oc.c \
38 gnunet-service-testbed_cpustatus.c 39 gnunet-service-testbed_cpustatus.c
39gnunet_service_testbed_LDADD = $(XLIB) \ 40gnunet_service_testbed_LDADD = $(XLIB) \
40 $(top_builddir)/src/util/libgnunetutil.la \ 41 $(top_builddir)/src/util/libgnunetutil.la \
41 $(top_builddir)/src/core/libgnunetcore.la \ 42 $(top_builddir)/src/core/libgnunetcore.la \
diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c
index 05668284b..25bded788 100644
--- a/src/testbed/gnunet-service-testbed.c
+++ b/src/testbed/gnunet-service-testbed.c
@@ -42,11 +42,6 @@ struct GNUNET_CONFIGURATION_Handle *our_config;
42struct Context *GST_context; 42struct Context *GST_context;
43 43
44/** 44/**
45 * A list of directly linked neighbours
46 */
47struct Slave **GST_slave_list;
48
49/**
50 * Array of hosts 45 * Array of hosts
51 */ 46 */
52struct GNUNET_TESTBED_Host **GST_host_list; 47struct GNUNET_TESTBED_Host **GST_host_list;
@@ -77,11 +72,6 @@ const struct GNUNET_TIME_Relative GST_timeout;
77unsigned int GST_host_list_size; 72unsigned int GST_host_list_size;
78 73
79/** 74/**
80 * The size of directly linked neighbours list
81 */
82unsigned int GST_slave_list_size;
83
84/**
85 * The size of the peer list 75 * The size of the peer list
86 */ 76 */
87unsigned int GST_peer_list_size; 77unsigned int GST_peer_list_size;
@@ -128,16 +118,6 @@ static char *hostname;
128static struct GNUNET_SERVER_TransmitHandle *transmit_handle; 118static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
129 119
130/** 120/**
131 * The head for the LCF queue
132 */
133static struct LCFContextQueue *lcfq_head;
134
135/**
136 * The tail for the LCF queue
137 */
138static struct LCFContextQueue *lcfq_tail;
139
140/**
141 * The message queue head 121 * The message queue head
142 */ 122 */
143static struct MessageQueue *mq_head; 123static struct MessageQueue *mq_head;
@@ -153,26 +133,6 @@ static struct MessageQueue *mq_tail;
153static struct GNUNET_CONTAINER_MultiHashMap *ss_map; 133static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
154 134
155/** 135/**
156 * A list of routes
157 */
158static struct Route **route_list;
159
160/**
161 * The event mask for the events we listen from sub-controllers
162 */
163static uint64_t event_mask;
164
165/**
166 * The size of the route list
167 */
168static unsigned int route_list_size;
169
170/**
171 * The lcf_task handle
172 */
173static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id;
174
175/**
176 * The shutdown task handle 136 * The shutdown task handle
177 */ 137 */
178static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id; 138static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
@@ -275,62 +235,6 @@ host_list_add (struct GNUNET_TESTBED_Host *host)
275 235
276 236
277/** 237/**
278 * Adds a route to the route list
279 *
280 * @param route the route to add
281 */
282static void
283route_list_add (struct Route *route)
284{
285 if (route->dest >= route_list_size)
286 GST_array_grow_large_enough (route_list, route_list_size, route->dest);
287 GNUNET_assert (NULL == route_list[route->dest]);
288 route_list[route->dest] = route;
289}
290
291
292/**
293 * Adds a slave to the slave array
294 *
295 * @param slave the slave controller to add
296 */
297static void
298slave_list_add (struct Slave *slave)
299{
300 if (slave->host_id >= GST_slave_list_size)
301 GST_array_grow_large_enough (GST_slave_list, GST_slave_list_size,
302 slave->host_id);
303 GNUNET_assert (NULL == GST_slave_list[slave->host_id]);
304 GST_slave_list[slave->host_id] = slave;
305}
306
307
308/**
309 * Finds the route with directly connected host as destination through which
310 * the destination host can be reached
311 *
312 * @param host_id the id of the destination host
313 * @return the route with directly connected destination host; NULL if no route
314 * is found
315 */
316struct Route *
317GST_find_dest_route (uint32_t host_id)
318{
319 struct Route *route;
320
321 if (route_list_size <= host_id)
322 return NULL;
323 while (NULL != (route = route_list[host_id]))
324 {
325 if (route->thru == GST_context->host_id)
326 break;
327 host_id = route->thru;
328 }
329 return route;
330}
331
332
333/**
334 * Routes message to a host given its host_id 238 * Routes message to a host given its host_id
335 * 239 *
336 * @param host_id the id of the destination host 240 * @param host_id the id of the destination host
@@ -395,61 +299,6 @@ GST_send_operation_success_msg (struct GNUNET_SERVER_Client *client,
395 GST_queue_message (client, &msg->header); 299 GST_queue_message (client, &msg->header);
396} 300}
397 301
398
399/**
400 * Function to send a failure reponse for controller link operation
401 *
402 * @param client the client to send the message to
403 * @param operation_id the operation ID of the controller link request
404 * @param cfg the configuration with which the delegated controller is started.
405 * Can be NULL if the delegated controller is not started but just
406 * linked to.
407 * @param emsg set to an error message explaining why the controller link
408 * failed. Setting this to NULL signifies success. !This should be
409 * NULL if cfg is set!
410 */
411static void
412send_controller_link_response (struct GNUNET_SERVER_Client *client,
413 uint64_t operation_id,
414 const struct GNUNET_CONFIGURATION_Handle
415 *cfg,
416 const char *emsg)
417{
418 struct GNUNET_TESTBED_ControllerLinkResponse *msg;
419 char *xconfig;
420 size_t config_size;
421 size_t xconfig_size;
422 uint16_t msize;
423
424 GNUNET_assert ((NULL == cfg) || (NULL == emsg));
425 xconfig = NULL;
426 xconfig_size = 0;
427 config_size = 0;
428 msize = sizeof (struct GNUNET_TESTBED_ControllerLinkResponse);
429 if (NULL != cfg)
430 {
431 xconfig = GNUNET_TESTBED_compress_cfg_ (cfg,
432 &config_size,
433 &xconfig_size);
434 msize += xconfig_size;
435 }
436 if (NULL != emsg)
437 msize += strlen (emsg);
438 msg = GNUNET_malloc (msize);
439 msg->header.type = htons
440 (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT);
441 msg->header.size = htons (msize);
442 if (NULL == emsg)
443 msg->success = htons (GNUNET_YES);
444 msg->operation_id = GNUNET_htonll (operation_id);
445 msg->config_size = htons ((uint16_t) config_size);
446 if (NULL != xconfig)
447 memcpy (&msg[1], xconfig, xconfig_size);
448 if (NULL != emsg)
449 memcpy (&msg[1], emsg, strlen (emsg));
450 GST_queue_message (client, &msg->header);
451}
452
453/** 302/**
454 * Callback which will be called after a host registration succeeded or failed 303 * Callback which will be called after a host registration succeeded or failed
455 * 304 *
@@ -543,55 +392,6 @@ GST_queue_host_registration (struct Slave *slave,
543 392
544 393
545/** 394/**
546 * The Link Controller forwarding task
547 *
548 * @param cls the LCFContext
549 * @param tc the Task context from scheduler
550 */
551static void
552lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
553
554
555/**
556 * Completion callback for host registrations while forwarding Link Controller messages
557 *
558 * @param cls the LCFContext
559 * @param emsg the error message; NULL if host registration is successful
560 */
561static void
562lcf_proc_cc (void *cls, const char *emsg)
563{
564 struct LCFContext *lcf = cls;
565
566 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
567 switch (lcf->state)
568 {
569 case INIT:
570 if (NULL != emsg)
571 goto registration_error;
572 lcf->state = DELEGATED_HOST_REGISTERED;
573 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
574 break;
575 case DELEGATED_HOST_REGISTERED:
576 if (NULL != emsg)
577 goto registration_error;
578 lcf->state = SLAVE_HOST_REGISTERED;
579 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
580 break;
581 default:
582 GNUNET_assert (0); /* Shouldn't reach here */
583 }
584 return;
585
586registration_error:
587 LOG (GNUNET_ERROR_TYPE_WARNING, "Host registration failed with message: %s\n",
588 emsg);
589 lcf->state = FINISHED;
590 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
591}
592
593
594/**
595 * Callback to relay the reply msg of a forwarded operation back to the client 395 * Callback to relay the reply msg of a forwarded operation back to the client
596 * 396 *
597 * @param cls ForwardedOperationContext 397 * @param cls ForwardedOperationContext
@@ -640,244 +440,6 @@ GST_forwarded_operation_timeout (void *cls,
640 440
641 441
642/** 442/**
643 * The Link Controller forwarding task
644 *
645 * @param cls the LCFContext
646 * @param tc the Task context from scheduler
647 */
648static void
649lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
650
651
652/**
653 * Task to free resources when forwarded link controllers has been timedout
654 *
655 * @param cls the LCFContext
656 * @param tc the task context from scheduler
657 */
658static void
659lcf_forwarded_operation_timeout (void *cls,
660 const struct GNUNET_SCHEDULER_TaskContext *tc)
661{
662 struct LCFContext *lcf = cls;
663
664 lcf->timeout_task = GNUNET_SCHEDULER_NO_TASK;
665 // GST_forwarded_operation_timeout (lcf->fopc, tc);
666 LOG (GNUNET_ERROR_TYPE_WARNING,
667 "A forwarded controller link operation has timed out\n");
668 send_controller_link_response (lcf->client, lcf->operation_id, NULL,
669 "A forwarded controller link operation has "
670 "timed out\n");
671 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
672 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
673}
674
675
676/**
677 * The Link Controller forwarding task
678 *
679 * @param cls the LCFContext
680 * @param tc the Task context from scheduler
681 */
682static void
683lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
684{
685 struct LCFContext *lcf = cls;
686 struct LCFContextQueue *lcfq;
687
688 lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
689 switch (lcf->state)
690 {
691 case INIT:
692 if (GNUNET_NO ==
693 GNUNET_TESTBED_is_host_registered_ (GST_host_list
694 [lcf->delegated_host_id],
695 lcf->gateway->controller))
696 {
697 GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf,
698 GST_host_list[lcf->delegated_host_id]);
699 }
700 else
701 {
702 lcf->state = DELEGATED_HOST_REGISTERED;
703 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
704 }
705 break;
706 case DELEGATED_HOST_REGISTERED:
707 if (GNUNET_NO ==
708 GNUNET_TESTBED_is_host_registered_ (GST_host_list[lcf->slave_host_id],
709 lcf->gateway->controller))
710 {
711 GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf,
712 GST_host_list[lcf->slave_host_id]);
713 }
714 else
715 {
716 lcf->state = SLAVE_HOST_REGISTERED;
717 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
718 }
719 break;
720 case SLAVE_HOST_REGISTERED:
721 lcf->op = GNUNET_TESTBED_controller_link (lcf,
722 lcf->gateway->controller,
723 GST_host_list[lcf->delegated_host_id],
724 GST_host_list[lcf->slave_host_id],
725 NULL,
726 lcf->is_subordinate);
727 lcf->timeout_task =
728 GNUNET_SCHEDULER_add_delayed (GST_timeout, &lcf_forwarded_operation_timeout,
729 lcf);
730 lcf->state = FINISHED;
731 break;
732 case FINISHED:
733 lcfq = lcfq_head;
734 GNUNET_assert (lcfq->lcf == lcf);
735 GNUNET_assert (NULL != lcf->cfg);
736 GNUNET_CONFIGURATION_destroy (lcf->cfg);
737 GNUNET_SERVER_client_drop (lcf->client);
738 GNUNET_TESTBED_operation_done (lcf->op);
739 GNUNET_free (lcf);
740 GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
741 GNUNET_free (lcfq);
742 if (NULL != lcfq_head)
743 lcf_proc_task_id =
744 GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf);
745 }
746}
747
748
749/**
750 * Callback for event from slave controllers
751 *
752 * @param cls struct Slave *
753 * @param event information about the event
754 */
755static void
756slave_event_callback (void *cls,
757 const struct GNUNET_TESTBED_EventInformation *event)
758{
759 struct RegisteredHostContext *rhc;
760 struct LCFContext *lcf;
761 struct GNUNET_CONFIGURATION_Handle *cfg;
762 struct GNUNET_TESTBED_Operation *old_op;
763
764 /* We currently only get here when working on RegisteredHostContexts and
765 LCFContexts */
766 GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
767 rhc = event->op_cls;
768 if (CLOSURE_TYPE_RHC == rhc->type)
769 {
770 GNUNET_assert (rhc->sub_op == event->op);
771 switch (rhc->state)
772 {
773 case RHC_GET_CFG:
774 cfg = event->details.operation_finished.generic;
775 old_op = rhc->sub_op;
776 rhc->state = RHC_LINK;
777 rhc->sub_op =
778 GNUNET_TESTBED_controller_link (rhc, rhc->gateway->controller,
779 rhc->reg_host, rhc->host, cfg,
780 GNUNET_NO);
781 GNUNET_TESTBED_operation_done (old_op);
782 break;
783 case RHC_LINK:
784 LOG_DEBUG ("OL: Linking controllers successfull\n");
785 GNUNET_TESTBED_operation_done (rhc->sub_op);
786 rhc->sub_op = NULL;
787 rhc->state = RHC_OL_CONNECT;
788 GST_process_next_focc (rhc);
789 break;
790 default:
791 GNUNET_assert (0);
792 }
793 return;
794 }
795 lcf = event->op_cls;
796 if (CLOSURE_TYPE_LCF == lcf->type)
797 {
798 GNUNET_assert (lcf->op == event->op);
799 GNUNET_assert (FINISHED == lcf->state);
800 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != lcf->timeout_task);
801 GNUNET_SCHEDULER_cancel (lcf->timeout_task);
802 if (NULL == event->details.operation_finished.emsg)
803 send_controller_link_response (lcf->client, lcf->operation_id,
804 GNUNET_TESTBED_host_get_cfg_
805 (GST_host_list[lcf->delegated_host_id]),
806 NULL);
807 else
808 send_controller_link_response (lcf->client, lcf->operation_id,
809 NULL,
810 event->details.operation_finished.emsg);
811 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
812 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
813 return;
814 }
815 GNUNET_assert (0);
816}
817
818
819/**
820 * Callback to signal successfull startup of the controller process
821 *
822 * @param cls the handle to the slave whose status is to be found here
823 * @param cfg the configuration with which the controller has been started;
824 * NULL if status is not GNUNET_OK
825 * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
826 * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
827 */
828static void
829slave_status_callback (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
830 int status)
831{
832 struct Slave *slave = cls;
833 struct LinkControllersContext *lcc;
834
835 lcc = slave->lcc;
836 if (GNUNET_SYSERR == status)
837 {
838 slave->controller_proc = NULL;
839 GST_slave_list[slave->host_id] = NULL;
840 GNUNET_free (slave);
841 slave = NULL;
842 LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected slave shutdown\n");
843 GNUNET_SCHEDULER_shutdown (); /* We too shutdown */
844 goto clean_lcc;
845 }
846 slave->controller =
847 GNUNET_TESTBED_controller_connect (cfg, GST_host_list[slave->host_id],
848 event_mask, &slave_event_callback,
849 slave);
850 if (NULL != slave->controller)
851 {
852 send_controller_link_response (lcc->client, lcc->operation_id, cfg, NULL);
853 }
854 else
855 {
856 send_controller_link_response (lcc->client, lcc->operation_id, NULL,
857 "Could not connect to delegated controller");
858 GNUNET_TESTBED_controller_stop (slave->controller_proc);
859 GST_slave_list[slave->host_id] = NULL;
860 GNUNET_free (slave);
861 slave = NULL;
862 }
863
864clean_lcc:
865 if (NULL != lcc)
866 {
867 if (NULL != lcc->client)
868 {
869 GNUNET_SERVER_receive_done (lcc->client, GNUNET_OK);
870 GNUNET_SERVER_client_drop (lcc->client);
871 lcc->client = NULL;
872 }
873 GNUNET_free (lcc);
874 }
875 if (NULL != slave)
876 slave->lcc = NULL;
877}
878
879
880/**
881 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages 443 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
882 * 444 *
883 * @param cls NULL 445 * @param cls NULL
@@ -1139,184 +701,6 @@ handle_configure_shared_service (void *cls, struct GNUNET_SERVER_Client *client,
1139 701
1140 702
1141/** 703/**
1142 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
1143 *
1144 * @param cls NULL
1145 * @param client identification of the client
1146 * @param message the actual message
1147 */
1148static void
1149handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
1150 const struct GNUNET_MessageHeader *message)
1151{
1152 const struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1153 struct GNUNET_CONFIGURATION_Handle *cfg;
1154 struct LCFContextQueue *lcfq;
1155 struct Route *route;
1156 struct Route *new_route;
1157 uint32_t delegated_host_id;
1158 uint32_t slave_host_id;
1159 uint16_t msize;
1160
1161 if (NULL == GST_context)
1162 {
1163 GNUNET_break (0);
1164 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1165 return;
1166 }
1167 msize = ntohs (message->size);
1168 if (sizeof (struct GNUNET_TESTBED_ControllerLinkRequest) >= msize)
1169 {
1170 GNUNET_break (0);
1171 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1172 return;
1173 }
1174 msg = (const struct GNUNET_TESTBED_ControllerLinkRequest *) message;
1175 delegated_host_id = ntohl (msg->delegated_host_id);
1176 if (delegated_host_id == GST_context->host_id)
1177 {
1178 GNUNET_break (0);
1179 LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
1180 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1181 return;
1182 }
1183 if ((delegated_host_id >= GST_host_list_size) ||
1184 (NULL == GST_host_list[delegated_host_id]))
1185 {
1186 LOG (GNUNET_ERROR_TYPE_WARNING,
1187 "Delegated host %u not registered with us\n", delegated_host_id);
1188 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1189 return;
1190 }
1191 slave_host_id = ntohl (msg->slave_host_id);
1192 if ((slave_host_id >= GST_host_list_size) ||
1193 (NULL == GST_host_list[slave_host_id]))
1194 {
1195 LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host %u not registered with us\n",
1196 slave_host_id);
1197 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1198 return;
1199 }
1200 if (slave_host_id == delegated_host_id)
1201 {
1202 LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
1203 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1204 return;
1205 }
1206 cfg = GNUNET_TESTBED_extract_config_ (message); /* destroy cfg here or in lcfcontext */
1207 if (NULL == cfg)
1208 {
1209 GNUNET_break (0); /* Configuration parsing error */
1210 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1211 return;
1212 }
1213 if (slave_host_id == GST_context->host_id) /* Link from us */
1214 {
1215 struct Slave *slave;
1216 struct LinkControllersContext *lcc;
1217
1218 if ((delegated_host_id < GST_slave_list_size) &&
1219 (NULL != GST_slave_list[delegated_host_id]))
1220 {
1221 GNUNET_break (0);
1222 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1223 return;
1224 }
1225 slave = GNUNET_malloc (sizeof (struct Slave));
1226 slave->host_id = delegated_host_id;
1227 slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100, GNUNET_NO);
1228 slave_list_add (slave);
1229 if (1 != msg->is_subordinate)
1230 {
1231 slave->controller =
1232 GNUNET_TESTBED_controller_connect (cfg, GST_host_list[slave->host_id],
1233 event_mask, &slave_event_callback,
1234 slave);
1235 if (NULL != slave->controller)
1236 send_controller_link_response (client,
1237 GNUNET_ntohll (msg->operation_id),
1238 NULL,
1239 NULL);
1240 else
1241 send_controller_link_response (client,
1242 GNUNET_ntohll (msg->operation_id),
1243 NULL,
1244 "Could not connect to delegated controller");
1245 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1246 return;
1247 }
1248 lcc = GNUNET_malloc (sizeof (struct LinkControllersContext));
1249 lcc->operation_id = GNUNET_ntohll (msg->operation_id);
1250 GNUNET_SERVER_client_keep (client);
1251 lcc->client = client;
1252 slave->lcc = lcc;
1253 slave->controller_proc =
1254 GNUNET_TESTBED_controller_start (GST_context->master_ip,
1255 GST_host_list[slave->host_id], cfg,
1256 &slave_status_callback, slave);
1257 GNUNET_CONFIGURATION_destroy (cfg);
1258 new_route = GNUNET_malloc (sizeof (struct Route));
1259 new_route->dest = delegated_host_id;
1260 new_route->thru = GST_context->host_id;
1261 route_list_add (new_route);
1262 return;
1263 }
1264
1265 /* Route the request */
1266 if (slave_host_id >= route_list_size)
1267 {
1268 LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
1269 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1270 return;
1271 }
1272 lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
1273 lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
1274 lcfq->lcf->type = CLOSURE_TYPE_LCF;
1275 lcfq->lcf->delegated_host_id = delegated_host_id;
1276 lcfq->lcf->slave_host_id = slave_host_id;
1277 route = GST_find_dest_route (slave_host_id);
1278 GNUNET_assert (NULL != route); /* because we add routes carefully */
1279 GNUNET_assert (route->dest < GST_slave_list_size);
1280 GNUNET_assert (NULL != GST_slave_list[route->dest]);
1281 lcfq->lcf->cfg = cfg;
1282 lcfq->lcf->is_subordinate = msg->is_subordinate;
1283 lcfq->lcf->state = INIT;
1284 lcfq->lcf->operation_id = GNUNET_ntohll (msg->operation_id);
1285 lcfq->lcf->gateway = GST_slave_list[route->dest];
1286 GNUNET_SERVER_client_keep (client);
1287 lcfq->lcf->client = client;
1288 if (NULL == lcfq_head)
1289 {
1290 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1291 GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1292 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq->lcf);
1293 }
1294 else
1295 GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1296 /* FIXME: Adding a new route should happen after the controllers are linked
1297 * successfully */
1298 if (1 != msg->is_subordinate)
1299 {
1300 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1301 return;
1302 }
1303 if ((delegated_host_id < route_list_size) &&
1304 (NULL != route_list[delegated_host_id]))
1305 {
1306 GNUNET_break_op (0); /* Are you trying to link delegated host twice
1307 * with is subordinate flag set to GNUNET_YES? */
1308 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1309 return;
1310 }
1311 new_route = GNUNET_malloc (sizeof (struct Route));
1312 new_route->dest = delegated_host_id;
1313 new_route->thru = route->dest;
1314 route_list_add (new_route);
1315 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1316}
1317
1318
1319/**
1320 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages 704 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages
1321 * 705 *
1322 * @param cls NULL 706 * @param cls NULL
@@ -1441,41 +825,6 @@ ss_map_free_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
1441 825
1442 826
1443/** 827/**
1444 * Iterator for freeing hash map entries in a slave's reghost_map
1445 *
1446 * @param cls handle to the slave
1447 * @param key current key code
1448 * @param value value in the hash map
1449 * @return GNUNET_YES if we should continue to
1450 * iterate,
1451 * GNUNET_NO if not.
1452 */
1453static int
1454reghost_free_iterator (void *cls, const struct GNUNET_HashCode *key,
1455 void *value)
1456{
1457 struct Slave *slave = cls;
1458 struct RegisteredHostContext *rhc = value;
1459 struct ForwardedOverlayConnectContext *focc;
1460
1461 GNUNET_assert (GNUNET_YES ==
1462 GNUNET_CONTAINER_multihashmap_remove (slave->reghost_map, key,
1463 value));
1464 while (NULL != (focc = rhc->focc_dll_head))
1465 {
1466 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
1467 GST_cleanup_focc (focc);
1468 }
1469 if (NULL != rhc->sub_op)
1470 GNUNET_TESTBED_operation_done (rhc->sub_op);
1471 if (NULL != rhc->client)
1472 GNUNET_SERVER_client_drop (rhc->client);
1473 GNUNET_free (value);
1474 return GNUNET_YES;
1475}
1476
1477
1478/**
1479 * Task to clean up and shutdown nicely 828 * Task to clean up and shutdown nicely
1480 * 829 *
1481 * @param cls NULL 830 * @param cls NULL
@@ -1484,7 +833,6 @@ reghost_free_iterator (void *cls, const struct GNUNET_HashCode *key,
1484static void 833static void
1485shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 834shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1486{ 835{
1487 struct LCFContextQueue *lcfq;
1488 struct MessageQueue *mq_entry; 836 struct MessageQueue *mq_entry;
1489 uint32_t id; 837 uint32_t id;
1490 838
@@ -1495,24 +843,7 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1495 GNUNET_CONTAINER_multihashmap_destroy (ss_map); 843 GNUNET_CONTAINER_multihashmap_destroy (ss_map);
1496 /* cleanup any remaining forwarded operations */ 844 /* cleanup any remaining forwarded operations */
1497 GST_clear_fopcq (); 845 GST_clear_fopcq ();
1498 if (NULL != lcfq_head) 846 GST_free_lcfq ();
1499 {
1500 if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
1501 {
1502 GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
1503 lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
1504 }
1505 }
1506 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1507 for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
1508 {
1509 GNUNET_SERVER_client_drop (lcfq->lcf->client);
1510 GNUNET_assert (NULL != lcfq->lcf->cfg);
1511 GNUNET_CONFIGURATION_destroy (lcfq->lcf->cfg);
1512 GNUNET_free (lcfq->lcf);
1513 GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
1514 GNUNET_free (lcfq);
1515 }
1516 GST_free_mctxq (); 847 GST_free_mctxq ();
1517 GST_free_occq (); 848 GST_free_occq ();
1518 GST_free_roccq (); 849 GST_free_roccq ();
@@ -1524,37 +855,9 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1524 GNUNET_TESTBED_host_destroy (GST_host_list[id]); 855 GNUNET_TESTBED_host_destroy (GST_host_list[id]);
1525 GNUNET_free_non_null (GST_host_list); 856 GNUNET_free_non_null (GST_host_list);
1526 /* Clear route list */ 857 /* Clear route list */
1527 for (id = 0; id < route_list_size; id++) 858 GST_route_list_clear ();
1528 if (NULL != route_list[id])
1529 GNUNET_free (route_list[id]);
1530 GNUNET_free_non_null (route_list);
1531 /* Clear GST_slave_list */ 859 /* Clear GST_slave_list */
1532 for (id = 0; id < GST_slave_list_size; id++) 860 GST_slave_list_clear ();
1533 if (NULL != GST_slave_list[id])
1534 {
1535 struct HostRegistration *hr_entry;
1536
1537 while (NULL != (hr_entry = GST_slave_list[id]->hr_dll_head))
1538 {
1539 GNUNET_CONTAINER_DLL_remove (GST_slave_list[id]->hr_dll_head,
1540 GST_slave_list[id]->hr_dll_tail, hr_entry);
1541 GNUNET_free (hr_entry);
1542 }
1543 if (NULL != GST_slave_list[id]->rhandle)
1544 GNUNET_TESTBED_cancel_registration (GST_slave_list[id]->rhandle);
1545 (void)
1546 GNUNET_CONTAINER_multihashmap_iterate (GST_slave_list
1547 [id]->reghost_map,
1548 reghost_free_iterator,
1549 GST_slave_list[id]);
1550 GNUNET_CONTAINER_multihashmap_destroy (GST_slave_list[id]->reghost_map);
1551 if (NULL != GST_slave_list[id]->controller)
1552 GNUNET_TESTBED_controller_disconnect (GST_slave_list[id]->controller);
1553 if (NULL != GST_slave_list[id]->controller_proc)
1554 GNUNET_TESTBED_controller_stop (GST_slave_list[id]->controller_proc);
1555 GNUNET_free (GST_slave_list[id]);
1556 }
1557 GNUNET_free_non_null (GST_slave_list);
1558 if (NULL != GST_context) 861 if (NULL != GST_context)
1559 { 862 {
1560 GNUNET_free_non_null (GST_context->master_ip); 863 GNUNET_free_non_null (GST_context->master_ip);
@@ -1623,7 +926,7 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
1623 {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, 0}, 926 {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, 0},
1624 {&handle_configure_shared_service, NULL, 927 {&handle_configure_shared_service, NULL,
1625 GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE, 0}, 928 GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE, 0},
1626 {&handle_link_controllers, NULL, 929 {&GST_handle_link_controllers, NULL,
1627 GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, 0}, 930 GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, 0},
1628 {&GST_handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER, 0}, 931 {&GST_handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER, 0},
1629 {&GST_handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER, 932 {&GST_handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER,
@@ -1685,7 +988,6 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
1685 GNUNET_SCHEDULER_PRIORITY_IDLE, 988 GNUNET_SCHEDULER_PRIORITY_IDLE,
1686 &shutdown_task, NULL); 989 &shutdown_task, NULL);
1687 LOG_DEBUG ("Testbed startup complete\n"); 990 LOG_DEBUG ("Testbed startup complete\n");
1688 event_mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED;
1689 GST_stats_init (our_config); 991 GST_stats_init (our_config);
1690} 992}
1691 993
diff --git a/src/testbed/gnunet-service-testbed.h b/src/testbed/gnunet-service-testbed.h
index 4a33b92ef..2a410a850 100644
--- a/src/testbed/gnunet-service-testbed.h
+++ b/src/testbed/gnunet-service-testbed.h
@@ -748,6 +748,18 @@ GST_find_dest_route (uint32_t host_id);
748 748
749 749
750/** 750/**
751 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
752 *
753 * @param cls NULL
754 * @param client identification of the client
755 * @param message the actual message
756 */
757void
758GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
759 const struct GNUNET_MessageHeader *message);
760
761
762/**
751 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages 763 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
752 * 764 *
753 * @param cls NULL 765 * @param cls NULL
@@ -931,6 +943,27 @@ GST_free_mctxq ();
931 943
932 944
933/** 945/**
946 * Cleans up the queue used for forwarding link controllers requests
947 */
948void
949GST_free_lcfq ();
950
951
952/**
953 * Cleans up the route list
954 */
955void
956GST_route_list_clear ();
957
958
959/**
960 * Cleans up the slave list
961 */
962void
963GST_slave_list_clear ();
964
965
966/**
934 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext 967 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
935 * 968 *
936 * @param rhc the RegisteredHostContext 969 * @param rhc the RegisteredHostContext
diff --git a/src/testbed/gnunet-service-testbed_links.c b/src/testbed/gnunet-service-testbed_links.c
new file mode 100644
index 000000000..6f71d8a61
--- /dev/null
+++ b/src/testbed/gnunet-service-testbed_links.c
@@ -0,0 +1,760 @@
1/*
2 This file is part of GNUnet.
3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file testbed/gnunet-service-testbed.c
23 * @brief implementation of the TESTBED service
24 * @author Sree Harsha Totakura
25 */
26
27#include "gnunet-service-testbed.h"
28
29/**
30 * The event mask for the events we listen from sub-controllers
31 */
32#define EVENT_MASK (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED)
33
34/**
35 * A list of directly linked neighbours
36 */
37struct Slave **GST_slave_list;
38
39/**
40 * The size of directly linked neighbours list
41 */
42unsigned int GST_slave_list_size;
43
44/**
45 * A list of routes
46 */
47static struct Route **route_list;
48
49/**
50 * The head for the LCF queue
51 */
52static struct LCFContextQueue *lcfq_head;
53
54/**
55 * The tail for the LCF queue
56 */
57static struct LCFContextQueue *lcfq_tail;
58
59/**
60 * The lcf_task handle
61 */
62static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id;
63
64/**
65 * The size of the route list
66 */
67static unsigned int route_list_size;
68
69
70/**
71 * Adds a slave to the slave array
72 *
73 * @param slave the slave controller to add
74 */
75static void
76slave_list_add (struct Slave *slave)
77{
78 if (slave->host_id >= GST_slave_list_size)
79 GST_array_grow_large_enough (GST_slave_list, GST_slave_list_size,
80 slave->host_id);
81 GNUNET_assert (NULL == GST_slave_list[slave->host_id]);
82 GST_slave_list[slave->host_id] = slave;
83}
84
85
86/**
87 * Adds a route to the route list
88 *
89 * @param route the route to add
90 */
91static void
92route_list_add (struct Route *route)
93{
94 if (route->dest >= route_list_size)
95 GST_array_grow_large_enough (route_list, route_list_size, route->dest);
96 GNUNET_assert (NULL == route_list[route->dest]);
97 route_list[route->dest] = route;
98}
99
100
101/**
102 * Cleans up the route list
103 */
104void
105GST_route_list_clear ()
106{
107 unsigned int id;
108
109 for (id = 0; id < route_list_size; id++)
110 if (NULL != route_list[id])
111 GNUNET_free (route_list[id]);
112 GNUNET_free_non_null (route_list);
113 route_list = NULL;
114}
115
116
117/**
118 * Iterator for freeing hash map entries in a slave's reghost_map
119 *
120 * @param cls handle to the slave
121 * @param key current key code
122 * @param value value in the hash map
123 * @return GNUNET_YES if we should continue to
124 * iterate,
125 * GNUNET_NO if not.
126 */
127static int
128reghost_free_iterator (void *cls, const struct GNUNET_HashCode *key,
129 void *value)
130{
131 struct Slave *slave = cls;
132 struct RegisteredHostContext *rhc = value;
133 struct ForwardedOverlayConnectContext *focc;
134
135 GNUNET_assert (GNUNET_YES ==
136 GNUNET_CONTAINER_multihashmap_remove (slave->reghost_map, key,
137 value));
138 while (NULL != (focc = rhc->focc_dll_head))
139 {
140 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
141 GST_cleanup_focc (focc);
142 }
143 if (NULL != rhc->sub_op)
144 GNUNET_TESTBED_operation_done (rhc->sub_op);
145 if (NULL != rhc->client)
146 GNUNET_SERVER_client_drop (rhc->client);
147 GNUNET_free (value);
148 return GNUNET_YES;
149}
150
151
152/**
153 * Cleans up the slave list
154 */
155void
156GST_slave_list_clear ()
157{
158 unsigned int id;
159 struct HostRegistration *hr_entry;
160
161 for (id = 0; id < GST_slave_list_size; id++)
162 if (NULL != GST_slave_list[id])
163 {
164 while (NULL != (hr_entry = GST_slave_list[id]->hr_dll_head))
165 {
166 GNUNET_CONTAINER_DLL_remove (GST_slave_list[id]->hr_dll_head,
167 GST_slave_list[id]->hr_dll_tail, hr_entry);
168 GNUNET_free (hr_entry);
169 }
170 if (NULL != GST_slave_list[id]->rhandle)
171 GNUNET_TESTBED_cancel_registration (GST_slave_list[id]->rhandle);
172 (void)
173 GNUNET_CONTAINER_multihashmap_iterate (GST_slave_list
174 [id]->reghost_map,
175 reghost_free_iterator,
176 GST_slave_list[id]);
177 GNUNET_CONTAINER_multihashmap_destroy (GST_slave_list[id]->reghost_map);
178 if (NULL != GST_slave_list[id]->controller)
179 GNUNET_TESTBED_controller_disconnect (GST_slave_list[id]->controller);
180 if (NULL != GST_slave_list[id]->controller_proc)
181 GNUNET_TESTBED_controller_stop (GST_slave_list[id]->controller_proc);
182 GNUNET_free (GST_slave_list[id]);
183 }
184 GNUNET_free_non_null (GST_slave_list);
185 GST_slave_list = NULL;
186}
187
188
189/**
190 * Finds the route with directly connected host as destination through which
191 * the destination host can be reached
192 *
193 * @param host_id the id of the destination host
194 * @return the route with directly connected destination host; NULL if no route
195 * is found
196 */
197struct Route *
198GST_find_dest_route (uint32_t host_id)
199{
200 struct Route *route;
201
202 if (route_list_size <= host_id)
203 return NULL;
204 while (NULL != (route = route_list[host_id]))
205 {
206 if (route->thru == GST_context->host_id)
207 break;
208 host_id = route->thru;
209 }
210 return route;
211}
212
213
214/**
215 * Function to send a failure reponse for controller link operation
216 *
217 * @param client the client to send the message to
218 * @param operation_id the operation ID of the controller link request
219 * @param cfg the configuration with which the delegated controller is started.
220 * Can be NULL if the delegated controller is not started but just
221 * linked to.
222 * @param emsg set to an error message explaining why the controller link
223 * failed. Setting this to NULL signifies success. !This should be
224 * NULL if cfg is set!
225 */
226static void
227send_controller_link_response (struct GNUNET_SERVER_Client *client,
228 uint64_t operation_id,
229 const struct GNUNET_CONFIGURATION_Handle
230 *cfg,
231 const char *emsg)
232{
233 struct GNUNET_TESTBED_ControllerLinkResponse *msg;
234 char *xconfig;
235 size_t config_size;
236 size_t xconfig_size;
237 uint16_t msize;
238
239 GNUNET_assert ((NULL == cfg) || (NULL == emsg));
240 xconfig = NULL;
241 xconfig_size = 0;
242 config_size = 0;
243 msize = sizeof (struct GNUNET_TESTBED_ControllerLinkResponse);
244 if (NULL != cfg)
245 {
246 xconfig = GNUNET_TESTBED_compress_cfg_ (cfg,
247 &config_size,
248 &xconfig_size);
249 msize += xconfig_size;
250 }
251 if (NULL != emsg)
252 msize += strlen (emsg);
253 msg = GNUNET_malloc (msize);
254 msg->header.type = htons
255 (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT);
256 msg->header.size = htons (msize);
257 if (NULL == emsg)
258 msg->success = htons (GNUNET_YES);
259 msg->operation_id = GNUNET_htonll (operation_id);
260 msg->config_size = htons ((uint16_t) config_size);
261 if (NULL != xconfig)
262 memcpy (&msg[1], xconfig, xconfig_size);
263 if (NULL != emsg)
264 memcpy (&msg[1], emsg, strlen (emsg));
265 GST_queue_message (client, &msg->header);
266}
267
268
269/**
270 * The Link Controller forwarding task
271 *
272 * @param cls the LCFContext
273 * @param tc the Task context from scheduler
274 */
275static void
276lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
277
278
279/**
280 * Completion callback for host registrations while forwarding Link Controller messages
281 *
282 * @param cls the LCFContext
283 * @param emsg the error message; NULL if host registration is successful
284 */
285static void
286lcf_proc_cc (void *cls, const char *emsg)
287{
288 struct LCFContext *lcf = cls;
289
290 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
291 switch (lcf->state)
292 {
293 case INIT:
294 if (NULL != emsg)
295 goto registration_error;
296 lcf->state = DELEGATED_HOST_REGISTERED;
297 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
298 break;
299 case DELEGATED_HOST_REGISTERED:
300 if (NULL != emsg)
301 goto registration_error;
302 lcf->state = SLAVE_HOST_REGISTERED;
303 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
304 break;
305 default:
306 GNUNET_assert (0); /* Shouldn't reach here */
307 }
308 return;
309
310registration_error:
311 LOG (GNUNET_ERROR_TYPE_WARNING, "Host registration failed with message: %s\n",
312 emsg);
313 lcf->state = FINISHED;
314 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
315}
316
317
318/**
319 * The Link Controller forwarding task
320 *
321 * @param cls the LCFContext
322 * @param tc the Task context from scheduler
323 */
324static void
325lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
326
327
328/**
329 * Task to free resources when forwarded link controllers has been timedout
330 *
331 * @param cls the LCFContext
332 * @param tc the task context from scheduler
333 */
334static void
335lcf_forwarded_operation_timeout (void *cls,
336 const struct GNUNET_SCHEDULER_TaskContext *tc)
337{
338 struct LCFContext *lcf = cls;
339
340 lcf->timeout_task = GNUNET_SCHEDULER_NO_TASK;
341 // GST_forwarded_operation_timeout (lcf->fopc, tc);
342 LOG (GNUNET_ERROR_TYPE_WARNING,
343 "A forwarded controller link operation has timed out\n");
344 send_controller_link_response (lcf->client, lcf->operation_id, NULL,
345 "A forwarded controller link operation has "
346 "timed out\n");
347 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
348 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
349}
350
351
352/**
353 * The Link Controller forwarding task
354 *
355 * @param cls the LCFContext
356 * @param tc the Task context from scheduler
357 */
358static void
359lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
360{
361 struct LCFContext *lcf = cls;
362 struct LCFContextQueue *lcfq;
363
364 lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
365 switch (lcf->state)
366 {
367 case INIT:
368 if (GNUNET_NO ==
369 GNUNET_TESTBED_is_host_registered_ (GST_host_list
370 [lcf->delegated_host_id],
371 lcf->gateway->controller))
372 {
373 GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf,
374 GST_host_list[lcf->delegated_host_id]);
375 }
376 else
377 {
378 lcf->state = DELEGATED_HOST_REGISTERED;
379 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
380 }
381 break;
382 case DELEGATED_HOST_REGISTERED:
383 if (GNUNET_NO ==
384 GNUNET_TESTBED_is_host_registered_ (GST_host_list[lcf->slave_host_id],
385 lcf->gateway->controller))
386 {
387 GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf,
388 GST_host_list[lcf->slave_host_id]);
389 }
390 else
391 {
392 lcf->state = SLAVE_HOST_REGISTERED;
393 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
394 }
395 break;
396 case SLAVE_HOST_REGISTERED:
397 lcf->op = GNUNET_TESTBED_controller_link (lcf,
398 lcf->gateway->controller,
399 GST_host_list[lcf->delegated_host_id],
400 GST_host_list[lcf->slave_host_id],
401 NULL,
402 lcf->is_subordinate);
403 lcf->timeout_task =
404 GNUNET_SCHEDULER_add_delayed (GST_timeout, &lcf_forwarded_operation_timeout,
405 lcf);
406 lcf->state = FINISHED;
407 break;
408 case FINISHED:
409 lcfq = lcfq_head;
410 GNUNET_assert (lcfq->lcf == lcf);
411 GNUNET_assert (NULL != lcf->cfg);
412 GNUNET_CONFIGURATION_destroy (lcf->cfg);
413 GNUNET_SERVER_client_drop (lcf->client);
414 GNUNET_TESTBED_operation_done (lcf->op);
415 GNUNET_free (lcf);
416 GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
417 GNUNET_free (lcfq);
418 if (NULL != lcfq_head)
419 lcf_proc_task_id =
420 GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf);
421 }
422}
423
424
425/**
426 * Callback for event from slave controllers
427 *
428 * @param cls struct Slave *
429 * @param event information about the event
430 */
431static void
432slave_event_callback (void *cls,
433 const struct GNUNET_TESTBED_EventInformation *event)
434{
435 struct RegisteredHostContext *rhc;
436 struct LCFContext *lcf;
437 struct GNUNET_CONFIGURATION_Handle *cfg;
438 struct GNUNET_TESTBED_Operation *old_op;
439
440 /* We currently only get here when working on RegisteredHostContexts and
441 LCFContexts */
442 GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
443 rhc = event->op_cls;
444 if (CLOSURE_TYPE_RHC == rhc->type)
445 {
446 GNUNET_assert (rhc->sub_op == event->op);
447 switch (rhc->state)
448 {
449 case RHC_GET_CFG:
450 cfg = event->details.operation_finished.generic;
451 old_op = rhc->sub_op;
452 rhc->state = RHC_LINK;
453 rhc->sub_op =
454 GNUNET_TESTBED_controller_link (rhc, rhc->gateway->controller,
455 rhc->reg_host, rhc->host, cfg,
456 GNUNET_NO);
457 GNUNET_TESTBED_operation_done (old_op);
458 break;
459 case RHC_LINK:
460 LOG_DEBUG ("OL: Linking controllers successfull\n");
461 GNUNET_TESTBED_operation_done (rhc->sub_op);
462 rhc->sub_op = NULL;
463 rhc->state = RHC_OL_CONNECT;
464 GST_process_next_focc (rhc);
465 break;
466 default:
467 GNUNET_assert (0);
468 }
469 return;
470 }
471 lcf = event->op_cls;
472 if (CLOSURE_TYPE_LCF == lcf->type)
473 {
474 GNUNET_assert (lcf->op == event->op);
475 GNUNET_assert (FINISHED == lcf->state);
476 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != lcf->timeout_task);
477 GNUNET_SCHEDULER_cancel (lcf->timeout_task);
478 if (NULL == event->details.operation_finished.emsg)
479 send_controller_link_response (lcf->client, lcf->operation_id,
480 GNUNET_TESTBED_host_get_cfg_
481 (GST_host_list[lcf->delegated_host_id]),
482 NULL);
483 else
484 send_controller_link_response (lcf->client, lcf->operation_id,
485 NULL,
486 event->details.operation_finished.emsg);
487 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
488 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
489 return;
490 }
491 GNUNET_assert (0);
492}
493
494
495/**
496 * Callback to signal successfull startup of the controller process
497 *
498 * @param cls the handle to the slave whose status is to be found here
499 * @param cfg the configuration with which the controller has been started;
500 * NULL if status is not GNUNET_OK
501 * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
502 * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
503 */
504static void
505slave_status_callback (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
506 int status)
507{
508 struct Slave *slave = cls;
509 struct LinkControllersContext *lcc;
510
511 lcc = slave->lcc;
512 if (GNUNET_SYSERR == status)
513 {
514 slave->controller_proc = NULL;
515 GST_slave_list[slave->host_id] = NULL;
516 GNUNET_free (slave);
517 slave = NULL;
518 LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected slave shutdown\n");
519 GNUNET_SCHEDULER_shutdown (); /* We too shutdown */
520 goto clean_lcc;
521 }
522 slave->controller =
523 GNUNET_TESTBED_controller_connect (cfg, GST_host_list[slave->host_id],
524 EVENT_MASK, &slave_event_callback,
525 slave);
526 if (NULL != slave->controller)
527 {
528 send_controller_link_response (lcc->client, lcc->operation_id, cfg, NULL);
529 }
530 else
531 {
532 send_controller_link_response (lcc->client, lcc->operation_id, NULL,
533 "Could not connect to delegated controller");
534 GNUNET_TESTBED_controller_stop (slave->controller_proc);
535 GST_slave_list[slave->host_id] = NULL;
536 GNUNET_free (slave);
537 slave = NULL;
538 }
539
540clean_lcc:
541 if (NULL != lcc)
542 {
543 if (NULL != lcc->client)
544 {
545 GNUNET_SERVER_receive_done (lcc->client, GNUNET_OK);
546 GNUNET_SERVER_client_drop (lcc->client);
547 lcc->client = NULL;
548 }
549 GNUNET_free (lcc);
550 }
551 if (NULL != slave)
552 slave->lcc = NULL;
553}
554
555
556/**
557 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
558 *
559 * @param cls NULL
560 * @param client identification of the client
561 * @param message the actual message
562 */
563void
564GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
565 const struct GNUNET_MessageHeader *message)
566{
567 const struct GNUNET_TESTBED_ControllerLinkRequest *msg;
568 struct GNUNET_CONFIGURATION_Handle *cfg;
569 struct LCFContextQueue *lcfq;
570 struct Route *route;
571 struct Route *new_route;
572 uint32_t delegated_host_id;
573 uint32_t slave_host_id;
574 uint16_t msize;
575
576 if (NULL == GST_context)
577 {
578 GNUNET_break (0);
579 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
580 return;
581 }
582 msize = ntohs (message->size);
583 if (sizeof (struct GNUNET_TESTBED_ControllerLinkRequest) >= msize)
584 {
585 GNUNET_break (0);
586 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
587 return;
588 }
589 msg = (const struct GNUNET_TESTBED_ControllerLinkRequest *) message;
590 delegated_host_id = ntohl (msg->delegated_host_id);
591 if (delegated_host_id == GST_context->host_id)
592 {
593 GNUNET_break (0);
594 LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
595 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
596 return;
597 }
598 if ((delegated_host_id >= GST_host_list_size) ||
599 (NULL == GST_host_list[delegated_host_id]))
600 {
601 LOG (GNUNET_ERROR_TYPE_WARNING,
602 "Delegated host %u not registered with us\n", delegated_host_id);
603 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
604 return;
605 }
606 slave_host_id = ntohl (msg->slave_host_id);
607 if ((slave_host_id >= GST_host_list_size) ||
608 (NULL == GST_host_list[slave_host_id]))
609 {
610 LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host %u not registered with us\n",
611 slave_host_id);
612 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
613 return;
614 }
615 if (slave_host_id == delegated_host_id)
616 {
617 LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
618 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
619 return;
620 }
621 cfg = GNUNET_TESTBED_extract_config_ (message); /* destroy cfg here or in lcfcontext */
622 if (NULL == cfg)
623 {
624 GNUNET_break (0); /* Configuration parsing error */
625 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
626 return;
627 }
628 if (slave_host_id == GST_context->host_id) /* Link from us */
629 {
630 struct Slave *slave;
631 struct LinkControllersContext *lcc;
632
633 if ((delegated_host_id < GST_slave_list_size) &&
634 (NULL != GST_slave_list[delegated_host_id]))
635 {
636 GNUNET_break (0);
637 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
638 return;
639 }
640 slave = GNUNET_malloc (sizeof (struct Slave));
641 slave->host_id = delegated_host_id;
642 slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100, GNUNET_NO);
643 slave_list_add (slave);
644 if (1 != msg->is_subordinate)
645 {
646 slave->controller =
647 GNUNET_TESTBED_controller_connect (cfg, GST_host_list[slave->host_id],
648 EVENT_MASK, &slave_event_callback,
649 slave);
650 if (NULL != slave->controller)
651 send_controller_link_response (client,
652 GNUNET_ntohll (msg->operation_id),
653 NULL,
654 NULL);
655 else
656 send_controller_link_response (client,
657 GNUNET_ntohll (msg->operation_id),
658 NULL,
659 "Could not connect to delegated controller");
660 GNUNET_SERVER_receive_done (client, GNUNET_OK);
661 return;
662 }
663 lcc = GNUNET_malloc (sizeof (struct LinkControllersContext));
664 lcc->operation_id = GNUNET_ntohll (msg->operation_id);
665 GNUNET_SERVER_client_keep (client);
666 lcc->client = client;
667 slave->lcc = lcc;
668 slave->controller_proc =
669 GNUNET_TESTBED_controller_start (GST_context->master_ip,
670 GST_host_list[slave->host_id], cfg,
671 &slave_status_callback, slave);
672 GNUNET_CONFIGURATION_destroy (cfg);
673 new_route = GNUNET_malloc (sizeof (struct Route));
674 new_route->dest = delegated_host_id;
675 new_route->thru = GST_context->host_id;
676 route_list_add (new_route);
677 return;
678 }
679
680 /* Route the request */
681 if (slave_host_id >= route_list_size)
682 {
683 LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
684 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
685 return;
686 }
687 lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
688 lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
689 lcfq->lcf->type = CLOSURE_TYPE_LCF;
690 lcfq->lcf->delegated_host_id = delegated_host_id;
691 lcfq->lcf->slave_host_id = slave_host_id;
692 route = GST_find_dest_route (slave_host_id);
693 GNUNET_assert (NULL != route); /* because we add routes carefully */
694 GNUNET_assert (route->dest < GST_slave_list_size);
695 GNUNET_assert (NULL != GST_slave_list[route->dest]);
696 lcfq->lcf->cfg = cfg;
697 lcfq->lcf->is_subordinate = msg->is_subordinate;
698 lcfq->lcf->state = INIT;
699 lcfq->lcf->operation_id = GNUNET_ntohll (msg->operation_id);
700 lcfq->lcf->gateway = GST_slave_list[route->dest];
701 GNUNET_SERVER_client_keep (client);
702 lcfq->lcf->client = client;
703 if (NULL == lcfq_head)
704 {
705 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
706 GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
707 lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq->lcf);
708 }
709 else
710 GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
711 /* FIXME: Adding a new route should happen after the controllers are linked
712 * successfully */
713 if (1 != msg->is_subordinate)
714 {
715 GNUNET_SERVER_receive_done (client, GNUNET_OK);
716 return;
717 }
718 if ((delegated_host_id < route_list_size) &&
719 (NULL != route_list[delegated_host_id]))
720 {
721 GNUNET_break_op (0); /* Are you trying to link delegated host twice
722 * with is subordinate flag set to GNUNET_YES? */
723 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
724 return;
725 }
726 new_route = GNUNET_malloc (sizeof (struct Route));
727 new_route->dest = delegated_host_id;
728 new_route->thru = route->dest;
729 route_list_add (new_route);
730 GNUNET_SERVER_receive_done (client, GNUNET_OK);
731}
732
733
734/**
735 * Cleans up the queue used for forwarding link controllers requests
736 */
737void
738GST_free_lcfq ()
739{
740 struct LCFContextQueue *lcfq;
741
742 if (NULL != lcfq_head)
743 {
744 if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
745 {
746 GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
747 lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
748 }
749 }
750 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
751 for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
752 {
753 GNUNET_SERVER_client_drop (lcfq->lcf->client);
754 GNUNET_assert (NULL != lcfq->lcf->cfg);
755 GNUNET_CONFIGURATION_destroy (lcfq->lcf->cfg);
756 GNUNET_free (lcfq->lcf);
757 GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
758 GNUNET_free (lcfq);
759 }
760}