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 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:
136 GNUNET_CLIENT_disconnect (sc->client);
137 if (sc->callback != NULL)
138 sc->callback (sc->cls, ret);
144 send_service_msg (void *cls, size_t size, void *buf)
146 struct ArmContext *sctx = cls;
147 struct GNUNET_MessageHeader *msg;
152 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
153 _("Error while trying to transmit to ARM service\n"));
154 GNUNET_CLIENT_disconnect (sctx->client);
155 if (sctx->callback != NULL)
156 sctx->callback (sctx->cls, GNUNET_SYSERR);
157 GNUNET_free (sctx->service_name);
162 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
163 _("Transmitting service request to ARM.\n"));
165 slen = strlen (sctx->service_name) + 1;
166 GNUNET_assert (size >= slen);
168 msg->size = htons (sizeof (struct GNUNET_MessageHeader) + slen);
169 msg->type = htons (sctx->type);
170 memcpy (&msg[1], sctx->service_name, slen);
171 GNUNET_free (sctx->service_name);
172 sctx->service_name = NULL;
173 GNUNET_CLIENT_receive (sctx->client,
176 GNUNET_TIME_absolute_get_remaining (sctx->timeout));
177 return slen + sizeof (struct GNUNET_MessageHeader);
182 * Start or stop a service.
184 * @param service_name name of the service
185 * @param cfg configuration to use (needed to contact ARM;
186 * the ARM service may internally use a different
187 * configuration to determine how to start the service).
188 * @param sched scheduler to use
189 * @param timeout how long to wait before failing for good
190 * @param cb callback to invoke when service is ready
191 * @param cb_cls closure for callback
194 change_service (const char *service_name,
195 struct GNUNET_CONFIGURATION_Handle *cfg,
196 struct GNUNET_SCHEDULER_Handle *sched,
197 struct GNUNET_TIME_Relative timeout,
198 GNUNET_ARM_Callback cb, void *cb_cls, uint16_t type)
200 struct GNUNET_CLIENT_Connection *client;
201 struct ArmContext *sctx;
204 slen = strlen (service_name) + 1;
205 if (slen + sizeof (struct GNUNET_MessageHeader) >
206 GNUNET_SERVER_MAX_MESSAGE_SIZE)
210 cb (cb_cls, GNUNET_NO);
213 client = GNUNET_CLIENT_connect (sched, "arm", cfg);
216 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
217 _("Failed to connect to ARM service\n"));
219 cb (cb_cls, GNUNET_SYSERR);
223 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
224 _("ARM requests starting of service `%s'.\n"), service_name);
226 sctx = GNUNET_malloc (sizeof (struct ArmContext));
229 sctx->client = client;
230 sctx->service_name = GNUNET_strdup (service_name);
231 sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
234 GNUNET_CLIENT_notify_transmit_ready (client,
237 GNUNET_MessageHeader),
238 timeout, &send_service_msg, sctx))
240 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
241 _("Failed to transmit request to ARM service\n"));
242 GNUNET_free (sctx->service_name);
245 cb (cb_cls, GNUNET_SYSERR);
246 GNUNET_CLIENT_disconnect (client);
255 * @param service_name name of the service
256 * @param cfg configuration to use (needed to contact ARM;
257 * the ARM service may internally use a different
258 * configuration to determine how to start the service).
259 * @param sched scheduler to use
260 * @param timeout how long to wait before failing for good
261 * @param cb callback to invoke when service is ready
262 * @param cb_cls closure for callback
265 GNUNET_ARM_start_service (const char *service_name,
266 struct GNUNET_CONFIGURATION_Handle *cfg,
267 struct GNUNET_SCHEDULER_Handle *sched,
268 struct GNUNET_TIME_Relative timeout,
269 GNUNET_ARM_Callback cb, void *cb_cls)
271 struct ArmContext *sctx;
273 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
274 _("Starting service `%s'\n"), service_name);
275 if (0 == strcmp ("arm", service_name))
277 sctx = GNUNET_malloc (sizeof (struct ArmContext));
281 GNUNET_CLIENT_service_test (sched,
283 cfg, timeout, &arm_service_report, sctx);
286 change_service (service_name,
288 sched, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_START);
297 * @param service_name name of the service
298 * @param cfg configuration to use (needed to contact ARM;
299 * the ARM service may internally use a different
300 * configuration to determine how to start the service).
301 * @param sched scheduler to use
302 * @param timeout how long to wait before failing for good
303 * @param cb callback to invoke when service is ready
304 * @param cb_cls closure for callback
307 GNUNET_ARM_stop_service (const char *service_name,
308 struct GNUNET_CONFIGURATION_Handle *cfg,
309 struct GNUNET_SCHEDULER_Handle *sched,
310 struct GNUNET_TIME_Relative timeout,
311 GNUNET_ARM_Callback cb, void *cb_cls)
313 struct GNUNET_CLIENT_Connection *client;
315 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
316 _("Stopping service `%s'\n"), service_name);
317 if (0 == strcmp ("arm", service_name))
319 client = GNUNET_CLIENT_connect (sched, "arm", cfg);
323 cb (cb_cls, GNUNET_SYSERR);
326 GNUNET_CLIENT_service_shutdown (client);
327 GNUNET_CLIENT_disconnect (client);
329 cb (cb_cls, GNUNET_NO);
332 change_service (service_name,
334 sched, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_STOP);
337 /* end of arm_api.c */