2 This file is part of GNUnet.
3 Copyright (C) 2008--2013 GNUnet e.V.
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 3, or (at your
8 option) any later version.
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.
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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * @file testbed/gnunet-service-testbed.c
23 * @brief implementation of the TESTBED service
24 * @author Sree Harsha Totakura
27 #include "gnunet-service-testbed.h"
28 #include "gnunet-service-testbed_barriers.h"
29 #include "gnunet-service-testbed_connectionpool.h"
38 struct GNUNET_CONFIGURATION_Handle *GST_config;
41 * The master context; generated with the first INIT message
43 struct Context *GST_context;
48 struct GNUNET_TESTBED_Host **GST_host_list;
51 * DLL head for forwarded operation contexts
53 struct ForwardedOperationContext *fopcq_head;
56 * DLL tail for forwarded operation contexts
58 struct ForwardedOperationContext *fopcq_tail;
61 * Operation queue for open file descriptors
63 struct OperationQueue *GST_opq_openfds;
66 * Timeout for operations which may take some time
68 const struct GNUNET_TIME_Relative GST_timeout;
71 * The size of the host list
73 unsigned int GST_host_list_size;
76 * The size of the peer list
78 unsigned int GST_peer_list_size;
81 /***********************************/
82 /* Local definitions and variables */
83 /***********************************/
86 * The message queue for sending messages to clients
91 * The message to be sent
93 struct GNUNET_MessageHeader *msg;
96 * The client to send the message to
98 struct GNUNET_SERVER_Client *client;
101 * next pointer for DLL
103 struct MessageQueue *next;
106 * prev pointer for DLL
108 struct MessageQueue *prev;
112 * Our hostname; we give this to all the peers we start
114 static char *hostname;
117 * Current Transmit Handle; NULL if no notify transmit exists currently
119 static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
122 * The message queue head
124 static struct MessageQueue *mq_head;
127 * The message queue tail
129 static struct MessageQueue *mq_tail;
133 * Function called to notify a client about the connection begin ready to queue
134 * more data. "buf" will be NULL and "size" zero if the connection was closed
135 * for writing in the meantime.
138 * @param size number of bytes available in buf
139 * @param buf where the callee should write the message
140 * @return number of bytes written to buf
143 transmit_ready_notify (void *cls, size_t size, void *buf)
145 struct MessageQueue *mq_entry;
147 transmit_handle = NULL;
149 GNUNET_assert (NULL != mq_entry);
152 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
153 size = ntohs (mq_entry->msg->size);
154 memcpy (buf, mq_entry->msg, size);
155 GNUNET_free (mq_entry->msg);
156 GNUNET_SERVER_client_drop (mq_entry->client);
157 GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
158 GNUNET_free (mq_entry);
160 if (NULL != mq_entry)
162 GNUNET_SERVER_notify_transmit_ready (mq_entry->client,
163 ntohs (mq_entry->msg->size),
164 GNUNET_TIME_UNIT_FOREVER_REL,
165 &transmit_ready_notify, NULL);
171 * Queues a message in send queue for sending to the service
173 * @param client the client to whom the queued message has to be sent
174 * @param msg the message to queue
177 GST_queue_message (struct GNUNET_SERVER_Client *client,
178 struct GNUNET_MessageHeader *msg)
180 struct MessageQueue *mq_entry;
184 type = ntohs (msg->type);
185 size = ntohs (msg->size);
186 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
187 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
188 mq_entry = GNUNET_new (struct MessageQueue);
190 mq_entry->client = client;
191 GNUNET_SERVER_client_keep (client);
192 LOG_DEBUG ("Queueing message of type %u, size %u for sending\n", type,
194 GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry);
195 if (NULL == transmit_handle)
197 GNUNET_SERVER_notify_transmit_ready (client, size,
198 GNUNET_TIME_UNIT_FOREVER_REL,
199 &transmit_ready_notify, NULL);
204 * Function to add a host to the current list of known hosts
206 * @param host the host to add
207 * @return GNUNET_OK on success; GNUNET_SYSERR on failure due to host-id
211 host_list_add (struct GNUNET_TESTBED_Host *host)
215 host_id = GNUNET_TESTBED_host_get_id_ (host);
216 if (GST_host_list_size <= host_id)
217 GST_array_grow_large_enough (GST_host_list, GST_host_list_size, host_id);
218 if (NULL != GST_host_list[host_id])
220 LOG_DEBUG ("A host with id: %u already exists\n", host_id);
221 return GNUNET_SYSERR;
223 GST_host_list[host_id] = host;
229 * Send operation failure message to client
231 * @param client the client to which the failure message has to be sent to
232 * @param operation_id the id of the failed operation
233 * @param emsg the error message; can be NULL
236 GST_send_operation_fail_msg (struct GNUNET_SERVER_Client *client,
237 uint64_t operation_id, const char *emsg)
239 struct GNUNET_TESTBED_OperationFailureEventMessage *msg;
243 msize = sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
244 emsg_len = (NULL == emsg) ? 0 : strlen (emsg) + 1;
246 msg = GNUNET_malloc (msize);
247 msg->header.size = htons (msize);
248 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT);
249 msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
250 msg->operation_id = GNUNET_htonll (operation_id);
252 memcpy (&msg[1], emsg, emsg_len);
253 GST_queue_message (client, &msg->header);
258 * Function to send generic operation success message to given client
260 * @param client the client to send the message to
261 * @param operation_id the id of the operation which was successful
264 GST_send_operation_success_msg (struct GNUNET_SERVER_Client *client,
265 uint64_t operation_id)
267 struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg;
270 msize = sizeof (struct GNUNET_TESTBED_GenericOperationSuccessEventMessage);
271 msg = GNUNET_malloc (msize);
272 msg->header.size = htons (msize);
274 htons (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS);
275 msg->operation_id = GNUNET_htonll (operation_id);
276 msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
277 GST_queue_message (client, &msg->header);
281 * Callback which will be called after a host registration succeeded or failed
283 * @param cls the handle to the slave at which the registration is completed
284 * @param emsg the error message; NULL if host registration is successful
287 hr_completion (void *cls, const char *emsg);
291 * Attempts to register the next host in the host registration queue
293 * @param slave the slave controller whose host registration queue is checked
294 * for host registrations
297 register_next_host (struct Slave *slave)
299 struct HostRegistration *hr;
301 hr = slave->hr_dll_head;
302 GNUNET_assert (NULL != hr);
303 GNUNET_assert (NULL == slave->rhandle);
304 LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering host %u at %u\n",
305 GNUNET_TESTBED_host_get_id_ (hr->host),
306 GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id]));
308 GNUNET_TESTBED_register_host (slave->controller, hr->host, hr_completion,
314 * Callback which will be called to after a host registration succeeded or failed
316 * @param cls the handle to the slave at which the registration is completed
317 * @param emsg the error message; NULL if host registration is successful
320 hr_completion (void *cls, const char *emsg)
322 struct Slave *slave = cls;
323 struct HostRegistration *hr;
325 slave->rhandle = NULL;
326 hr = slave->hr_dll_head;
327 GNUNET_assert (NULL != hr);
328 LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering host %u at %u successful\n",
329 GNUNET_TESTBED_host_get_id_ (hr->host),
330 GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id]));
331 GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, slave->hr_dll_tail, hr);
333 hr->cb (hr->cb_cls, emsg);
335 if (NULL != slave->hr_dll_head)
336 register_next_host (slave);
341 * Adds a host registration's request to a slave's registration queue
343 * @param slave the slave controller at which the given host has to be
345 * @param cb the host registration completion callback
346 * @param cb_cls the closure for the host registration completion callback
347 * @param host the host which has to be registered
350 GST_queue_host_registration (struct Slave *slave,
351 GNUNET_TESTBED_HostRegistrationCompletion cb,
352 void *cb_cls, struct GNUNET_TESTBED_Host *host)
354 struct HostRegistration *hr;
357 LOG (GNUNET_ERROR_TYPE_DEBUG,
358 "Queueing host registration for host %u at %u\n",
359 GNUNET_TESTBED_host_get_id_ (host),
360 GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id]));
361 hr = GNUNET_new (struct HostRegistration);
365 call_register = (NULL == slave->hr_dll_head) ? GNUNET_YES : GNUNET_NO;
366 GNUNET_CONTAINER_DLL_insert_tail (slave->hr_dll_head, slave->hr_dll_tail, hr);
367 if (GNUNET_YES == call_register)
368 register_next_host (slave);
373 * Callback to relay the reply msg of a forwarded operation back to the client
375 * @param cls ForwardedOperationContext
376 * @param msg the message to relay
379 GST_forwarded_operation_reply_relay (void *cls,
380 const struct GNUNET_MessageHeader *msg)
382 struct ForwardedOperationContext *fopc = cls;
383 struct GNUNET_MessageHeader *dup_msg;
386 msize = ntohs (msg->size);
387 LOG_DEBUG ("Relaying message with type: %u, size: %u\n", ntohs (msg->type),
389 dup_msg = GNUNET_copy_message (msg);
390 GST_queue_message (fopc->client, dup_msg);
391 GNUNET_SERVER_client_drop (fopc->client);
392 GNUNET_SCHEDULER_cancel (fopc->timeout_task);
393 GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc);
399 * Task to free resources when forwarded operation has been timedout
401 * @param cls the ForwardedOperationContext
404 GST_forwarded_operation_timeout (void *cls)
406 struct ForwardedOperationContext *fopc = cls;
408 GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc);
409 LOG (GNUNET_ERROR_TYPE_DEBUG, "A forwarded operation has timed out\n");
410 GST_send_operation_fail_msg (fopc->client, fopc->operation_id,
411 "A forwarded operation has timed out");
412 GNUNET_SERVER_client_drop (fopc->client);
413 GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc);
419 * Parse service sharing specification line.
420 * Format is "[<service:share>] [<service:share>] ..."
422 * @param ss_str the spec string to be parsed
423 * @param cfg the configuration to use for shared services
424 * @return an array suitable to pass to GNUNET_TESTING_system_create(). NULL
425 * upon empty service sharing specification.
427 static struct GNUNET_TESTING_SharedService *
428 parse_shared_services (char *ss_str, struct GNUNET_CONFIGURATION_Handle *cfg)
430 struct GNUNET_TESTING_SharedService ss;
431 struct GNUNET_TESTING_SharedService *slist;
437 GNUNET_array_grow (slist, n, n+1); \
438 (void) memcpy (&slist[n - 1], &ss, \
439 sizeof (struct GNUNET_TESTING_SharedService)); \
445 for (; NULL != (arg = strtok (ss_str, " ")); ss_str = NULL)
449 if (2 != sscanf (arg, "%255[^:]:%u", service, &ss.share))
451 LOG (GNUNET_ERROR_TYPE_WARNING, "Ignoring shared service spec: %s", arg);
454 LOG_DEBUG ("Will be sharing %s service among %u peers\n", service, ss.share);
455 ss.service = GNUNET_strdup (service);
460 /* Add trailing NULL block */
461 (void) memset (&ss, 0, sizeof (struct GNUNET_TESTING_SharedService));
470 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
473 * @param client identification of the client
474 * @param message the actual message
477 handle_init (void *cls,
478 struct GNUNET_SERVER_Client *client,
479 const struct GNUNET_MessageHeader *message)
481 const struct GNUNET_TESTBED_InitMessage *msg;
482 struct GNUNET_TESTBED_Host *host;
483 const char *controller_hostname;
485 struct GNUNET_TESTING_SharedService *ss;
489 if (NULL != GST_context)
491 LOG_DEBUG ("We are being connected to laterally\n");
492 GNUNET_SERVER_receive_done (client, GNUNET_OK);
495 msg = (const struct GNUNET_TESTBED_InitMessage *) message;
496 msize = ntohs (message->size);
497 if (msize <= sizeof (struct GNUNET_TESTBED_InitMessage))
500 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
503 msize -= sizeof (struct GNUNET_TESTBED_InitMessage);
504 controller_hostname = (const char *) &msg[1];
505 if ('\0' != controller_hostname[msize - 1])
508 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
513 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (GST_config, "TESTBED",
517 ss = parse_shared_services (ss_str, GST_config);
518 GNUNET_free (ss_str);
521 GST_context = GNUNET_new (struct Context);
522 GNUNET_SERVER_client_keep (client);
523 GST_context->client = client;
524 GST_context->host_id = ntohl (msg->host_id);
525 GST_context->master_ip = GNUNET_strdup (controller_hostname);
526 LOG_DEBUG ("Our IP: %s\n", GST_context->master_ip);
527 GST_context->system =
528 GNUNET_TESTING_system_create ("testbed", GST_context->master_ip,
532 for (cnt = 0; NULL != ss[cnt].service; cnt++)
534 ss_str = (char *) ss[cnt].service;
535 GNUNET_free (ss_str);
541 GNUNET_TESTBED_host_create_with_id (GST_context->host_id,
542 GST_context->master_ip, NULL,
544 host_list_add (host);
545 LOG_DEBUG ("Created master context with host ID: %u\n", GST_context->host_id);
546 GNUNET_SERVER_receive_done (client, GNUNET_OK);
551 * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
554 * @param client identification of the client
555 * @param message the actual message
558 handle_add_host (void *cls,
559 struct GNUNET_SERVER_Client *client,
560 const struct GNUNET_MessageHeader *message)
562 struct GNUNET_TESTBED_Host *host;
563 const struct GNUNET_TESTBED_AddHostMessage *msg;
564 struct GNUNET_TESTBED_HostConfirmedMessage *reply;
565 struct GNUNET_CONFIGURATION_Handle *host_cfg;
571 uint16_t username_length;
572 uint16_t hostname_length;
576 msg = (const struct GNUNET_TESTBED_AddHostMessage *) message;
577 msize = ntohs (msg->header.size);
578 if (msize <= sizeof (struct GNUNET_TESTBED_AddHostMessage))
581 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
584 username_length = ntohs (msg->username_length);
585 hostname_length = ntohs (msg->hostname_length);
586 /* msg must contain hostname */
587 if ((msize <= (sizeof (struct GNUNET_TESTBED_AddHostMessage) +
589 || (0 == hostname_length))
592 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
595 /* msg must contain configuration */
596 if (msize <= (sizeof (struct GNUNET_TESTBED_AddHostMessage) +
597 username_length + hostname_length))
600 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
606 if (0 != username_length)
608 username = GNUNET_malloc (username_length + 1);
609 strncpy (username, ptr, username_length);
610 ptr += username_length;
612 hostname = GNUNET_malloc (hostname_length + 1);
613 strncpy (hostname, ptr, hostname_length);
614 if (NULL == (host_cfg = GNUNET_TESTBED_extract_config_ (message)))
616 GNUNET_free_non_null (username);
617 GNUNET_free_non_null (hostname);
619 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
622 host_id = ntohl (msg->host_id);
623 LOG_DEBUG ("Received ADDHOST %u message\n", host_id);
624 LOG_DEBUG ("-------host id: %u\n", host_id);
625 LOG_DEBUG ("-------hostname: %s\n", hostname);
626 if (NULL != username)
627 LOG_DEBUG ("-------username: %s\n", username);
629 LOG_DEBUG ("-------username: <not given>\n");
630 LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
632 GNUNET_TESTBED_host_create_with_id (host_id, hostname, username,
633 host_cfg, ntohs (msg->ssh_port));
634 GNUNET_free_non_null (username);
635 GNUNET_free (hostname);
636 GNUNET_CONFIGURATION_destroy (host_cfg);
640 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
643 reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage);
644 if (GNUNET_OK != host_list_add (host))
646 /* We are unable to add a host */
647 emsg = "A host exists with given host-id";
648 LOG_DEBUG ("%s: %u", emsg, host_id);
649 GNUNET_TESTBED_host_destroy (host);
650 reply_size += strlen (emsg) + 1;
651 reply = GNUNET_malloc (reply_size);
652 memcpy (&reply[1], emsg, strlen (emsg) + 1);
656 LOG_DEBUG ("Added host %u at %u\n", host_id, GST_context->host_id);
657 reply = GNUNET_malloc (reply_size);
659 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS);
660 reply->header.size = htons (reply_size);
661 reply->host_id = htonl (host_id);
662 GST_queue_message (client, &reply->header);
663 GNUNET_SERVER_receive_done (client, GNUNET_OK);
668 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages
671 * @param client identification of the client
672 * @param message the actual message
675 handle_slave_get_config (void *cls,
676 struct GNUNET_SERVER_Client *client,
677 const struct GNUNET_MessageHeader *message)
679 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
681 struct GNUNET_TESTBED_SlaveConfiguration *reply;
682 const struct GNUNET_CONFIGURATION_Handle *cfg;
691 msg = (struct GNUNET_TESTBED_SlaveGetConfigurationMessage *) message;
692 slave_id = ntohl (msg->slave_id);
693 op_id = GNUNET_ntohll (msg->operation_id);
694 if ((GST_slave_list_size <= slave_id) || (NULL == GST_slave_list[slave_id]))
696 /* FIXME: Add forwardings for this type of message here.. */
697 GST_send_operation_fail_msg (client, op_id, "Slave not found");
698 GNUNET_SERVER_receive_done (client, GNUNET_OK);
701 slave = GST_slave_list[slave_id];
702 GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (GST_host_list[slave->host_id])));
703 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
705 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
706 GNUNET_free (config);
707 reply_size = xconfig_size + sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
708 GNUNET_break (reply_size <= UINT16_MAX);
709 GNUNET_break (config_size <= UINT16_MAX);
710 reply = GNUNET_realloc (xconfig, reply_size);
711 (void) memmove (&reply[1], reply, xconfig_size);
712 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION);
713 reply->header.size = htons ((uint16_t) reply_size);
714 reply->slave_id = msg->slave_id;
715 reply->operation_id = msg->operation_id;
716 reply->config_size = htons ((uint16_t) config_size);
717 GST_queue_message (client, &reply->header);
718 GNUNET_SERVER_receive_done (client, GNUNET_OK);
723 * Clears the forwarded operations queue
728 struct ForwardedOperationContext *fopc;
730 while (NULL != (fopc = fopcq_head))
732 GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc);
733 GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc);
734 if (NULL != fopc->timeout_task)
735 GNUNET_SCHEDULER_cancel (fopc->timeout_task);
736 GNUNET_SERVER_client_drop (fopc->client);
740 GNUNET_free (fopc->cls);
742 case OP_SHUTDOWN_PEERS:
744 struct HandlerContext_ShutdownPeers *hc = fopc->cls;
746 GNUNET_assert (0 < hc->nslaves);
748 if (0 == hc->nslaves)
754 case OP_PEER_DESTROY:
756 case OP_OVERLAY_CONNECT:
757 case OP_LINK_CONTROLLERS:
758 case OP_GET_SLAVE_CONFIG:
759 case OP_MANAGE_SERVICE:
760 case OP_PEER_RECONFIGURE:
771 * Task to clean up and shutdown nicely
776 shutdown_task (void *cls)
778 struct MessageQueue *mq_entry;
781 LOG_DEBUG ("Shutting down testbed service\n");
782 /* cleanup any remaining forwarded operations */
789 GST_neighbour_list_clean();
791 /* Clear peer list */
792 GST_destroy_peers ();
793 /* Clear route list */
794 GST_route_list_clear ();
795 /* Clear GST_slave_list */
796 GST_slave_list_clear ();
797 /* Clear host list */
798 for (id = 0; id < GST_host_list_size; id++)
799 if (NULL != GST_host_list[id])
800 GNUNET_TESTBED_host_destroy (GST_host_list[id]);
801 GNUNET_free_non_null (GST_host_list);
802 if (NULL != GST_context)
804 GNUNET_free_non_null (GST_context->master_ip);
805 if (NULL != GST_context->system)
806 GNUNET_TESTING_system_destroy (GST_context->system, GNUNET_YES);
807 GNUNET_SERVER_client_drop (GST_context->client);
808 GNUNET_free (GST_context);
811 if (NULL != transmit_handle)
812 GNUNET_SERVER_notify_transmit_ready_cancel (transmit_handle);
813 while (NULL != (mq_entry = mq_head))
815 GNUNET_free (mq_entry->msg);
816 GNUNET_SERVER_client_drop (mq_entry->client);
817 GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
818 GNUNET_free (mq_entry);
820 GNUNET_free_non_null (hostname);
821 /* Free hello cache */
823 GST_connection_pool_destroy ();
824 GNUNET_TESTBED_operation_queue_destroy_ (GST_opq_openfds);
825 GST_opq_openfds = NULL;
826 GST_stats_destroy ();
827 GST_barriers_destroy ();
828 GNUNET_CONFIGURATION_destroy (GST_config);
833 * Callback for client disconnect
836 * @param client the client which has disconnected
839 client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
841 if (NULL == GST_context)
843 if (client == GST_context->client)
845 LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n");
846 /* should not be needed as we're terminated by failure to read
847 * from stdin, but if stdin fails for some reason, this shouldn't
848 * hurt for now --- might need to revise this later if we ever
849 * decide that master connections might be temporarily down
851 //GNUNET_SCHEDULER_shutdown ();
860 * @param server the initialized server
861 * @param cfg configuration to use
864 testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
865 const struct GNUNET_CONFIGURATION_Handle *cfg)
867 static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
868 {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT, 0},
869 {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, 0},
870 {&GST_handle_link_controllers, NULL,
871 GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
872 sizeof (struct GNUNET_TESTBED_ControllerLinkRequest)},
873 {&GST_handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER, 0},
874 {&GST_handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER,
875 sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)},
876 {&GST_handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_START_PEER,
877 sizeof (struct GNUNET_TESTBED_PeerStartMessage)},
878 {&GST_handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER,
879 sizeof (struct GNUNET_TESTBED_PeerStopMessage)},
880 {&GST_handle_peer_get_config, NULL,
881 GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION,
882 sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)},
883 {&GST_handle_overlay_connect, NULL,
884 GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT,
885 sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)},
886 {&GST_handle_remote_overlay_connect, NULL,
887 GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT, 0},
888 {&GST_handle_manage_peer_service, NULL,
889 GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE, 0},
890 {&handle_slave_get_config, NULL,
891 GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION,
892 sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)},
893 {&GST_handle_shutdown_peers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS,
894 sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage)},
895 {&GST_handle_peer_reconfigure, NULL,
896 GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER, 0},
897 {&GST_handle_barrier_init, NULL,
898 GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT, 0},
899 {&GST_handle_barrier_cancel, NULL,
900 GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL, 0},
901 {&GST_handle_barrier_status, NULL,
902 GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, 0},
906 unsigned long long num;
908 LOG_DEBUG ("Starting testbed\n");
910 GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED", "LOG_FILE",
913 GNUNET_break (GNUNET_OK == GNUNET_log_setup ("testbed", "DEBUG", logfile));
914 GNUNET_free (logfile);
916 GNUNET_assert (GNUNET_OK ==
917 GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED",
918 "CACHE_SIZE", &num));
919 GST_cache_init ((unsigned int) num);
920 GST_connection_pool_init ((unsigned int) num);
921 GNUNET_assert (GNUNET_OK ==
922 GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED",
923 "MAX_OPEN_FDS", &num));
924 GST_opq_openfds = GNUNET_TESTBED_operation_queue_create_
925 (OPERATION_QUEUE_TYPE_FIXED, (unsigned int) num);
926 GNUNET_assert (GNUNET_OK ==
927 GNUNET_CONFIGURATION_get_value_time (cfg, "TESTBED",
930 GNUNET_TIME_Relative *)
932 GNUNET_assert (GNUNET_OK ==
933 GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
934 "HOSTNAME", &hostname));
935 GST_config = GNUNET_CONFIGURATION_dup (cfg);
936 GNUNET_SERVER_add_handlers (server, message_handlers);
937 GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL);
938 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
939 LOG_DEBUG ("Testbed startup complete\n");
940 GST_stats_init (GST_config);
941 GST_barriers_init (GST_config);
946 * The starting point of execution
949 main (int argc, char *const *argv)
952 GNUNET_SERVICE_run (argc, argv,
954 GNUNET_SERVICE_OPTION_NONE,
955 &testbed_run, NULL)) ? 0 : 1;
958 /* end of gnunet-service-testbed.c */