2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
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.
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testbed/gnunet-service-testbed.c
23 * @brief implementation of the TESTBED service
24 * @author Sree Harsha Totakura
28 #include "gnunet_service_lib.h"
29 #include "gnunet_server_lib.h"
32 #include "gnunet_testbed_service.h"
34 #define LOG(kind,...) \
35 GNUNET_log (kind, __VA_ARGS__)
41 * The client handle associated with this context
43 struct GNUNET_SERVER_Client *client;
46 * Event mask of event to be responded in this context
51 * Our host id according to this context
60 static struct GNUNET_DISK_FileHandle *fh;
63 * The master context; generated with the first INIT message
65 static struct Context *master_context;
68 * The shutdown task handle
70 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
74 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
77 * @param client identification of the client
78 * @param message the actual message
81 handle_init (void *cls,
82 struct GNUNET_SERVER_Client *client,
83 const struct GNUNET_MessageHeader *message)
85 const struct GNUNET_TESTBED_InitMessage *msg;
87 if (NULL != master_context)
90 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
93 msg = (const struct GNUNET_TESTBED_InitMessage *) message;
94 master_context = GNUNET_malloc (sizeof (struct Context));
95 master_context->client = client;
96 master_context->host_id = ntohl (msg->host_id);
97 master_context->event_mask = GNUNET_ntohll (msg->event_mask);
98 GNUNET_SERVER_client_keep (client);
99 LOG (GNUNET_ERROR_TYPE_DEBUG,
100 "Created master context with host ID: %u\n", master_context->host_id);
101 GNUNET_SERVER_receive_done (client, GNUNET_OK);
106 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
109 * @param client identification of the client
110 * @param message the actual message
113 handle_addhost (void *cls,
114 struct GNUNET_SERVER_Client *client,
115 const struct GNUNET_MessageHeader *message)
117 struct GNUNET_TESTBED_Host *host;
118 const struct GNUNET_TESTBED_AddHostMessage *msg;
121 uint16_t username_length;
122 uint16_t hostname_length;
124 msg = (const struct GNUNET_TESTBED_AddHostMessage *) message;
125 username_length = ntohs (msg->user_name_length);
126 username_length = (0 == username_length) ? 0 : username_length + 1;
127 username = (char *) &(msg[1]);
128 hostname = username + username_length;
129 if (ntohs (message->size) <=
130 (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length))
133 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
136 hostname_length = ntohs (message->size)
137 - (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length);
138 if (strlen (hostname) != hostname_length)
141 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
144 host = GNUNET_TESTBED_host_create (hostname, username, ntohs
146 /* Store host in a hashmap? But the host_id will be different */
147 /* hashmap? maybe array? 4-8 bytes/host and O(1) lookup vs.
148 > 80 bytes for hash map with slightly worse lookup; only
149 if we really get a tiny fraction of the hosts, the hash
150 map would result in any savings... (GNUNET_array_grow) */
155 * Task to clean up and shutdown nicely
158 * @param tc the TaskContext from scheduler
161 shutdown_task (void *cls,
162 const struct GNUNET_SCHEDULER_TaskContext *tc)
164 shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
165 GNUNET_SCHEDULER_shutdown ();
166 LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
169 GNUNET_DISK_file_close (fh);
172 GNUNET_free_non_null (master_context);
173 master_context = NULL;
178 * Callback for client disconnect
181 * @param client the client which has disconnected
184 client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
186 if (NULL == master_context)
188 if (client == master_context->client)
190 LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n");
191 GNUNET_SERVER_client_drop (client);
192 /* should not be needed as we're terminated by failure to read
193 from stdin, but if stdin fails for some reason, this shouldn't
194 hurt for now --- might need to revise this later if we ever
195 decide that master connections might be temporarily down
197 GNUNET_SCHEDULER_shutdown ();
206 * @param server the initialized server
207 * @param cfg configuration to use
210 testbed_run (void *cls,
211 struct GNUNET_SERVER_Handle *server,
212 const struct GNUNET_CONFIGURATION_Handle *cfg)
214 static const struct GNUNET_SERVER_MessageHandler message_handlers[] =
216 {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT,
217 sizeof (struct GNUNET_TESTBED_InitMessage)},
218 {&handle_addhost, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST, 0},
222 GNUNET_SERVER_add_handlers (server,
224 GNUNET_SERVER_disconnect_notify (server,
225 &client_disconnect_cb,
227 fh = GNUNET_DISK_get_handle_from_native (stdin);
230 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
235 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
243 * The starting point of execution
245 int main (int argc, char *const *argv)
249 GNUNET_SERVICE_run (argc,
252 GNUNET_SERVICE_OPTION_NONE,