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