aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-04-11 16:35:18 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-04-11 16:35:18 +0000
commit94b2f31f285e6483fbced750204f7464b16058e8 (patch)
tree890078fb43e5ff614bbb28dfff0105babd1f7ae5
parent2c1b69bdea307f298fe22c758a85822e684bd4ee (diff)
downloadgnunet-94b2f31f285e6483fbced750204f7464b16058e8.tar.gz
gnunet-94b2f31f285e6483fbced750204f7464b16058e8.zip
- towards on-demand controller linking
-rw-r--r--src/testbed/gnunet-service-testbed.c2
-rw-r--r--src/testbed/gnunet-service-testbed.h192
-rw-r--r--src/testbed/gnunet-service-testbed_links.c452
-rw-r--r--src/testbed/gnunet-service-testbed_links.h138
-rw-r--r--src/testbed/gnunet-service-testbed_oc.c106
5 files changed, 635 insertions, 255 deletions
diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c
index 25bded788..7864b0984 100644
--- a/src/testbed/gnunet-service-testbed.c
+++ b/src/testbed/gnunet-service-testbed.c
@@ -847,6 +847,8 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
847 GST_free_mctxq (); 847 GST_free_mctxq ();
848 GST_free_occq (); 848 GST_free_occq ();
849 GST_free_roccq (); 849 GST_free_roccq ();
850 GST_free_nccq ();
851 GST_neighbour_list_clean();
850 /* Clear peer list */ 852 /* Clear peer list */
851 GST_destroy_peers (); 853 GST_destroy_peers ();
852 /* Clear host list */ 854 /* Clear host list */
diff --git a/src/testbed/gnunet-service-testbed.h b/src/testbed/gnunet-service-testbed.h
index 2a410a850..b17c3d781 100644
--- a/src/testbed/gnunet-service-testbed.h
+++ b/src/testbed/gnunet-service-testbed.h
@@ -35,6 +35,7 @@
35#include "testbed_api_operations.h" 35#include "testbed_api_operations.h"
36#include "testbed_api_hosts.h" 36#include "testbed_api_hosts.h"
37#include "gnunet_testing_lib.h" 37#include "gnunet_testing_lib.h"
38#include "gnunet-service-testbed_links.h"
38 39
39 40
40/** 41/**
@@ -171,55 +172,6 @@ struct LinkControllersContext
171 172
172 173
173/** 174/**
174 * Structure representing a connected(directly-linked) controller
175 */
176struct Slave
177{
178 /**
179 * The controller process handle if we had started the controller
180 */
181 struct GNUNET_TESTBED_ControllerProc *controller_proc;
182
183 /**
184 * The controller handle
185 */
186 struct GNUNET_TESTBED_Controller *controller;
187
188 /**
189 * handle to lcc which is associated with this slave startup. Should be set to
190 * NULL when the slave has successfully started up
191 */
192 struct LinkControllersContext *lcc;
193
194 /**
195 * Head of the host registration DLL
196 */
197 struct HostRegistration *hr_dll_head;
198
199 /**
200 * Tail of the host registration DLL
201 */
202 struct HostRegistration *hr_dll_tail;
203
204 /**
205 * The current host registration handle
206 */
207 struct GNUNET_TESTBED_HostRegistrationHandle *rhandle;
208
209 /**
210 * Hashmap to hold Registered host contexts
211 */
212 struct GNUNET_CONTAINER_MultiHashMap *reghost_map;
213
214 /**
215 * The id of the host this controller is running on
216 */
217 uint32_t host_id;
218
219};
220
221
222/**
223 * A peer 175 * A peer
224 */ 176 */
225 177
@@ -487,119 +439,6 @@ struct RegisteredHostContext
487 439
488 440
489/** 441/**
490 * States of LCFContext
491 */
492enum LCFContextState
493{
494 /**
495 * The Context has been initialized; Nothing has been done on it
496 */
497 INIT,
498
499 /**
500 * Delegated host has been registered at the forwarding controller
501 */
502 DELEGATED_HOST_REGISTERED,
503
504 /**
505 * The slave host has been registred at the forwarding controller
506 */
507 SLAVE_HOST_REGISTERED,
508
509 /**
510 * The context has been finished (may have error)
511 */
512 FINISHED
513};
514
515
516/**
517 * Link controllers request forwarding context
518 */
519struct LCFContext
520{
521 /**
522 * The type of this data structure. Set this to CLOSURE_TYPE_LCF
523 */
524 enum ClosureType type;
525
526 /**
527 * The gateway which will pass the link message to delegated host
528 */
529 struct Slave *gateway;
530
531 /**
532 * The client which has asked to perform this operation
533 */
534 struct GNUNET_SERVER_Client *client;
535
536 /**
537 * Handle for operations which are forwarded while linking controllers
538 */
539 struct GNUNET_TESTBED_Operation *op;
540
541 /**
542 * The configuration which has to be either used as a template while starting
543 * the delegated controller or for connecting to the delegated controller
544 */
545 struct GNUNET_CONFIGURATION_Handle *cfg;
546
547 /**
548 * The timeout task
549 */
550 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
551
552 /**
553 * The id of the operation which created this context
554 */
555 uint64_t operation_id;
556
557 /**
558 * should the slave controller start the delegated controller?
559 */
560 int is_subordinate;
561
562 /**
563 * The state of this context
564 */
565 enum LCFContextState state;
566
567 /**
568 * The delegated host
569 */
570 uint32_t delegated_host_id;
571
572 /**
573 * The slave host
574 */
575 uint32_t slave_host_id;
576
577};
578
579
580/**
581 * Structure of a queue entry in LCFContext request queue
582 */
583struct LCFContextQueue
584{
585 /**
586 * The LCFContext
587 */
588 struct LCFContext *lcf;
589
590 /**
591 * Head prt for DLL
592 */
593 struct LCFContextQueue *next;
594
595 /**
596 * Tail ptr for DLL
597 */
598 struct LCFContextQueue *prev;
599};
600
601
602/**
603 * Context data for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS handler 442 * Context data for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS handler
604 */ 443 */
605struct HandlerContext_ShutdownPeers 444struct HandlerContext_ShutdownPeers
@@ -649,11 +488,6 @@ extern struct Peer **GST_peer_list;
649extern struct GNUNET_TESTBED_Host **GST_host_list; 488extern struct GNUNET_TESTBED_Host **GST_host_list;
650 489
651/** 490/**
652 * A list of directly linked neighbours
653 */
654extern struct Slave **GST_slave_list;
655
656/**
657 * Operation queue for open file descriptors 491 * Operation queue for open file descriptors
658 */ 492 */
659extern struct OperationQueue *GST_opq_openfds; 493extern struct OperationQueue *GST_opq_openfds;
@@ -674,11 +508,6 @@ extern unsigned int GST_peer_list_size;
674extern unsigned int GST_host_list_size; 508extern unsigned int GST_host_list_size;
675 509
676/** 510/**
677 * The size of directly linked neighbours list
678 */
679extern unsigned int GST_slave_list_size;
680
681/**
682 * The directory where to store load statistics data 511 * The directory where to store load statistics data
683 */ 512 */
684extern char *GST_stats_dir; 513extern char *GST_stats_dir;
@@ -748,18 +577,6 @@ GST_find_dest_route (uint32_t host_id);
748 577
749 578
750/** 579/**
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/**
763 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages 580 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
764 * 581 *
765 * @param cls NULL 582 * @param cls NULL
@@ -957,13 +774,6 @@ GST_route_list_clear ();
957 774
958 775
959/** 776/**
960 * Cleans up the slave list
961 */
962void
963GST_slave_list_clear ();
964
965
966/**
967 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext 777 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
968 * 778 *
969 * @param rhc the RegisteredHostContext 779 * @param rhc the RegisteredHostContext
diff --git a/src/testbed/gnunet-service-testbed_links.c b/src/testbed/gnunet-service-testbed_links.c
index d09e4aff6..ae984e331 100644
--- a/src/testbed/gnunet-service-testbed_links.c
+++ b/src/testbed/gnunet-service-testbed_links.c
@@ -19,18 +19,199 @@
19*/ 19*/
20 20
21/** 21/**
22 * @file testbed/gnunet-service-testbed.c 22 * @file testbed/gnunet-service-testbed_links.c
23 * @brief implementation of the TESTBED service 23 * @brief TESTBED service components that deals with starting slave controllers
24 * and establishing lateral links between controllers
24 * @author Sree Harsha Totakura 25 * @author Sree Harsha Totakura
25 */ 26 */
26 27
27#include "gnunet-service-testbed.h" 28#include "gnunet-service-testbed.h"
28 29
29/** 30/**
31 * Redefine LOG with a changed log component string
32 */
33#ifdef LOG
34#undef LOG
35#endif
36#define LOG(kind,...) \
37 GNUNET_log_from (kind, "testbed-links", __VA_ARGS__)
38
39/**
30 * The event mask for the events we listen from sub-controllers 40 * The event mask for the events we listen from sub-controllers
31 */ 41 */
32#define EVENT_MASK (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED) 42#define EVENT_MASK (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED)
33 43
44
45/**
46 * States of LCFContext
47 */
48enum LCFContextState
49{
50 /**
51 * The Context has been initialized; Nothing has been done on it
52 */
53 INIT,
54
55 /**
56 * Delegated host has been registered at the forwarding controller
57 */
58 DELEGATED_HOST_REGISTERED,
59
60 /**
61 * The slave host has been registred at the forwarding controller
62 */
63 SLAVE_HOST_REGISTERED,
64
65 /**
66 * The context has been finished (may have error)
67 */
68 FINISHED
69};
70
71
72/**
73 * Link controllers request forwarding context
74 */
75struct LCFContext
76{
77 /**
78 * The type of this data structure. Set this to CLOSURE_TYPE_LCF
79 */
80 enum ClosureType type;
81
82 /**
83 * The gateway which will pass the link message to delegated host
84 */
85 struct Slave *gateway;
86
87 /**
88 * The client which has asked to perform this operation
89 */
90 struct GNUNET_SERVER_Client *client;
91
92 /**
93 * Handle for operations which are forwarded while linking controllers
94 */
95 struct GNUNET_TESTBED_Operation *op;
96
97 /**
98 * The configuration which has to be either used as a template while starting
99 * the delegated controller or for connecting to the delegated controller
100 */
101 struct GNUNET_CONFIGURATION_Handle *cfg;
102
103 /**
104 * The timeout task
105 */
106 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
107
108 /**
109 * The id of the operation which created this context
110 */
111 uint64_t operation_id;
112
113 /**
114 * should the slave controller start the delegated controller?
115 */
116 int is_subordinate;
117
118 /**
119 * The state of this context
120 */
121 enum LCFContextState state;
122
123 /**
124 * The delegated host
125 */
126 uint32_t delegated_host_id;
127
128 /**
129 * The slave host
130 */
131 uint32_t slave_host_id;
132
133};
134
135
136/**
137 * Structure of a queue entry in LCFContext request queue
138 */
139struct LCFContextQueue
140{
141 /**
142 * The LCFContext
143 */
144 struct LCFContext *lcf;
145
146 /**
147 * Head prt for DLL
148 */
149 struct LCFContextQueue *next;
150
151 /**
152 * Tail ptr for DLL
153 */
154 struct LCFContextQueue *prev;
155};
156
157struct NeighbourConnectNotification
158{
159 struct NeighbourConnectNotification *next;
160 struct NeighbourConnectNotification *prev;
161 struct Neighbour *n;
162 GST_NeigbourConnectNotifyCallback cb;
163 void *cb_cls;
164};
165
166/**
167 * A connected controller which is not our child
168 */
169struct Neighbour
170{
171 /**
172 * The controller handle
173 */
174 struct GNUNET_TESTBED_Controller *controller;
175
176 /**
177 * Operation handle for opening a lateral connection to another controller.
178 * Will be NULL if the slave controller is started by this controller
179 */
180 struct GNUNET_TESTBED_Operation *conn_op;
181
182 struct NeighbourConnectNotification *nl_head;
183
184 struct NeighbourConnectNotification *nl_tail;
185
186 GNUNET_SCHEDULER_TaskIdentifier notify_task;
187
188 unsigned int reference_cnt;
189
190 /**
191 * The id of the host this controller is running on
192 */
193 uint32_t host_id;
194
195 int8_t inactive;
196};
197
198static struct Neighbour **neighbour_list;
199static unsigned int neighbour_list_size;
200
201struct NeighbourConnectCtxt
202{
203 struct NeighbourConnectCtxt *next;
204 struct NeighbourConnectCtxt *prev;
205 struct Neighbour *n;
206 struct GNUNET_SERVER_Client *client;
207 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
208 struct NeighbourConnectNotification *nh;
209 uint64_t op_id;
210};
211
212struct NeighbourConnectCtxt *ncc_head;
213struct NeighbourConnectCtxt *ncc_tail;
214
34/** 215/**
35 * A list of directly linked neighbours 216 * A list of directly linked neighbours
36 */ 217 */
@@ -97,6 +278,15 @@ route_list_add (struct Route *route)
97 route_list[route->dest] = route; 278 route_list[route->dest] = route;
98} 279}
99 280
281static void
282neighbour_list_add (struct Neighbour *n)
283{
284 if (n->host_id >= neighbour_list_size)
285 GST_array_grow_large_enough (neighbour_list, neighbour_list_size, n->host_id);
286 GNUNET_assert (NULL == neighbour_list[n->host_id]);
287 neighbour_list[n->host_id] = n;
288}
289
100 290
101/** 291/**
102 * Cleans up the route list 292 * Cleans up the route list
@@ -425,7 +615,7 @@ lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
425/** 615/**
426 * Callback for event from slave controllers 616 * Callback for event from slave controllers
427 * 617 *
428 * @param cls struct Slave * 618 * @param cls NULL
429 * @param event information about the event 619 * @param event information about the event
430 */ 620 */
431static void 621static void
@@ -491,6 +681,9 @@ slave_event_callback (void *cls,
491 GNUNET_assert (0); 681 GNUNET_assert (0);
492} 682}
493 683
684static void
685slave_status_callback (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
686 int status);
494 687
495/** 688/**
496 * Callback to signal successfull startup of the controller process 689 * Callback to signal successfull startup of the controller process
@@ -552,6 +745,201 @@ clean_lcc:
552 slave->lcc = NULL; 745 slave->lcc = NULL;
553} 746}
554 747
748static void
749neighbour_connect_notify_task (void *cls,
750 const struct GNUNET_SCHEDULER_TaskContext *tc);
751
752static void
753trigger_notifications (struct Neighbour *n)
754{
755 GNUNET_assert (NULL != n->conn_op);
756 if (NULL == n->nl_head)
757 return;
758 if (NULL == n->controller)
759 return;
760 if (GNUNET_SCHEDULER_NO_TASK != n->notify_task)
761 return;
762 n->notify_task =
763 GNUNET_SCHEDULER_add_now (&neighbour_connect_notify_task, n->nl_head);
764}
765
766static void
767neighbour_connect_notify_task (void *cls,
768 const struct GNUNET_SCHEDULER_TaskContext *tc)
769{
770 struct NeighbourConnectNotification *h = cls;
771 struct Neighbour *n;
772
773 n = h->n;
774 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != n->notify_task);
775 n->notify_task = GNUNET_SCHEDULER_NO_TASK;
776 GNUNET_assert (NULL != n->controller);
777 GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h);
778 trigger_notifications (n);
779 if ((0 == n->reference_cnt) && (1 == n->inactive))
780 {
781 GNUNET_TESTBED_operation_activate_ (n->conn_op);
782 n->inactive = 0;
783 }
784 n->reference_cnt++;
785 h->cb (h->cb_cls, n->controller);
786}
787
788static void
789opstart_neighbour_conn (void *cls)
790{
791 struct Neighbour *n = cls;
792
793 GNUNET_assert (NULL != n->conn_op);
794 GNUNET_assert (NULL == n->controller);
795 LOG_DEBUG ("Opening connection to controller on host %u\n", n->host_id);
796 n->controller = GNUNET_TESTBED_controller_connect (GST_host_list[n->host_id],
797 EVENT_MASK,
798 &slave_event_callback,
799 NULL);
800 trigger_notifications (n);
801}
802
803static void
804oprelease_neighbour_conn (void *cls)
805{
806 struct Neighbour *n = cls;
807
808 GNUNET_assert (0 == n->reference_cnt);
809 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == n->notify_task);
810 GNUNET_assert (NULL == n->nl_head);
811 LOG_DEBUG ("Closing connection to controller on host %u\n", n->host_id);
812 GNUNET_TESTBED_controller_disconnect (n->controller);
813 n->controller = NULL;
814 n->conn_op = NULL;
815}
816
817struct NeighbourConnectNotification *
818GST_neighbour_get_connection (struct Neighbour *n,
819 GST_NeigbourConnectNotifyCallback cb,
820 void *cb_cls)
821{
822 struct NeighbourConnectNotification *h;
823
824 GNUNET_assert (NULL != cb);
825 LOG_DEBUG ("Attempting to get connection to controller on host %u\n",
826 n->host_id);
827 h = GNUNET_malloc (sizeof (struct NeighbourConnectNotification));
828 h->n = n;
829 h->cb = cb;
830 h->cb_cls = cb_cls;
831 GNUNET_CONTAINER_DLL_insert_tail (n->nl_head, n->nl_tail, h);
832 if (NULL == n->conn_op)
833 {
834 GNUNET_assert (NULL == n->controller);
835 n->conn_op = GNUNET_TESTBED_operation_create_ (n, &opstart_neighbour_conn,
836 &oprelease_neighbour_conn);
837 GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, n->conn_op);
838 GNUNET_TESTBED_operation_begin_wait_ (n->conn_op);
839 return h;
840 }
841 trigger_notifications (n);
842 return h;
843}
844
845void
846GST_neighbour_get_connection_cancel (struct NeighbourConnectNotification *h)
847{
848 struct Neighbour *n;
849
850 n = h->n;
851 if ((h == n->nl_head) && (GNUNET_SCHEDULER_NO_TASK != n->notify_task))
852 {
853 GNUNET_SCHEDULER_cancel (n->notify_task);
854 n->notify_task = GNUNET_SCHEDULER_NO_TASK;
855 }
856 GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h);
857 GNUNET_free (h);
858}
859
860void
861GST_neighbour_release_connection (struct Neighbour *n)
862{
863 GNUNET_assert (0 == n->inactive);
864 GNUNET_assert (0 < n->reference_cnt);
865 n->reference_cnt--;
866 if (0 == n->reference_cnt)
867 {
868 GNUNET_TESTBED_operation_inactivate_ (n->conn_op);
869 n->inactive = 1;
870 }
871}
872
873static void
874cleanup_ncc (struct NeighbourConnectCtxt *ncc)
875{
876 if (NULL != ncc->nh)
877 GST_neighbour_get_connection_cancel (ncc->nh);
878 if (GNUNET_SCHEDULER_NO_TASK != ncc->timeout_task)
879 GNUNET_SCHEDULER_cancel (ncc->timeout_task);
880 GNUNET_SERVER_client_drop (ncc->client);
881 GNUNET_CONTAINER_DLL_remove (ncc_head, ncc_tail, ncc);
882 GNUNET_free (ncc);
883}
884
885void
886GST_neighbour_list_clean()
887{
888 struct Neighbour *n;
889 unsigned int id;
890
891 for (id = 0; id < neighbour_list_size; id++)
892 {
893 if (NULL == (n = neighbour_list[id]))
894 continue;
895 if (NULL != n->conn_op)
896 GNUNET_TESTBED_operation_release_ (n->conn_op);
897 GNUNET_free (n);
898 neighbour_list[id] = NULL;
899 }
900 GNUNET_free_non_null (neighbour_list);
901}
902
903struct Neighbour *
904GST_get_neighbour (uint32_t id)
905{
906 if (neighbour_list_size <= id)
907 return NULL;
908 else
909 return neighbour_list[id];
910}
911
912void
913GST_free_nccq ()
914{
915 while (NULL != ncc_head)
916 cleanup_ncc (ncc_head);
917}
918
919static void
920timeout_neighbour_connect (void *cls,
921 const struct GNUNET_SCHEDULER_TaskContext *tc)
922{
923 struct NeighbourConnectCtxt *ncc = cls;
924
925 ncc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
926 send_controller_link_response (ncc->client, ncc->op_id, NULL,
927 "Could not connect to delegated controller");
928 cleanup_ncc (ncc);
929}
930
931static void
932neighbour_connect_cb (void *cls, struct GNUNET_TESTBED_Controller *c)
933{
934 struct NeighbourConnectCtxt *ncc = cls;
935
936 GNUNET_SCHEDULER_cancel (ncc->timeout_task);
937 ncc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
938 ncc->nh = NULL;
939 GST_neighbour_release_connection (ncc->n);
940 send_controller_link_response (ncc->client, ncc->op_id, NULL, NULL);
941 cleanup_ncc (ncc);
942}
555 943
556/** 944/**
557 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message 945 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
@@ -569,6 +957,7 @@ GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
569 struct LCFContextQueue *lcfq; 957 struct LCFContextQueue *lcfq;
570 struct Route *route; 958 struct Route *route;
571 struct Route *new_route; 959 struct Route *new_route;
960 uint64_t op_id;
572 uint32_t delegated_host_id; 961 uint32_t delegated_host_id;
573 uint32_t slave_host_id; 962 uint32_t slave_host_id;
574 uint16_t msize; 963 uint16_t msize;
@@ -625,11 +1014,43 @@ GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
625 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 1014 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
626 return; 1015 return;
627 } 1016 }
1017 op_id = GNUNET_ntohll (msg->operation_id);
628 if (slave_host_id == GST_context->host_id) /* Link from us */ 1018 if (slave_host_id == GST_context->host_id) /* Link from us */
629 { 1019 {
630 struct Slave *slave; 1020 struct Slave *slave;
631 struct LinkControllersContext *lcc; 1021 struct LinkControllersContext *lcc;
632 1022
1023
1024 if (1 != msg->is_subordinate)
1025 {
1026 struct Neighbour *n;
1027 struct NeighbourConnectCtxt *ncc;
1028
1029 if ((delegated_host_id < neighbour_list_size) &&
1030 (NULL != neighbour_list[delegated_host_id]))
1031 {
1032 GNUNET_break (0);
1033 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1034 return;
1035 }
1036 LOG_DEBUG ("Received request to establish a link to host %u\n",
1037 delegated_host_id);
1038 n = GNUNET_malloc (sizeof (struct Neighbour));
1039 n->host_id = delegated_host_id;
1040 neighbour_list_add (n); /* just add; connect on-demand */
1041 ncc = GNUNET_malloc (sizeof (struct NeighbourConnectCtxt));
1042 ncc->n = n;
1043 ncc->op_id = op_id;
1044 ncc->client = client;
1045 GNUNET_SERVER_client_keep (client);
1046 ncc->nh = GST_neighbour_get_connection (n, neighbour_connect_cb, ncc);
1047 ncc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout,
1048 &timeout_neighbour_connect,
1049 ncc);
1050 GNUNET_CONTAINER_DLL_insert_tail (ncc_head, ncc_tail, ncc);
1051 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1052 return;
1053 }
633 if ((delegated_host_id < GST_slave_list_size) && 1054 if ((delegated_host_id < GST_slave_list_size) &&
634 (NULL != GST_slave_list[delegated_host_id])) 1055 (NULL != GST_slave_list[delegated_host_id]))
635 { 1056 {
@@ -637,31 +1058,14 @@ GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
637 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 1058 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
638 return; 1059 return;
639 } 1060 }
1061 LOG_DEBUG ("Received request to start and establish a link to host %u\n",
1062 delegated_host_id);
640 slave = GNUNET_malloc (sizeof (struct Slave)); 1063 slave = GNUNET_malloc (sizeof (struct Slave));
641 slave->host_id = delegated_host_id; 1064 slave->host_id = delegated_host_id;
642 slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100, GNUNET_NO); 1065 slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100, GNUNET_NO);
643 slave_list_add (slave); 1066 slave_list_add (slave);
644 if (1 != msg->is_subordinate)
645 {
646 slave->controller =
647 GNUNET_TESTBED_controller_connect (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)); 1067 lcc = GNUNET_malloc (sizeof (struct LinkControllersContext));
664 lcc->operation_id = GNUNET_ntohll (msg->operation_id); 1068 lcc->operation_id = op_id;
665 GNUNET_SERVER_client_keep (client); 1069 GNUNET_SERVER_client_keep (client);
666 lcc->client = client; 1070 lcc->client = client;
667 slave->lcc = lcc; 1071 slave->lcc = lcc;
@@ -696,7 +1100,7 @@ GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
696 lcfq->lcf->cfg = cfg; 1100 lcfq->lcf->cfg = cfg;
697 lcfq->lcf->is_subordinate = msg->is_subordinate; 1101 lcfq->lcf->is_subordinate = msg->is_subordinate;
698 lcfq->lcf->state = INIT; 1102 lcfq->lcf->state = INIT;
699 lcfq->lcf->operation_id = GNUNET_ntohll (msg->operation_id); 1103 lcfq->lcf->operation_id = op_id;
700 lcfq->lcf->gateway = GST_slave_list[route->dest]; 1104 lcfq->lcf->gateway = GST_slave_list[route->dest];
701 GNUNET_SERVER_client_keep (client); 1105 GNUNET_SERVER_client_keep (client);
702 lcfq->lcf->client = client; 1106 lcfq->lcf->client = client;
diff --git a/src/testbed/gnunet-service-testbed_links.h b/src/testbed/gnunet-service-testbed_links.h
new file mode 100644
index 000000000..b6a38c09e
--- /dev/null
+++ b/src/testbed/gnunet-service-testbed_links.h
@@ -0,0 +1,138 @@
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_links.h
23 * @brief TESTBED service components that deals with starting slave controllers
24 * and establishing lateral links between controllers
25 * @author Sree Harsha Totakura
26 */
27
28struct Neighbour;
29
30
31/**
32 * Structure representing a connected(directly-linked) controller
33 */
34struct Slave
35{
36 /**
37 * The controller process handle if we had started the controller
38 */
39 struct GNUNET_TESTBED_ControllerProc *controller_proc;
40
41 /**
42 * The controller handle
43 */
44 struct GNUNET_TESTBED_Controller *controller;
45
46 /**
47 * handle to lcc which is associated with this slave startup. Should be set to
48 * NULL when the slave has successfully started up
49 */
50 struct LinkControllersContext *lcc;
51
52 /**
53 * Head of the host registration DLL
54 */
55 struct HostRegistration *hr_dll_head;
56
57 /**
58 * Tail of the host registration DLL
59 */
60 struct HostRegistration *hr_dll_tail;
61
62 /**
63 * The current host registration handle
64 */
65 struct GNUNET_TESTBED_HostRegistrationHandle *rhandle;
66
67 /**
68 * Hashmap to hold Registered host contexts
69 */
70 struct GNUNET_CONTAINER_MultiHashMap *reghost_map;
71
72 /**
73 * Operation handle for opening a lateral connection to another controller.
74 * Will be NULL if the slave controller is started by this controller
75 */
76 struct GNUNET_TESTBED_Operation *conn_op;
77
78 /**
79 * The id of the host this controller is running on
80 */
81 uint32_t host_id;
82
83};
84
85/**
86 * A list of directly linked neighbours
87 */
88extern struct Slave **GST_slave_list;
89
90/**
91 * The size of directly linked neighbours list
92 */
93extern unsigned int GST_slave_list_size;
94
95void
96GST_neighbour_list_clean();
97
98struct Neighbour *
99GST_get_neighbour (uint32_t id);
100
101void
102GST_free_nccq ();
103
104struct NeighbourConnectNotification;
105
106typedef void (*GST_NeigbourConnectNotifyCallback) (void *cls,
107 struct
108 GNUNET_TESTBED_Controller
109 *controller);
110
111struct NeighbourConnectNotification *
112GST_neighbour_get_connection (struct Neighbour *n,
113 GST_NeigbourConnectNotifyCallback cb,
114 void *cb_cls);
115
116void
117GST_neighbour_get_connection_cancel (struct NeighbourConnectNotification *h);
118
119void
120GST_neighbour_release_connection (struct Neighbour *n);
121
122/**
123 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
124 *
125 * @param cls NULL
126 * @param client identification of the client
127 * @param message the actual message
128 */
129void
130GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
131 const struct GNUNET_MessageHeader *message);
132
133
134/**
135 * Cleans up the slave list
136 */
137void
138GST_slave_list_clear ();
diff --git a/src/testbed/gnunet-service-testbed_oc.c b/src/testbed/gnunet-service-testbed_oc.c
index 07a9fd0f0..d27c2bbf7 100644
--- a/src/testbed/gnunet-service-testbed_oc.c
+++ b/src/testbed/gnunet-service-testbed_oc.c
@@ -150,9 +150,14 @@ struct OverlayConnectContext
150 struct OperationContext *opc; 150 struct OperationContext *opc;
151 151
152 /** 152 /**
153 * Controller of peer 2; NULL if the peer is a local peer 153 * Controller of peer 2; NULL if the peer is a local peer or until the
154 * connection to the controller is established
154 */ 155 */
155 struct GNUNET_TESTBED_Controller *peer2_controller; 156 struct GNUNET_TESTBED_Controller *p2c;
157
158 struct NeighbourConnectNotification *p2_ncn;
159
160 struct Neighbour *p2n;
156 161
157 /** 162 /**
158 * The transport TryConnectContext. This will be NULL if the second peer is a 163 * The transport TryConnectContext. This will be NULL if the second peer is a
@@ -418,16 +423,23 @@ cleanup_occ (struct OverlayConnectContext *occ)
418 GST_cache_get_handle_done (occ->cgh_p1th); 423 GST_cache_get_handle_done (occ->cgh_p1th);
419 if (NULL != occ->tcc.cgh_th) 424 if (NULL != occ->tcc.cgh_th)
420 GST_cache_get_handle_done (occ->tcc.cgh_th); 425 GST_cache_get_handle_done (occ->tcc.cgh_th);
426 if (NULL != occ->p2n)
427 {
428 if (NULL != occ->p2_ncn)
429 GST_neighbour_get_connection_cancel (occ->p2_ncn);
430 if (NULL != occ->p2c)
431 GST_neighbour_release_connection (occ->p2n);
432 }
421 GNUNET_assert (NULL != GST_peer_list); 433 GNUNET_assert (NULL != GST_peer_list);
422 GNUNET_assert (occ->peer->reference_cnt > 0); 434 GNUNET_assert (occ->peer->reference_cnt > 0);
423 occ->peer->reference_cnt--; 435 occ->peer->reference_cnt--;
424 if ( (GNUNET_YES == occ->peer->destroy_flag) && 436 if ( (GNUNET_YES == occ->peer->destroy_flag) &&
425 (0 == occ->peer->reference_cnt) ) 437 (0 == occ->peer->reference_cnt) )
426 GST_destroy_peer (occ->peer); 438 GST_destroy_peer (occ->peer);
427 if (NULL == occ->peer2_controller) 439 if ( (occ->other_peer_id < GST_peer_list_size)
440 && (NULL != (other_peer = GST_peer_list[occ->other_peer_id]))
441 && (GNUNET_YES != other_peer->is_remote) )
428 { 442 {
429 other_peer = GST_peer_list[occ->other_peer_id];
430 GNUNET_assert (NULL != other_peer);
431 GNUNET_assert (other_peer->reference_cnt > 0); 443 GNUNET_assert (other_peer->reference_cnt > 0);
432 other_peer->reference_cnt--; 444 other_peer->reference_cnt--;
433 if ( (GNUNET_YES == other_peer->destroy_flag) && 445 if ( (GNUNET_YES == other_peer->destroy_flag) &&
@@ -675,7 +687,7 @@ send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
675 return; 687 return;
676 GNUNET_assert (NULL != occ->hello); 688 GNUNET_assert (NULL != occ->hello);
677 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); 689 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
678 if (NULL != occ->peer2_controller) 690 if (NULL != occ->p2c)
679 { 691 {
680 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg; 692 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
681 uint16_t msize; 693 uint16_t msize;
@@ -697,7 +709,7 @@ send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
697 (void) memcpy (&msg->peer_identity, &occ->peer_identity, 709 (void) memcpy (&msg->peer_identity, &occ->peer_identity,
698 sizeof (struct GNUNET_PeerIdentity)); 710 sizeof (struct GNUNET_PeerIdentity));
699 memcpy (msg->hello, occ->hello, hello_size); 711 memcpy (msg->hello, occ->hello, hello_size);
700 GNUNET_TESTBED_queue_message_ (occ->peer2_controller, &msg->header); 712 GNUNET_TESTBED_queue_message_ (occ->p2c, &msg->header);
701 } 713 }
702 else 714 else
703 { 715 {
@@ -767,7 +779,7 @@ p2_transport_connect (struct OverlayConnectContext *occ)
767 GNUNET_assert (NULL == occ->ghh); 779 GNUNET_assert (NULL == occ->ghh);
768 GNUNET_assert (NULL == occ->p1th_); 780 GNUNET_assert (NULL == occ->p1th_);
769 GNUNET_assert (NULL == occ->cgh_p1th); 781 GNUNET_assert (NULL == occ->cgh_p1th);
770 if (NULL == occ->peer2_controller) 782 if (NULL == occ->p2c)
771 { 783 {
772 GNUNET_assert (NULL != GST_peer_list[occ->other_peer_id]); 784 GNUNET_assert (NULL != GST_peer_list[occ->other_peer_id]);
773 occ->tcc.cgh_th = 785 occ->tcc.cgh_th =
@@ -1069,6 +1081,31 @@ hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1069 return hash; 1081 return hash;
1070} 1082}
1071 1083
1084static void
1085p2_controller_connect_cb (void *cls, struct GNUNET_TESTBED_Controller *c)
1086{
1087 struct OverlayConnectContext *occ = cls;
1088 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1089
1090 occ->p2_ncn = NULL;
1091 occ->p2c = c;
1092 cmsg.header.size =
1093 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1094 cmsg.header.type =
1095 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION);
1096 cmsg.peer_id = htonl (occ->other_peer_id);
1097 cmsg.operation_id = GNUNET_htonll (occ->op_id);
1098 occ->opc =
1099 GNUNET_TESTBED_forward_operation_msg_ (occ->p2c,
1100 occ->op_id, &cmsg.header,
1101 &overlay_connect_get_config,
1102 occ);
1103 GNUNET_free_non_null (occ->emsg);
1104 GNUNET_asprintf (&occ->emsg,
1105 "0x%llx: Timeout while getting peer identity of peer "
1106 "with id: %u", occ->op_id, occ->other_peer_id);
1107}
1108
1072 1109
1073/** 1110/**
1074 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages 1111 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
@@ -1084,7 +1121,7 @@ GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
1084 const struct GNUNET_TESTBED_OverlayConnectMessage *msg; 1121 const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1085 struct Peer *peer; 1122 struct Peer *peer;
1086 struct OverlayConnectContext *occ; 1123 struct OverlayConnectContext *occ;
1087 struct GNUNET_TESTBED_Controller *peer2_controller; 1124 struct GNUNET_TESTBED_Controller *p2c;
1088 uint64_t operation_id; 1125 uint64_t operation_id;
1089 uint32_t p1; 1126 uint32_t p1;
1090 uint32_t p2; 1127 uint32_t p2;
@@ -1225,23 +1262,17 @@ GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
1225 return; 1262 return;
1226 } 1263 }
1227 1264
1228 peer2_controller = NULL; 1265 struct Neighbour *p2n;
1266 p2n = NULL;
1267 p2c = NULL;
1229 if ((p2 >= GST_peer_list_size) || (NULL == GST_peer_list[p2])) 1268 if ((p2 >= GST_peer_list_size) || (NULL == GST_peer_list[p2]))
1230 { 1269 {
1231 if ((peer2_host_id >= GST_slave_list_size) || 1270 if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
1232 (NULL == GST_slave_list[peer2_host_id]))
1233 { 1271 {
1234 GNUNET_break (0); 1272 GNUNET_break (0);
1235 LOG (GNUNET_ERROR_TYPE_WARNING, 1273 LOG (GNUNET_ERROR_TYPE_WARNING,
1236 "0x%llx: Configuration of peer2's controller missing for connecting peers" 1274 "0x%llx: Peer %u's host not in our neighbours list\n",
1237 "%u and %u\n", operation_id, p1, p2); 1275 operation_id, p2);
1238 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1239 return;
1240 }
1241 peer2_controller = GST_slave_list[peer2_host_id]->controller;
1242 if (NULL == peer2_controller)
1243 {
1244 GNUNET_break (0); /* What's going on? */
1245 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 1276 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1246 return; 1277 return;
1247 } 1278 }
@@ -1249,7 +1280,7 @@ GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
1249 else 1280 else
1250 { 1281 {
1251 if (GNUNET_YES == GST_peer_list[p2]->is_remote) 1282 if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1252 peer2_controller = GST_peer_list[p2]->details.remote.slave->controller; 1283 p2c = GST_peer_list[p2]->details.remote.slave->controller;
1253 } 1284 }
1254 occ = GNUNET_malloc (sizeof (struct OverlayConnectContext)); 1285 occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
1255 GNUNET_CONTAINER_DLL_insert_tail (occq_head, occq_tail, occ); 1286 GNUNET_CONTAINER_DLL_insert_tail (occq_head, occq_tail, occ);
@@ -1258,30 +1289,25 @@ GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
1258 occ->other_peer_id = p2; 1289 occ->other_peer_id = p2;
1259 GST_peer_list[p1]->reference_cnt++; 1290 GST_peer_list[p1]->reference_cnt++;
1260 occ->peer = GST_peer_list[p1]; 1291 occ->peer = GST_peer_list[p1];
1261 occ->op_id = GNUNET_ntohll (msg->operation_id); 1292 occ->op_id = operation_id;
1262 occ->peer2_controller = peer2_controller; 1293 occ->p2n = p2n;
1263 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->timeout_task); 1294 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->timeout_task);
1264 occ->timeout_task = 1295 occ->timeout_task =
1265 GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_overlay_connect, occ); 1296 GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_overlay_connect, occ);
1266 /* Get the identity of the second peer */ 1297 /* Get the identity of the second peer */
1267 if (NULL != occ->peer2_controller) 1298 if (NULL != p2n)
1268 { 1299 {
1269 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1270
1271 cmsg.header.size =
1272 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1273 cmsg.header.type =
1274 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION);
1275 cmsg.peer_id = msg->peer2;
1276 cmsg.operation_id = msg->operation_id;
1277 occ->opc =
1278 GNUNET_TESTBED_forward_operation_msg_ (occ->peer2_controller,
1279 occ->op_id, &cmsg.header,
1280 &overlay_connect_get_config,
1281 occ);
1282 GNUNET_asprintf (&occ->emsg, 1300 GNUNET_asprintf (&occ->emsg,
1283 "0x%llx: Timeout while getting peer identity of peer " 1301 "0x%llx: Timeout while acquiring connection to peer %u's "
1284 "with id: %u", occ->op_id, occ->other_peer_id); 1302 "host: %u\n", occ->op_id, occ->other_peer_id, peer2_host_id);
1303 occ->p2_ncn = GST_neighbour_get_connection (p2n, &p2_controller_connect_cb,
1304 occ);
1305 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1306 return;
1307 }
1308 if (NULL != p2c)
1309 {
1310 p2_controller_connect_cb (occ, p2c);
1285 GNUNET_SERVER_receive_done (client, GNUNET_OK); 1311 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1286 return; 1312 return;
1287 } 1313 }