aboutsummaryrefslogtreecommitdiff
path: root/src/testbed/gnunet-service-testbed.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testbed/gnunet-service-testbed.c')
-rw-r--r--src/testbed/gnunet-service-testbed.c985
1 files changed, 0 insertions, 985 deletions
diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c
deleted file mode 100644
index 3ef99ae25..000000000
--- a/src/testbed/gnunet-service-testbed.c
+++ /dev/null
@@ -1,985 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2008--2013, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
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#include "gnunet-service-testbed_barriers.h"
29#include "gnunet-service-testbed_connectionpool.h"
30
31/***********/
32/* Globals */
33/***********/
34
35/**
36 * Our configuration
37 */
38struct GNUNET_CONFIGURATION_Handle *GST_config;
39
40/**
41 * The master context; generated with the first INIT message
42 */
43struct Context *GST_context;
44
45/**
46 * Array of hosts
47 */
48struct GNUNET_TESTBED_Host **GST_host_list;
49
50/**
51 * DLL head for forwarded operation contexts
52 */
53struct ForwardedOperationContext *fopcq_head;
54
55/**
56 * DLL tail for forwarded operation contexts
57 */
58struct ForwardedOperationContext *fopcq_tail;
59
60/**
61 * Operation queue for open file descriptors
62 */
63struct OperationQueue *GST_opq_openfds;
64
65/**
66 * Timeout for operations which may take some time
67 */
68struct GNUNET_TIME_Relative GST_timeout;
69
70/**
71 * The size of the host list
72 */
73unsigned int GST_host_list_size;
74
75/**
76 * The size of the peer list
77 */
78unsigned int GST_peer_list_size;
79
80
81/***********************************/
82/* Local definitions and variables */
83/***********************************/
84
85/**
86 * Our hostname; we give this to all the peers we start
87 */
88static char *hostname;
89
90
91/**
92 * Function to add a host to the current list of known hosts
93 *
94 * @param host the host to add
95 * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure due to host-id
96 * already in use
97 */
98static int
99host_list_add (struct GNUNET_TESTBED_Host *host)
100{
101 uint32_t host_id;
102
103 host_id = GNUNET_TESTBED_host_get_id_ (host);
104 if (GST_host_list_size <= host_id)
105 GST_array_grow_large_enough (GST_host_list, GST_host_list_size, host_id);
106 if (NULL != GST_host_list[host_id])
107 {
108 LOG_DEBUG ("A host with id: %u already exists\n", host_id);
109 return GNUNET_SYSERR;
110 }
111 GST_host_list[host_id] = host;
112 return GNUNET_OK;
113}
114
115
116/**
117 * Send operation failure message to client
118 *
119 * @param client the client to which the failure message has to be sent to
120 * @param operation_id the id of the failed operation
121 * @param emsg the error message; can be NULL
122 */
123void
124GST_send_operation_fail_msg (struct GNUNET_SERVICE_Client *client,
125 uint64_t operation_id,
126 const char *emsg)
127{
128 struct GNUNET_MQ_Envelope *env;
129 struct GNUNET_TESTBED_OperationFailureEventMessage *msg;
130 uint16_t emsg_len;
131
132 emsg_len = (NULL == emsg) ? 0 : strlen (emsg) + 1;
133 env = GNUNET_MQ_msg_extra (msg,
134 emsg_len,
135 GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT);
136 msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
137 msg->operation_id = GNUNET_htonll (operation_id);
138 GNUNET_memcpy (&msg[1],
139 emsg,
140 emsg_len);
141 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
142 env);
143}
144
145
146/**
147 * Function to send generic operation success message to given client
148 *
149 * @param client the client to send the message to
150 * @param operation_id the id of the operation which was successful
151 */
152void
153GST_send_operation_success_msg (struct GNUNET_SERVICE_Client *client,
154 uint64_t operation_id)
155{
156 struct GNUNET_MQ_Envelope *env;
157 struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg;
158
159 env = GNUNET_MQ_msg (msg,
160 GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS);
161 msg->operation_id = GNUNET_htonll (operation_id);
162 msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
163 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
164 env);
165}
166
167
168/**
169 * Callback which will be called after a host registration succeeded or failed
170 *
171 * @param cls the handle to the slave at which the registration is completed
172 * @param emsg the error message; NULL if host registration is successful
173 */
174static void
175hr_completion (void *cls,
176 const char *emsg);
177
178
179/**
180 * Attempts to register the next host in the host registration queue
181 *
182 * @param slave the slave controller whose host registration queue is checked
183 * for host registrations
184 */
185static void
186register_next_host (struct Slave *slave)
187{
188 struct HostRegistration *hr;
189
190 hr = slave->hr_dll_head;
191 GNUNET_assert (NULL != hr);
192 GNUNET_assert (NULL == slave->rhandle);
193 LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering host %u at %u\n",
194 GNUNET_TESTBED_host_get_id_ (hr->host),
195 GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id]));
196 slave->rhandle
197 = GNUNET_TESTBED_register_host (slave->controller,
198 hr->host,
199 hr_completion,
200 slave);
201}
202
203
204/**
205 * Callback which will be called to after a host registration succeeded or failed
206 *
207 * @param cls the handle to the slave at which the registration is completed
208 * @param emsg the error message; NULL if host registration is successful
209 */
210static void
211hr_completion (void *cls,
212 const char *emsg)
213{
214 struct Slave *slave = cls;
215 struct HostRegistration *hr;
216
217 slave->rhandle = NULL;
218 hr = slave->hr_dll_head;
219 GNUNET_assert (NULL != hr);
220 LOG (GNUNET_ERROR_TYPE_DEBUG,
221 "Registering host %u at %u successful\n",
222 GNUNET_TESTBED_host_get_id_ (hr->host),
223 GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id]));
224 GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head,
225 slave->hr_dll_tail,
226 hr);
227 if (NULL != hr->cb)
228 hr->cb (hr->cb_cls,
229 emsg);
230 GNUNET_free (hr);
231 if (NULL != slave->hr_dll_head)
232 register_next_host (slave);
233}
234
235
236/**
237 * Adds a host registration's request to a slave's registration queue
238 *
239 * @param slave the slave controller at which the given host has to be
240 * registered
241 * @param cb the host registration completion callback
242 * @param cb_cls the closure for the host registration completion callback
243 * @param host the host which has to be registered
244 */
245void
246GST_queue_host_registration (struct Slave *slave,
247 GNUNET_TESTBED_HostRegistrationCompletion cb,
248 void *cb_cls,
249 struct GNUNET_TESTBED_Host *host)
250{
251 struct HostRegistration *hr;
252 int call_register;
253
254 LOG (GNUNET_ERROR_TYPE_DEBUG,
255 "Queueing host registration for host %u at %u\n",
256 GNUNET_TESTBED_host_get_id_ (host),
257 GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id]));
258 hr = GNUNET_new (struct HostRegistration);
259 hr->cb = cb;
260 hr->cb_cls = cb_cls;
261 hr->host = host;
262 call_register = (NULL == slave->hr_dll_head) ? GNUNET_YES : GNUNET_NO;
263 GNUNET_CONTAINER_DLL_insert_tail (slave->hr_dll_head,
264 slave->hr_dll_tail,
265 hr);
266 if (GNUNET_YES == call_register)
267 register_next_host (slave);
268}
269
270
271/**
272 * Callback to relay the reply msg of a forwarded operation back to the client
273 *
274 * @param cls ForwardedOperationContext
275 * @param msg the message to relay
276 */
277void
278GST_forwarded_operation_reply_relay (void *cls,
279 const struct GNUNET_MessageHeader *msg)
280{
281 struct ForwardedOperationContext *fopc = cls;
282 struct GNUNET_MQ_Envelope *env;
283
284 LOG_DEBUG ("Relaying message with type: %u, size: %u\n",
285 ntohs (msg->type),
286 ntohs (msg->size));
287 env = GNUNET_MQ_msg_copy (msg);
288 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (fopc->client),
289 env);
290 GNUNET_SCHEDULER_cancel (fopc->timeout_task);
291 GNUNET_CONTAINER_DLL_remove (fopcq_head,
292 fopcq_tail,
293 fopc);
294 GNUNET_free (fopc);
295}
296
297
298/**
299 * Task to free resources when forwarded operation has been timed out
300 *
301 * @param cls the ForwardedOperationContext
302 */
303void
304GST_forwarded_operation_timeout (void *cls)
305{
306 struct ForwardedOperationContext *fopc = cls;
307
308 fopc->timeout_task = NULL;
309 GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc);
310 LOG (GNUNET_ERROR_TYPE_DEBUG,
311 "A forwarded operation has timed out\n");
312 GST_send_operation_fail_msg (fopc->client,
313 fopc->operation_id,
314 "A forwarded operation has timed out");
315 GNUNET_CONTAINER_DLL_remove (fopcq_head,
316 fopcq_tail,
317 fopc);
318 GNUNET_free (fopc);
319}
320
321
322/**
323 * Parse service sharing specification line.
324 * Format is "[<service:share>] [<service:share>] ..."
325 *
326 * @param ss_str the spec string to be parsed
327 * @param cfg the configuration to use for shared services
328 * @return an array suitable to pass to GNUNET_TESTING_system_create(). NULL
329 * upon empty service sharing specification.
330 */
331static struct GNUNET_TESTING_SharedService *
332parse_shared_services (char *ss_str,
333 struct GNUNET_CONFIGURATION_Handle *cfg)
334{
335 struct GNUNET_TESTING_SharedService ss;
336 struct GNUNET_TESTING_SharedService *slist;
337 char service[256];
338 char *arg;
339 unsigned int n;
340
341#define GROW_SS \
342 do { \
343 GNUNET_array_grow (slist, n, n + 1); \
344 GNUNET_memcpy (&slist[n - 1], &ss, \
345 sizeof(struct GNUNET_TESTING_SharedService)); \
346 } while (0)
347
348 slist = NULL;
349 n = 0;
350 ss.cfg = cfg;
351 for (; NULL != (arg = strtok (ss_str, " ")); ss_str = NULL)
352 {
353 ss.service = NULL;
354 ss.share = 0;
355 if (2 != sscanf (arg, "%255[^:]:%u",
356 service,
357 &ss.share))
358 {
359 LOG (GNUNET_ERROR_TYPE_WARNING,
360 "Ignoring shared service spec: %s",
361 arg);
362 continue;
363 }
364 LOG_DEBUG ("Will be sharing %s service among %u peers\n",
365 service,
366 ss.share);
367 ss.service = GNUNET_strdup (service);
368 GROW_SS;
369 }
370 if (NULL != slist)
371 {
372 /* Add trailing NULL block */
373 (void) memset (&ss,
374 0,
375 sizeof(struct GNUNET_TESTING_SharedService));
376 GROW_SS;
377 }
378 return slist;
379#undef GROW_SS
380}
381
382
383/**
384 * Check #GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
385 *
386 * @param cls identification of the client
387 * @param message the actual message
388 * @return #GNUNET_OK if @a message is well-formed
389 */
390static int
391check_init (void *cls,
392 const struct GNUNET_TESTBED_InitMessage *msg)
393{
394 const char *controller_hostname;
395 uint16_t msize;
396
397 msize = ntohs (msg->header.size) - sizeof(struct GNUNET_TESTBED_InitMessage);
398 controller_hostname = (const char *) &msg[1];
399 if ('\0' != controller_hostname[msize - 1])
400 {
401 GNUNET_break (0);
402 return GNUNET_SYSERR;
403 }
404 return GNUNET_OK;
405}
406
407
408/**
409 * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
410 *
411 * @param cls identification of the client
412 * @param message the actual message
413 */
414static void
415handle_init (void *cls,
416 const struct GNUNET_TESTBED_InitMessage *msg)
417{
418 struct GNUNET_SERVICE_Client *client = cls;
419 struct GNUNET_TESTBED_Host *host;
420 const char *controller_hostname;
421 char *ss_str;
422 struct GNUNET_TESTING_SharedService *ss;
423 unsigned int cnt;
424
425 if (NULL != GST_context)
426 {
427 LOG_DEBUG ("We are being connected to laterally\n");
428 GNUNET_SERVICE_client_continue (client);
429 return;
430 }
431 controller_hostname = (const char *) &msg[1];
432 ss_str = NULL;
433 ss = NULL;
434 if (GNUNET_OK ==
435 GNUNET_CONFIGURATION_get_value_string (GST_config,
436 "TESTBED",
437 "SHARED_SERVICES",
438 &ss_str))
439 {
440 ss = parse_shared_services (ss_str,
441 GST_config);
442 GNUNET_free (ss_str);
443 ss_str = NULL;
444 }
445 GST_context = GNUNET_new (struct Context);
446 GST_context->client = client;
447 GST_context->host_id = ntohl (msg->host_id);
448 GST_context->master_ip = GNUNET_strdup (controller_hostname);
449 LOG_DEBUG ("Our IP: %s\n",
450 GST_context->master_ip);
451 GST_context->system
452 = GNUNET_TESTING_system_create ("testbed",
453 GST_context->master_ip,
454 hostname,
455 ss);
456 if (NULL != ss)
457 {
458 for (cnt = 0; NULL != ss[cnt].service; cnt++)
459 {
460 ss_str = (char *) ss[cnt].service;
461 GNUNET_free (ss_str);
462 }
463 GNUNET_free (ss);
464 ss = NULL;
465 }
466 host =
467 GNUNET_TESTBED_host_create_with_id (GST_context->host_id,
468 GST_context->master_ip,
469 NULL,
470 GST_config,
471 0);
472 host_list_add (host);
473 LOG_DEBUG ("Created master context with host ID: %u\n",
474 GST_context->host_id);
475 GNUNET_SERVICE_client_continue (client);
476}
477
478
479/**
480 * Check #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
481 *
482 * @param cls identification of the client
483 * @param msg the actual message
484 * @return #GNUNET_OK if @a message is well-formed
485 */
486static int
487check_add_host (void *cls,
488 const struct GNUNET_TESTBED_AddHostMessage *msg)
489{
490 uint16_t username_length;
491 uint16_t hostname_length;
492 uint16_t msize;
493
494 msize = ntohs (msg->header.size) - sizeof(struct
495 GNUNET_TESTBED_AddHostMessage);
496 username_length = ntohs (msg->username_length);
497 hostname_length = ntohs (msg->hostname_length);
498 /* msg must contain hostname */
499 if ((msize <= username_length) ||
500 (0 == hostname_length))
501 {
502 GNUNET_break (0);
503 return GNUNET_SYSERR;
504 }
505 /* msg must contain configuration */
506 if (msize <= username_length + hostname_length)
507 {
508 GNUNET_break (0);
509 return GNUNET_SYSERR;
510 }
511 return GNUNET_OK;
512}
513
514
515/**
516 * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
517 *
518 * @param cls identification of the client
519 * @param msg the actual message
520 */
521static void
522handle_add_host (void *cls,
523 const struct GNUNET_TESTBED_AddHostMessage *msg)
524{
525 struct GNUNET_SERVICE_Client *client = cls;
526 struct GNUNET_TESTBED_Host *host;
527 struct GNUNET_TESTBED_HostConfirmedMessage *reply;
528 struct GNUNET_CONFIGURATION_Handle *host_cfg;
529 char *username;
530 char *hostname;
531 char *emsg;
532 const void *ptr;
533 uint32_t host_id;
534 uint16_t username_length;
535 uint16_t hostname_length;
536 struct GNUNET_MQ_Envelope *env;
537
538 username_length = ntohs (msg->username_length);
539 hostname_length = ntohs (msg->hostname_length);
540 username = NULL;
541 hostname = NULL;
542 ptr = &msg[1];
543 if (0 != username_length)
544 {
545 username = GNUNET_malloc (username_length + 1);
546 GNUNET_strlcpy (username, ptr, username_length + 1);
547 ptr += username_length;
548 }
549 hostname = GNUNET_malloc (hostname_length + 1);
550 GNUNET_strlcpy (hostname, ptr, hostname_length + 1);
551 if (NULL == (host_cfg = GNUNET_TESTBED_extract_config_ (&msg->header)))
552 {
553 GNUNET_free (username);
554 GNUNET_free (hostname);
555 GNUNET_break_op (0);
556 GNUNET_SERVICE_client_drop (client);
557 return;
558 }
559 host_id = ntohl (msg->host_id);
560 LOG_DEBUG ("Received ADDHOST %u message\n", host_id);
561 LOG_DEBUG ("-------host id: %u\n", host_id);
562 LOG_DEBUG ("-------hostname: %s\n", hostname);
563 if (NULL != username)
564 LOG_DEBUG ("-------username: %s\n", username);
565 else
566 LOG_DEBUG ("-------username: <not given>\n");
567 LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
568 host = GNUNET_TESTBED_host_create_with_id (host_id,
569 hostname,
570 username,
571 host_cfg,
572 ntohs (msg->ssh_port));
573 GNUNET_free (username);
574 GNUNET_free (hostname);
575 GNUNET_CONFIGURATION_destroy (host_cfg);
576 if (NULL == host)
577 {
578 GNUNET_break_op (0);
579 GNUNET_SERVICE_client_drop (client);
580 return;
581 }
582 if (GNUNET_OK != host_list_add (host))
583 {
584 /* We are unable to add a host */
585 emsg = "A host exists with given host-id";
586 LOG_DEBUG ("%s: %u",
587 emsg,
588 host_id);
589 GNUNET_TESTBED_host_destroy (host);
590 env = GNUNET_MQ_msg_extra (reply,
591 strlen (emsg) + 1,
592 GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS);
593 GNUNET_memcpy (&reply[1],
594 emsg,
595 strlen (emsg) + 1);
596 }
597 else
598 {
599 LOG_DEBUG ("Added host %u at %u\n",
600 host_id,
601 GST_context->host_id);
602 env = GNUNET_MQ_msg (reply,
603 GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS);
604 }
605 reply->host_id = htonl (host_id);
606 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
607 env);
608 GNUNET_SERVICE_client_continue (client);
609}
610
611
612/**
613 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages
614 *
615 * @param cls identification of the client
616 * @param msg the actual message
617 */
618static void
619handle_slave_get_config (void *cls,
620 const struct
621 GNUNET_TESTBED_SlaveGetConfigurationMessage *msg)
622{
623 struct GNUNET_SERVICE_Client *client = cls;
624 struct Slave *slave;
625 struct GNUNET_TESTBED_SlaveConfiguration *reply;
626 const struct GNUNET_CONFIGURATION_Handle *cfg;
627 struct GNUNET_MQ_Envelope *env;
628 char *config;
629 char *xconfig;
630 size_t config_size;
631 size_t xconfig_size;
632 uint64_t op_id;
633 uint32_t slave_id;
634
635 slave_id = ntohl (msg->slave_id);
636 op_id = GNUNET_ntohll (msg->operation_id);
637 if ((GST_slave_list_size <= slave_id) ||
638 (NULL == GST_slave_list[slave_id]))
639 {
640 /* FIXME: Add forwardings for this type of message here.. */
641 GST_send_operation_fail_msg (client,
642 op_id,
643 "Slave not found");
644 GNUNET_SERVICE_client_continue (client);
645 return;
646 }
647 slave = GST_slave_list[slave_id];
648 GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (
649 GST_host_list[slave->host_id])));
650 config = GNUNET_CONFIGURATION_serialize (cfg,
651 &config_size);
652 /* FIXME: maybe we want to transmit the delta to the default here? */
653 xconfig_size = GNUNET_TESTBED_compress_config_ (config,
654 config_size,
655 &xconfig);
656 GNUNET_free (config);
657 GNUNET_assert (xconfig_size + sizeof(struct
658 GNUNET_TESTBED_SlaveConfiguration) <=
659 UINT16_MAX);
660 GNUNET_assert (xconfig_size <= UINT16_MAX);
661 env = GNUNET_MQ_msg_extra (reply,
662 xconfig_size,
663 GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION);
664 reply->slave_id = msg->slave_id;
665 reply->operation_id = msg->operation_id;
666 reply->config_size = htons ((uint16_t) config_size);
667 GNUNET_memcpy (&reply[1],
668 xconfig,
669 xconfig_size);
670 GNUNET_free (xconfig);
671 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
672 env);
673 GNUNET_SERVICE_client_continue (client);
674}
675
676
677/**
678 * Clears the forwarded operations queue
679 */
680void
681GST_clear_fopcq ()
682{
683 struct ForwardedOperationContext *fopc;
684
685 while (NULL != (fopc = fopcq_head))
686 {
687 GNUNET_CONTAINER_DLL_remove (fopcq_head,
688 fopcq_tail,
689 fopc);
690 GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc);
691 if (NULL != fopc->timeout_task)
692 GNUNET_SCHEDULER_cancel (fopc->timeout_task);
693 switch (fopc->type)
694 {
695 case OP_PEER_CREATE:
696 GNUNET_free (fopc->cls);
697 break;
698
699 case OP_SHUTDOWN_PEERS:
700 {
701 struct HandlerContext_ShutdownPeers *hc = fopc->cls;
702
703 GNUNET_assert (0 < hc->nslaves);
704 hc->nslaves--;
705 if (0 == hc->nslaves)
706 GNUNET_free (hc);
707 }
708 break;
709
710 case OP_PEER_START:
711 case OP_PEER_STOP:
712 case OP_PEER_DESTROY:
713 case OP_PEER_INFO:
714 case OP_OVERLAY_CONNECT:
715 case OP_LINK_CONTROLLERS:
716 case OP_GET_SLAVE_CONFIG:
717 case OP_MANAGE_SERVICE:
718 case OP_PEER_RECONFIGURE:
719 break;
720
721 case OP_FORWARDED:
722 GNUNET_assert (0);
723 }
724 ;
725 GNUNET_free (fopc);
726 }
727}
728
729
730/**
731 * Task to clean up and shutdown nicely
732 *
733 * @param cls NULL
734 */
735static void
736shutdown_task (void *cls)
737{
738 uint32_t id;
739
740 LOG_DEBUG ("Shutting down testbed service\n");
741 /* cleanup any remaining forwarded operations */
742 GST_clear_fopcq ();
743 GST_free_lcf ();
744 GST_free_mctxq ();
745 GST_free_occq ();
746 GST_free_roccq ();
747 GST_free_nccq ();
748 GST_neighbour_list_clean ();
749 GST_free_prcq ();
750 /* Clear peer list */
751 GST_destroy_peers ();
752 /* Clear route list */
753 GST_route_list_clear ();
754 /* Clear GST_slave_list */
755 GST_slave_list_clear ();
756 /* Clear host list */
757 for (id = 0; id < GST_host_list_size; id++)
758 if (NULL != GST_host_list[id])
759 GNUNET_TESTBED_host_destroy (GST_host_list[id]);
760 GNUNET_free (GST_host_list);
761 if (NULL != GST_context)
762 {
763 GNUNET_free (GST_context->master_ip);
764 if (NULL != GST_context->system)
765 GNUNET_TESTING_system_destroy (GST_context->system,
766 GNUNET_YES);
767 GNUNET_free (GST_context);
768 GST_context = NULL;
769 }
770 GNUNET_free (hostname);
771 /* Free hello cache */
772 GST_cache_clear ();
773 GST_connection_pool_destroy ();
774 GNUNET_TESTBED_operation_queue_destroy_ (GST_opq_openfds);
775 GST_opq_openfds = NULL;
776 GST_stats_destroy ();
777 GST_barriers_destroy ();
778 GNUNET_CONFIGURATION_destroy (GST_config);
779}
780
781
782/**
783 * Callback for client connect
784 *
785 * @param cls NULL
786 * @param client the client which has disconnected
787 * @param mq queue for sending messages to @a client
788 * @return @a client
789 */
790static void *
791client_connect_cb (void *cls,
792 struct GNUNET_SERVICE_Client *client,
793 struct GNUNET_MQ_Handle *mq)
794{
795 return client;
796}
797
798
799/**
800 * Callback for client disconnect
801 *
802 * @param cls NULL
803 * @param client the client which has disconnected
804 * @param app_ctx should match @a client
805 */
806static void
807client_disconnect_cb (void *cls,
808 struct GNUNET_SERVICE_Client *client,
809 void *app_ctx)
810{
811 struct ForwardedOperationContext *fopc;
812 struct ForwardedOperationContext *fopcn;
813
814 GNUNET_assert (client == app_ctx);
815 GST_notify_client_disconnect_oc (client);
816 GST_link_notify_disconnect (client);
817 GST_notify_client_disconnect_peers (client);
818 for (fopc = fopcq_head; NULL != fopc; fopc = fopcn)
819 {
820 fopcn = fopc->next;
821 if (fopc->client == client)
822 {
823 /* handle as if it were a timeout */
824 GNUNET_SCHEDULER_cancel (fopc->timeout_task);
825 GST_forwarded_operation_timeout (fopc);
826 }
827 }
828 if (NULL == GST_context)
829 return;
830 if (client == GST_context->client)
831 {
832 LOG (GNUNET_ERROR_TYPE_DEBUG,
833 "Master client disconnected\n");
834 GST_context->client = NULL;
835 /* should not be needed as we're terminated by failure to read
836 * from stdin, but if stdin fails for some reason, this shouldn't
837 * hurt for now --- might need to revise this later if we ever
838 * decide that master connections might be temporarily down
839 * for some reason */// GNUNET_SCHEDULER_shutdown ();
840 }
841}
842
843
844/**
845 * Testbed setup
846 *
847 * @param cls closure
848 * @param cfg configuration to use
849 * @param service the initialized server
850 */
851static void
852testbed_run (void *cls,
853 const struct GNUNET_CONFIGURATION_Handle *cfg,
854 struct GNUNET_SERVICE_Handle *service)
855{
856 char *logfile;
857 unsigned long long num;
858
859 LOG_DEBUG ("Starting testbed\n");
860 if (GNUNET_OK ==
861 GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED", "LOG_FILE",
862 &logfile))
863 {
864 GNUNET_break (GNUNET_OK ==
865 GNUNET_log_setup ("testbed",
866 "DEBUG",
867 logfile));
868 GNUNET_free (logfile);
869 }
870 GNUNET_assert (GNUNET_OK ==
871 GNUNET_CONFIGURATION_get_value_number (cfg,
872 "testbed",
873 "CACHE_SIZE",
874 &num));
875 GST_cache_init ((unsigned int) num);
876 GST_connection_pool_init ((unsigned int) num);
877 GNUNET_assert (GNUNET_OK ==
878 GNUNET_CONFIGURATION_get_value_number (cfg,
879 "testbed",
880 "MAX_OPEN_FDS",
881 &num));
882 GST_opq_openfds = GNUNET_TESTBED_operation_queue_create_ (
883 OPERATION_QUEUE_TYPE_FIXED,
884 (unsigned int) num);
885 GNUNET_assert (GNUNET_OK ==
886 GNUNET_CONFIGURATION_get_value_time (cfg,
887 "testbed",
888 "OPERATION_TIMEOUT",
889 &GST_timeout));
890 GNUNET_assert (GNUNET_OK ==
891 GNUNET_CONFIGURATION_get_value_string (cfg,
892 "testbed",
893 "HOSTNAME",
894 &hostname));
895 GST_config = GNUNET_CONFIGURATION_dup (cfg);
896 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
897 NULL);
898 LOG_DEBUG ("Testbed startup complete\n");
899 GST_stats_init (GST_config);
900 GST_barriers_init (GST_config);
901}
902
903
904/**
905 * Define "main" method using service macro.
906 */
907GNUNET_SERVICE_MAIN
908 ("testbed",
909 GNUNET_SERVICE_OPTION_NONE,
910 &testbed_run,
911 &client_connect_cb,
912 &client_disconnect_cb,
913 NULL,
914 GNUNET_MQ_hd_var_size (init,
915 GNUNET_MESSAGE_TYPE_TESTBED_INIT,
916 struct GNUNET_TESTBED_InitMessage,
917 NULL),
918 GNUNET_MQ_hd_var_size (add_host,
919 GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST,
920 struct GNUNET_TESTBED_AddHostMessage,
921 NULL),
922 GNUNET_MQ_hd_fixed_size (slave_get_config,
923 GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION,
924 struct GNUNET_TESTBED_SlaveGetConfigurationMessage,
925 NULL),
926 GNUNET_MQ_hd_fixed_size (link_controllers,
927 GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
928 struct GNUNET_TESTBED_ControllerLinkRequest,
929 NULL),
930 GNUNET_MQ_hd_var_size (remote_overlay_connect,
931 GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT,
932 struct GNUNET_TESTBED_RemoteOverlayConnectMessage,
933 NULL),
934 GNUNET_MQ_hd_fixed_size (overlay_connect,
935 GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT,
936 struct GNUNET_TESTBED_OverlayConnectMessage,
937 NULL),
938 GNUNET_MQ_hd_var_size (peer_create,
939 GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER,
940 struct GNUNET_TESTBED_PeerCreateMessage,
941 NULL),
942 GNUNET_MQ_hd_fixed_size (peer_destroy,
943 GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER,
944 struct GNUNET_TESTBED_PeerDestroyMessage,
945 NULL),
946 GNUNET_MQ_hd_fixed_size (peer_start,
947 GNUNET_MESSAGE_TYPE_TESTBED_START_PEER,
948 struct GNUNET_TESTBED_PeerStartMessage,
949 NULL),
950 GNUNET_MQ_hd_fixed_size (peer_stop,
951 GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER,
952 struct GNUNET_TESTBED_PeerStopMessage,
953 NULL),
954 GNUNET_MQ_hd_fixed_size (peer_get_config,
955 GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION,
956 struct GNUNET_TESTBED_PeerGetConfigurationMessage,
957 NULL),
958 GNUNET_MQ_hd_var_size (manage_peer_service,
959 GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE,
960 struct GNUNET_TESTBED_ManagePeerServiceMessage,
961 NULL),
962 GNUNET_MQ_hd_fixed_size (shutdown_peers,
963 GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS,
964 struct GNUNET_TESTBED_ShutdownPeersMessage,
965 NULL),
966 GNUNET_MQ_hd_var_size (peer_reconfigure,
967 GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER,
968 struct GNUNET_TESTBED_PeerReconfigureMessage,
969 NULL),
970 GNUNET_MQ_hd_var_size (barrier_init,
971 GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT,
972 struct GNUNET_TESTBED_BarrierInit,
973 NULL),
974 GNUNET_MQ_hd_var_size (barrier_cancel,
975 GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL,
976 struct GNUNET_TESTBED_BarrierCancel,
977 NULL),
978 GNUNET_MQ_hd_var_size (barrier_status,
979 GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS,
980 struct GNUNET_TESTBED_BarrierStatusMsg,
981 NULL),
982 GNUNET_MQ_handler_end ());
983
984
985/* end of gnunet-service-testbed.c */