2 This file is part of GNUnet.
3 (C) 2009 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.
23 * @brief API for accessing the ARM service
24 * @author Christian Grothoff
27 #include "gnunet_arm_service.h"
28 #include "gnunet_client_lib.h"
29 #include "gnunet_getopt_lib.h"
30 #include "gnunet_os_lib.h"
31 #include "gnunet_protocols.h"
32 #include "gnunet_server_lib.h"
38 GNUNET_ARM_Callback callback;
41 struct GNUNET_CLIENT_Connection *client;
42 const struct GNUNET_CONFIGURATION_Handle *cfg;
43 struct GNUNET_TIME_Absolute timeout;
49 arm_service_report (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
51 struct ArmContext *pos = cls;
56 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE))
58 if (pos->callback != NULL)
59 pos->callback (pos->cls, GNUNET_YES);
67 GNUNET_CONFIGURATION_get_value_filename (pos->cfg,
72 GNUNET_CONFIGURATION_get_value_filename (pos->cfg,
73 "arm", "CONFIG", &config)))
75 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
76 _("Configuration file or binary for ARM not known!\n"));
77 if (pos->callback != NULL)
78 pos->callback (pos->cls, GNUNET_SYSERR);
79 GNUNET_free_non_null (binary);
83 pid = GNUNET_OS_start_process (binary, binary, "-d", "-c", config,
92 if (pos->callback != NULL)
93 pos->callback (pos->cls, GNUNET_SYSERR);
97 /* FIXME: consider checking again to see if it worked!? */
98 if (pos->callback != NULL)
99 pos->callback (pos->cls, GNUNET_YES);
105 handle_response (void *cls, const struct GNUNET_MessageHeader *msg)
107 struct ArmContext *sc = cls;
112 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
113 _("Error receiving response from ARM service\n"));
114 GNUNET_CLIENT_disconnect (sc->client);
115 if (sc->callback != NULL)
116 sc->callback (sc->cls, GNUNET_SYSERR);
121 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
122 _("Received response from ARM service\n"));
124 switch (ntohs (msg->type))
126 case GNUNET_MESSAGE_TYPE_ARM_IS_UP:
129 case GNUNET_MESSAGE_TYPE_ARM_IS_DOWN:
132 case GNUNET_MESSAGE_TYPE_ARM_IS_UNKNOWN:
139 GNUNET_CLIENT_disconnect (sc->client);
140 if (sc->callback != NULL)
141 sc->callback (sc->cls, ret);
147 send_service_msg (void *cls, size_t size, void *buf)
149 struct ArmContext *sctx = cls;
150 struct GNUNET_MessageHeader *msg;
155 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
156 _("Error while trying to transmit to ARM service\n"));
157 GNUNET_CLIENT_disconnect (sctx->client);
158 if (sctx->callback != NULL)
159 sctx->callback (sctx->cls, GNUNET_SYSERR);
160 GNUNET_free (sctx->service_name);
165 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
166 _("Transmitting service request to ARM.\n"));
168 slen = strlen (sctx->service_name) + 1;
169 GNUNET_assert (size >= slen);
171 msg->size = htons (sizeof (struct GNUNET_MessageHeader) + slen);
172 msg->type = htons (sctx->type);
173 memcpy (&msg[1], sctx->service_name, slen);
174 GNUNET_free (sctx->service_name);
175 sctx->service_name = NULL;
176 GNUNET_CLIENT_receive (sctx->client,
179 GNUNET_TIME_absolute_get_remaining (sctx->timeout));
180 return slen + sizeof (struct GNUNET_MessageHeader);
185 * Start or stop a service.
187 * @param service_name name of the service
188 * @param cfg configuration to use (needed to contact ARM;
189 * the ARM service may internally use a different
190 * configuration to determine how to start the service).
191 * @param sched scheduler to use
192 * @param timeout how long to wait before failing for good
193 * @param cb callback to invoke when service is ready
194 * @param cb_cls closure for callback
197 change_service (const char *service_name,
198 const struct GNUNET_CONFIGURATION_Handle *cfg,
199 struct GNUNET_SCHEDULER_Handle *sched,
200 struct GNUNET_TIME_Relative timeout,
201 GNUNET_ARM_Callback cb, void *cb_cls, uint16_t type)
203 struct GNUNET_CLIENT_Connection *client;
204 struct ArmContext *sctx;
207 slen = strlen (service_name) + 1;
208 if (slen + sizeof (struct GNUNET_MessageHeader) >
209 GNUNET_SERVER_MAX_MESSAGE_SIZE)
213 cb (cb_cls, GNUNET_NO);
216 client = GNUNET_CLIENT_connect (sched, "arm", cfg);
219 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
220 _("Failed to connect to ARM service\n"));
222 cb (cb_cls, GNUNET_SYSERR);
226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
227 _("ARM requests starting of service `%s'.\n"), service_name);
229 sctx = GNUNET_malloc (sizeof (struct ArmContext));
232 sctx->client = client;
233 sctx->service_name = GNUNET_strdup (service_name);
234 sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
237 GNUNET_CLIENT_notify_transmit_ready (client,
240 GNUNET_MessageHeader),
241 timeout, &send_service_msg, sctx))
243 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
244 _("Failed to transmit request to ARM service\n"));
245 GNUNET_free (sctx->service_name);
248 cb (cb_cls, GNUNET_SYSERR);
249 GNUNET_CLIENT_disconnect (client);
258 * @param service_name name of the service
259 * @param cfg configuration to use (needed to contact ARM;
260 * the ARM service may internally use a different
261 * configuration to determine how to start the service).
262 * @param sched scheduler to use
263 * @param timeout how long to wait before failing for good
264 * @param cb callback to invoke when service is ready
265 * @param cb_cls closure for callback
268 GNUNET_ARM_start_service (const char *service_name,
269 const struct GNUNET_CONFIGURATION_Handle *cfg,
270 struct GNUNET_SCHEDULER_Handle *sched,
271 struct GNUNET_TIME_Relative timeout,
272 GNUNET_ARM_Callback cb, void *cb_cls)
274 struct ArmContext *sctx;
276 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
277 _("Starting service `%s'\n"), service_name);
278 if (0 == strcmp ("arm", service_name))
280 sctx = GNUNET_malloc (sizeof (struct ArmContext));
284 GNUNET_CLIENT_service_test (sched,
286 cfg, timeout, &arm_service_report, sctx);
289 change_service (service_name,
291 sched, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_START);
300 * @param service_name name of the service
301 * @param cfg configuration to use (needed to contact ARM;
302 * the ARM service may internally use a different
303 * configuration to determine how to start the service).
304 * @param sched scheduler to use
305 * @param timeout how long to wait before failing for good
306 * @param cb callback to invoke when service is ready
307 * @param cb_cls closure for callback
310 GNUNET_ARM_stop_service (const char *service_name,
311 const struct GNUNET_CONFIGURATION_Handle *cfg,
312 struct GNUNET_SCHEDULER_Handle *sched,
313 struct GNUNET_TIME_Relative timeout,
314 GNUNET_ARM_Callback cb, void *cb_cls)
316 struct GNUNET_CLIENT_Connection *client;
318 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
319 _("Stopping service `%s'\n"), service_name);
320 if (0 == strcmp ("arm", service_name))
322 client = GNUNET_CLIENT_connect (sched, "arm", cfg);
326 cb (cb_cls, GNUNET_SYSERR);
329 GNUNET_CLIENT_service_shutdown (client);
330 GNUNET_CLIENT_disconnect (client);
332 cb (cb_cls, GNUNET_NO);
335 change_service (service_name,
337 sched, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_STOP);
340 /* end of arm_api.c */