HomePort
daemon.c
Go to the documentation of this file.
1 /*
2  * Copyright 2011 Aalborg University. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are
5  * permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  * conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  * of conditions and the following disclaimer in the documentation and/or other materials
12  * provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY Aalborg University ''AS IS'' AND ANY EXPRESS OR IMPLIED
15  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Aalborg University OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  * The views and conclusions contained in the software and documentation are those of the
25  * authors and should not be interpreted as representing official policies, either expressed
26  */
27 
28 #include "request.h"
29 #include "discovery.h"
30 #include "daemon.h"
31 #include "event.h"
32 #include "value.h"
33 #include "log.h"
34 #include "model.h"
35 
36 static hpd_error_t daemon_options_parse(hpd_t *hpd, int argc, char **argv);
37 
38 static void daemon_on_signal(hpd_ev_loop_t *loop, ev_signal *w, int revents)
39 {
40  ev_break(loop, EVBREAK_ALL);
41 }
42 
43 static int daemon_on_parse_opt(int key, char *arg, struct argp_state *state)
44 {
45  hpd_error_t rc;
46  hpd_t *hpd = state->input;
47 
48  if (key >= 0xff && (key - 0xff) < hpd->module_options_count) {
49  const hpd_module_t *module = hpd->option2module[key-0xff];
50  const char *name = hpd->option2name[key - 0xff];
51  while ((name++)[0] != '-');
52  switch ((rc = module->def.on_parse_opt(module->data, name, arg))) {
53  case HPD_E_SUCCESS:
54  return 0;
55  case HPD_E_ARGUMENT:
56  LOG_DEBUG("Module '%s' did not recognise the option '%s'.", module->id, name);
57  return ARGP_ERR_UNKNOWN;
58  default:
59  // TODO Wrong return type
60  return rc;
61  }
62  }
63 
64  switch (key) {
65  case 'c': {
66  // TODO Skipping some checks here...
67  LOG_WARN("Configuration files are still very much in an early alpha state.");
68  char *buffer = NULL;
69  FILE *fp = fopen(arg, "rb");
70  if (fp) {
71  fseek(fp, 0, SEEK_END);
72  // TODO Puts a limit on file size (recheck the casting bit)
73  size_t len = (size_t) ftell(fp);
74  fseek(fp, 0, SEEK_SET);
75  HPD_CALLOC(buffer, len, char);
76  fread(buffer, 1, len, fp);
77  fclose(fp);
78  }
79  if (buffer) {
80  int argc = 1;
81  char **argv = NULL;
82  HPD_REALLOC(argv, argc, char *);
83  argv[0] = hpd->argv0;
84  for (char *a = strtok(buffer, " \n\t"); a; a = strtok(NULL, " ")) {
85  HPD_REALLOC(argv, argc + 1, char *);
86  argv[argc] = a;
87  argc++;
88  }
89  daemon_options_parse(hpd, argc, argv); // TODO Check error
90  free(argv);
91  }
92  return 0;
93  }
94  default:
95  return ARGP_ERR_UNKNOWN;
96  }
97 
98  alloc_error:
99  // TODO What ?
100  // TODO Free up a lot of stuff...
101  return 0;
102 }
103 
104 static hpd_error_t daemon_add_global_option(hpd_t *hpd, const char *name, int key, const char *arg, int flags, const char *doc)
105 {
106  char *name_alloc = NULL, *arg_alloc = NULL, *doc_alloc = NULL;
107  hpd_argp_option_t option = { 0 };
108  hpd_argp_option_t empty = { 0 };
109 
110  if (name) HPD_STR_CPY(name_alloc, name);
111  if (arg) HPD_STR_CPY(arg_alloc, arg);
112  if (doc) HPD_STR_CPY(doc_alloc, doc);
113  option.name = name_alloc;
114  option.key = key;
115  option.arg = arg_alloc;
116  option.flags = flags;
117  option.doc = doc_alloc;
118 
120  hpd->options[hpd->options_count] = option;
121  hpd->options[hpd->options_count+1] = empty;
122  hpd->options_count++;
123 
124  return HPD_E_SUCCESS;
125 
126  alloc_error:
127  free(name_alloc);
128  free(arg_alloc);
129  free(doc_alloc);
131 }
132 
134 {
135  // Create event loop
136  hpd->loop = ev_loop_new(EVFLAG_AUTO);
137  if (!hpd->loop) LOG_RETURN_E_ALLOC();
138  return HPD_E_SUCCESS;
139 }
140 
142 {
143  // Destroy event loop
144  ev_loop_destroy(hpd->loop);
145  hpd->loop = NULL;
146 }
147 
148 static void daemon_loop_run(hpd_t *hpd)
149 {
150  // Start signal watchers
151  ev_signal_start(hpd->loop, &hpd->sigint_watcher);
152  ev_signal_start(hpd->loop, &hpd->sigterm_watcher);
153 
154  // Run until we are stopped
155  // TODO Return value of ev_run can be used to run until all watchers have stopped (e.g. nice shutdown)
156  ev_run(hpd->loop, 0);
157 
158  // Stop signal watchers
159  ev_signal_stop(hpd->loop, &hpd->sigterm_watcher);
160  ev_signal_stop(hpd->loop, &hpd->sigint_watcher);
161 }
162 
164 {
165  // Call on_create() on modules
166  hpd_error_t rc;
167  hpd_module_t *module;
168  TAILQ_FOREACH(module, &hpd->modules, HPD_TAILQ_FIELD)
169  if ((rc = module->def.on_create(&module->data, module)) != HPD_E_SUCCESS)
170  goto module_create_error;
171  return HPD_E_SUCCESS;
172 
173  module_create_error:
174  for (; module; module = TAILQ_PREV(module, hpd_modules, HPD_TAILQ_FIELD))
175  if (module->data) module->def.on_destroy(module->data);
176  return rc;
177 }
178 
180 {
181  // Call on_destroy on modules
182  hpd_error_t rc;
183  hpd_module_t *module;
184  TAILQ_FOREACH_REVERSE(module, &hpd->modules, hpd_modules, HPD_TAILQ_FIELD)
185  if (module->data) {
186  if ((rc = module->def.on_destroy(module->data)) != HPD_E_SUCCESS)
187  goto module_destroy_error;
188  module->data = NULL;
189  }
190  return HPD_E_SUCCESS;
191 
192  module_destroy_error:
193  for (; module; module = TAILQ_PREV(module, hpd_modules, HPD_TAILQ_FIELD))
194  if (module->data) module->def.on_destroy(module->data);
195  return rc;
196 }
197 
199 {
200  hpd_error_t rc, rc2;
201  hpd_module_t *module;
202 
203  // Call on_start() on modules
204  TAILQ_FOREACH(module, &hpd->modules, HPD_TAILQ_FIELD)
205  if ((rc = module->def.on_start(module->data, hpd)) != HPD_E_SUCCESS)
206  goto module_error;
207 
208  return HPD_E_SUCCESS;
209 
210  module_error:
211  for (module = TAILQ_PREV(module, hpd_modules, HPD_TAILQ_FIELD); module; module = TAILQ_PREV(module, hpd_modules, HPD_TAILQ_FIELD))
212  if ((rc2 = module->def.on_stop(module->data, hpd)))
213  LOG_ERROR("Failed to stop module [code: %i].", rc2);
214  return rc;
215 }
216 
218 {
219  hpd_error_t rc, rc2;
220  hpd_module_t *module;
221 
222  // Call on_stop() on modules
223  TAILQ_FOREACH_REVERSE(module, &hpd->modules, hpd_modules, HPD_TAILQ_FIELD)
224  if ((rc = module->def.on_stop(module->data, hpd)) != HPD_E_SUCCESS)
225  goto module_error;
226 
227  return HPD_E_SUCCESS;
228 
229  module_error:
230  for (module = TAILQ_PREV(module, hpd_modules, HPD_TAILQ_FIELD); module; module = TAILQ_PREV(module, hpd_modules, HPD_TAILQ_FIELD))
231  if ((rc2 = module->def.on_stop(module->data, hpd)))
232  LOG_ERROR("Failed to stop module [code: %i].", rc2);
233  return rc;
234 }
235 
237 {
238  hpd_error_t rc;
239 
241  if ((rc = daemon_add_global_option(hpd, "conf", 'c', "file", 0, "Load arguments from configuration file"))) goto error;
242 
243  return HPD_E_SUCCESS;
244 
245  alloc_error:
247 
248  error:
249  free(hpd->options);
250  hpd->options = NULL;
251  return rc;
252 }
253 
255 {
256  // Deallocate option memory
257  hpd_argp_option_t empty = { 0 };
258  for (hpd_argp_option_t *option = hpd->options; memcmp(option, &empty, sizeof(hpd_argp_option_t)); option++) {
259  free((void *) option->name);
260  free((void *) option->arg);
261  free((void *) option->doc);
262  }
263  free(hpd->options);
264  hpd->options = NULL;
265  free(hpd->option2module);
266  hpd->option2module = NULL;
267  free(hpd->option2name);
268  hpd->option2name = NULL;
269 }
270 
271 static hpd_error_t daemon_options_parse(hpd_t *hpd, int argc, char **argv)
272 {
273  // Parse options
274  struct argp argp = {hpd->options, daemon_on_parse_opt };
275  if (argp_parse(&argp, argc, argv, 0, 0, hpd)) {
276  LOG_DEBUG("Error while parsing arguments.");
277  return HPD_E_ARGUMENT;
278  }
279  return HPD_E_SUCCESS;
280 }
281 
283 {
285  TAILQ_INIT(&hpd->configuration->adapters);
286  TAILQ_INIT(&hpd->configuration->listeners);
287  hpd->configuration->hpd = hpd;
288  return HPD_E_SUCCESS;
289 
290  alloc_error:
292 }
293 
295 {
296  hpd_error_t rc;
299  free(hpd->configuration);
300  hpd->configuration = NULL;
301  return HPD_E_SUCCESS;
302 
303  map_error:
304  LOG_RETURN(rc, "Free function returned an error [code: %i]", rc);
305 }
306 
308 {
309  hpd_error_t rc = HPD_E_SUCCESS, tmp;
310 
311  // Stop other watchers
312  hpd_ev_async_t *async, *async_tmp;
313  TAILQ_FOREACH_SAFE(async, &hpd->request_watchers, HPD_TAILQ_FIELD, async_tmp) {
314  TAILQ_REMOVE(&hpd->request_watchers, async, HPD_TAILQ_FIELD);
315  ev_async_stop(hpd->loop, &async->watcher);
316  tmp = request_free_request(async->request);
317  if (!rc) rc = tmp;
318  else LOG_ERROR("free function failed [code: %i]", tmp);
319  free(async);
320  }
321  TAILQ_FOREACH_SAFE(async, &hpd->respond_watchers, HPD_TAILQ_FIELD, async_tmp) {
322  TAILQ_REMOVE(&hpd->respond_watchers, async, HPD_TAILQ_FIELD);
323  ev_async_stop(hpd->loop, &async->watcher);
324  tmp = request_free_response(async->response);
325  if (!rc) rc = tmp;
326  else LOG_ERROR("free function failed [code: %i]", tmp);
327  free(async);
328  }
329  TAILQ_FOREACH_SAFE(async, &hpd->changed_watchers, HPD_TAILQ_FIELD, async_tmp) {
330  TAILQ_REMOVE(&hpd->changed_watchers, async, HPD_TAILQ_FIELD);
331  ev_async_stop(hpd->loop, &async->watcher);
332  tmp = discovery_free_sid(async->service);
333  if (!rc) rc = tmp;
334  else LOG_ERROR("free function failed [code: %i]", tmp);
335  tmp = value_free(async->value);
336  if (!rc) rc = tmp;
337  else LOG_ERROR("free function failed [code: %i]", tmp);
338  free(async);
339  }
340  TAILQ_FOREACH_SAFE(async, &hpd->attached_watchers, HPD_TAILQ_FIELD, async_tmp) {
341  TAILQ_REMOVE(&hpd->attached_watchers, async, HPD_TAILQ_FIELD);
342  ev_async_stop(hpd->loop, &async->watcher);
343  tmp = discovery_free_did(async->device);
344  if (!rc) rc = tmp;
345  else LOG_ERROR("free function failed [code: %i]", tmp);
346  free(async);
347  }
348  TAILQ_FOREACH_SAFE(async, &hpd->detached_watchers, HPD_TAILQ_FIELD, async_tmp) {
349  TAILQ_REMOVE(&hpd->detached_watchers, async, HPD_TAILQ_FIELD);
350  ev_async_stop(hpd->loop, &async->watcher);
351  tmp = discovery_free_did(async->device);if (!rc) rc = tmp;
352  else LOG_ERROR("free function failed [code: %i]", tmp);
353  free(async);
354  }
355 
356  return rc;
357 }
358 
360 {
361  HPD_CALLOC(*hpd, 1, hpd_t);
362  TAILQ_INIT(&(*hpd)->modules);
363  TAILQ_INIT(&(*hpd)->request_watchers);
364  TAILQ_INIT(&(*hpd)->respond_watchers);
365  TAILQ_INIT(&(*hpd)->changed_watchers);
366  TAILQ_INIT(&(*hpd)->attached_watchers);
367  TAILQ_INIT(&(*hpd)->detached_watchers);
368  ev_signal_init(&(*hpd)->sigint_watcher, daemon_on_signal, SIGINT);
369  ev_signal_init(&(*hpd)->sigterm_watcher, daemon_on_signal, SIGTERM);
370  (*hpd)->sigint_watcher.data = hpd;
371  (*hpd)->sigterm_watcher.data = hpd;
372  return HPD_E_SUCCESS;
373 
374  alloc_error:
375  if (*hpd) {
376  if ((*hpd)->options) free((*hpd)->options);
377  free(*hpd);
378  }
380 }
381 
383 {
384  hpd_module_t *module, *module_tmp;
385  TAILQ_FOREACH_SAFE(module, &hpd->modules, HPD_TAILQ_FIELD, module_tmp) {
386  TAILQ_REMOVE(&hpd->modules, module, HPD_TAILQ_FIELD);
387  free(module->id);
388  free(module);
389  }
390  free(hpd);
391  return HPD_E_SUCCESS;
392 }
393 
394 hpd_error_t daemon_add_module(hpd_t *hpd, const char *id, const hpd_module_def_t *module_def)
395 {
396  hpd_module_t *module;
397  HPD_CALLOC(module, 1, hpd_module_t);
398  module->hpd = hpd;
399  module->def = *module_def;
400  HPD_STR_CPY(module->id, id);
401  TAILQ_INSERT_TAIL(&hpd->modules, module, HPD_TAILQ_FIELD);
402  return HPD_E_SUCCESS;
403 
404  alloc_error:
405  if (module) free(module);
407 }
408 
409 hpd_error_t daemon_add_option(const hpd_module_t *context, const char *name, const char *arg, int flags,
410  const char *doc)
411 {
412  hpd_error_t rc;
413  hpd_t *hpd = context->hpd;
414 
415  char *name_cat;
416  HPD_CALLOC(name_cat, strlen(name)+strlen(context->id)+2, char);
417  strcpy(name_cat, context->id);
418  strcat(name_cat, "-");
419  strcat(name_cat, name);
420 
421  int key = 0xff + hpd->module_options_count;
422 
423  if ((rc = daemon_add_global_option(hpd, name_cat, key, arg, flags, doc))) goto error;
424 
426  hpd->option2module[hpd->module_options_count] = context;
427 
428  HPD_REALLOC(hpd->option2name, hpd->module_options_count+1, const char *);
429  hpd->option2name[hpd->module_options_count] = hpd->options[hpd->options_count-1].name;
430 
431  hpd->module_options_count++;
432 
433  free(name_cat);
434  return HPD_E_SUCCESS;
435 
436  error:
437  free(name_cat);
438  return rc;
439 
440  alloc_error:
441  // TODO This leaves everything in a bit of a weird state
442  free(name_cat);
444 }
445 
446 hpd_error_t daemon_start(hpd_t *hpd, int argc, char *argv[])
447 {
448  hpd_error_t rc, rc2;
449 
450  hpd->argv0 = argv[0];
451 
452  // Allocate run-time and option memory
453  if ((rc = daemon_runtime_create(hpd))) goto runtime_create_error;
454  if ((rc = daemon_options_create(hpd))) goto options_create_error;
455  if ((rc = daemon_modules_create(hpd))) goto modules_create_error;
456  if ((rc = daemon_options_parse(hpd, argc, argv))) goto options_parse_error;
458  if ((rc = daemon_loop_create(hpd))) goto loop_create_error;
459  if ((rc = daemon_modules_start(hpd))) goto modules_start_error;
460  daemon_loop_run(hpd);
461  if ((rc = daemon_modules_stop(hpd))) goto modules_stop_error;
462  if ((rc = daemon_watchers_stop(hpd))) goto watchers_stop_error;
463  daemon_loop_destroy(hpd);
464  if ((rc = daemon_modules_destroy(hpd))) goto modules_destroy_error;
465  if ((rc = daemon_runtime_destroy(hpd))) goto runtime_destroy_error;
466 
467  // Return
468  return HPD_E_SUCCESS;
469 
470  // Return in a nice state if an error occur
471  options_parse_error:
472  if ((rc2 = daemon_modules_destroy(hpd))) LOG_ERROR("Failed to destroy modules [code: %i]", rc2);
473  modules_create_error:
475  options_create_error:
476  if ((rc2 = daemon_runtime_destroy(hpd))) LOG_ERROR("Failed to destroy runtime [code: %i]", rc2);
477  runtime_create_error:
478  return rc;
479  modules_start_error:
480  modules_stop_error:
481  if ((rc2 = daemon_watchers_stop(hpd))) LOG_ERROR("Failed to stop watchers [code: %i]", rc2);
482  watchers_stop_error:
483  daemon_loop_destroy(hpd);
484  loop_create_error:
485  if ((rc2 = daemon_modules_destroy(hpd))) LOG_ERROR("Failed to destroy modules [code: %i]", rc2);
486  modules_destroy_error:
487  if ((rc2 = daemon_runtime_destroy(hpd))) LOG_ERROR("Failed to destroy runtime [code: %i]", rc2);
488  runtime_destroy_error:
489  return rc;
490 }
491 
493 {
494  ev_break(hpd->loop, EVBREAK_ALL);
495  return HPD_E_SUCCESS;
496 }
497 
498 hpd_error_t daemon_get_id(const hpd_module_t *context, const char **id)
499 {
500  (*id) = context->id;
501  return HPD_E_SUCCESS;
502 }
503 
505 {
506  (*loop) = hpd->loop;
507  return HPD_E_SUCCESS;
508 }
const hpd_module_t ** option2module
Definition: daemon.h:59
static hpd_error_t daemon_runtime_destroy(hpd_t *hpd)
Definition: daemon.c:294
const char ** option2name
Definition: daemon.h:60
hpd_ev_loop_t * loop
Definition: daemon.h:51
hpd_error_t discovery_free_adapter(hpd_adapter_t *adapter)
Definition: discovery.c:120
void * data
Definition: daemon.h:94
static hpd_error_t daemon_options_create(hpd_t *hpd)
Definition: daemon.c:236
hpd_parse_opt_f on_parse_opt
Definition: hpd_types.h:205
static hpd_error_t daemon_modules_create(const hpd_t *hpd)
Definition: daemon.c:163
#define HPD_STR_CPY(DST, SRC)
Definition: hpd_common.h:64
hpd_modules_t modules
Definition: daemon.h:55
char * id
Definition: daemon.h:93
static void daemon_loop_destroy(hpd_t *hpd)
Definition: daemon.c:141
hpd_error_t daemon_stop(const hpd_t *hpd)
Definition: daemon.c:492
struct argp_option hpd_argp_option_t
Definition: daemon.h:43
#define LOG_RETURN_E_ALLOC()
Definition: log.h:51
hpd_error_t daemon_get_loop(const hpd_t *hpd, hpd_ev_loop_t **loop)
Definition: daemon.c:504
#define HPD_TAILQ_MAP_REMOVE(LIST, FUNC, TYPE, RC)
Definition: hpd_queue.h:39
static hpd_error_t daemon_modules_start(hpd_t *hpd)
Definition: daemon.c:198
static void daemon_on_signal(hpd_ev_loop_t *loop, ev_signal *w, int revents)
Definition: daemon.c:38
static hpd_error_t daemon_runtime_create(hpd_t *hpd)
Definition: daemon.c:282
static hpd_error_t daemon_modules_stop(hpd_t *hpd)
Definition: daemon.c:217
static void daemon_loop_run(hpd_t *hpd)
Definition: daemon.c:148
free(data.url)
ev_signal sigterm_watcher
Definition: daemon.h:54
hpd_error_t discovery_free_did(hpd_device_id_t *id)
Definition: discovery_id.c:178
hpd_ev_asyncs_t respond_watchers
Definition: daemon.h:62
static hpd_error_t daemon_watchers_stop(hpd_t *hpd)
Definition: daemon.c:307
hpd_error_t daemon_get_id(const hpd_module_t *context, const char **id)
Definition: daemon.c:498
#define HPD_TAILQ_FIELD
Definition: hpd_queue.h:37
hpd_listeners_t listeners
Definition: model.h:60
hpd_argp_option_t * options
Definition: daemon.h:58
int options_count
Definition: daemon.h:57
#define HPD_CALLOC(PTR, NUM, CAST)
Allocates and zeros a structure.
Definition: hpd_common.h:44
ev_async watcher
Definition: daemon.h:72
hpd_error_t daemon_start(hpd_t *hpd, int argc, char *argv[])
Definition: daemon.c:446
hpd_error_t event_free_listener(hpd_listener_t *listener)
Definition: event.c:46
static hpd_error_t daemon_loop_create(hpd_t *hpd)
Definition: daemon.c:133
data key
hpd_configuration_t * configuration
Definition: daemon.h:52
hpd_error_t daemon_free(hpd_t *hpd)
Definition: daemon.c:382
static hpd_error_t daemon_options_parse(hpd_t *hpd, int argc, char **argv)
Definition: daemon.c:271
hpd_adapters_t adapters
Definition: model.h:59
hpd_error_t daemon_add_option(const hpd_module_t *context, const char *name, const char *arg, int flags, const char *doc)
Definition: daemon.c:409
hpd_ev_asyncs_t request_watchers
Definition: daemon.h:61
hpd_error_t daemon_add_module(hpd_t *hpd, const char *id, const hpd_module_def_t *module_def)
Definition: daemon.c:394
hpd_create_f on_create
Definition: hpd_types.h:201
enum hpd_error hpd_error_t
Definition: hpd_types.h:167
[Application API Callbacks]
Definition: hpd_types.h:200
#define LOG_WARN(FMT,...)
Definition: log.h:44
hpd_error_t request_free_response(hpd_response_t *response)
Definition: request.c:122
ev_signal sigint_watcher
Definition: daemon.h:53
hpd_start_f on_start
Definition: hpd_types.h:203
#define LOG_RETURN(E, FMT,...)
Definition: log.h:48
#define LOG_DEBUG(FMT,...)
Definition: log.h:46
Definition: daemon.h:50
static struct ev_loop * loop
hpd_ev_asyncs_t changed_watchers
Definition: daemon.h:63
hpd_t * hpd
Definition: daemon.h:90
hpd_error_t value_free(hpd_value_t *value)
Definition: value.c:99
static int daemon_on_parse_opt(int key, char *arg, struct argp_state *state)
Definition: daemon.c:43
state
The possible states of a request.
Definition: httpd_request.c:37
hpd_error_t request_free_request(hpd_request_t *request)
Definition: request.c:58
hpd_t * hpd
Definition: model.h:61
static hpd_error_t daemon_modules_destroy(const hpd_t *hpd)
Definition: daemon.c:179
static hpd_error_t daemon_add_global_option(hpd_t *hpd, const char *name, int key, const char *arg, int flags, const char *doc)
Definition: daemon.c:104
hpd_error_t discovery_free_sid(hpd_service_id_t *id)
Definition: discovery_id.c:186
hpd_ev_asyncs_t detached_watchers
Definition: daemon.h:65
hpd_ev_asyncs_t attached_watchers
Definition: daemon.h:64
hpd_stop_f on_stop
Definition: hpd_types.h:204
struct ev_loop hpd_ev_loop_t
Definition: hpd_types.h:51
static void daemon_options_destroy(hpd_t *hpd)
Definition: daemon.c:254
hpd_error_t daemon_alloc(hpd_t **hpd)
Definition: daemon.c:359
#define LOG_ERROR(FMT,...)
Definition: log.h:43
char * argv0
Definition: daemon.h:66
#define HPD_REALLOC(PTR, NUM, CAST)
CAST is for c++ compatibility (tests).
Definition: hpd_common.h:52
hpd_destroy_f on_destroy
Definition: hpd_types.h:202
int module_options_count
Definition: daemon.h:56
hpd_module_def_t def
Definition: daemon.h:92