aboutsummaryrefslogtreecommitdiffstats
path: root/ctrl/facemgr/src/main.c
diff options
context:
space:
mode:
authorJordan Augé <jordan.auge+fdio@cisco.com>2019-10-07 09:52:33 +0200
committerJordan Augé <jordan.auge+fdio@cisco.com>2019-10-07 15:55:42 +0200
commit6b84ec54083da9911f5ad4816d0eb4f4745afad4 (patch)
treee4296ebb218fff02dc0bbea73ce1c8d12aba7bcc /ctrl/facemgr/src/main.c
parent85a791ac2cdd35d79c00141e748b4c68fbdafb0d (diff)
[HICN-298] Release new hICN app for Android
Change-Id: I43adc62fadf00690b687078d739788dffdc5e566 Signed-off-by: Jordan Augé <jordan.auge+fdio@cisco.com>
Diffstat (limited to 'ctrl/facemgr/src/main.c')
-rw-r--r--ctrl/facemgr/src/main.c773
1 files changed, 637 insertions, 136 deletions
diff --git a/ctrl/facemgr/src/main.c b/ctrl/facemgr/src/main.c
index 6a80d806b..2a336db8f 100644
--- a/ctrl/facemgr/src/main.c
+++ b/ctrl/facemgr/src/main.c
@@ -18,8 +18,21 @@
* \brief Face manager daemon entry point
*/
+#ifdef WITH_THREAD
+#ifndef __linux__
+#error "Not implemented"
+#endif /* __linux__ */
+#include <pthread.h>
+#endif /* WITH_THREAD */
+
+#ifndef __APPLE__
+#include <event2/event.h>
+#include <event2/thread.h>
+#endif /* __APPLE__ */
+
#include <getopt.h>
#include <limits.h>
+#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -27,20 +40,41 @@
#include <libconfig.h>
-#include "util/log.h"
-#include "util/policy.h"
-
#ifdef __APPLE__
#include <Dispatch/Dispatch.h>
#else
-// Note: we might want to use libevent on Apple too
#include <event2/event.h>
#endif
-#include "facemgr.h"
+#include <hicn/facemgr.h>
+#include <hicn/policy.h>
+
+#include <hicn/util/ip_address.h>
+#include <hicn/util/log.h>
+
+#include <hicn/facemgr/cfg.h>
#define FACEMGR_TIMEOUT 3
+static struct event_base * loop;
+
+void facemgr_signal_handler(int signal) {
+ fprintf(stderr, "Received ^C... quitting !\n");
+ exit(0);
+#if 0
+ return;
+
+ // FIXME
+
+ /* should be atomic */
+ // FIXME Don't use loop in a static variable as we should not need it if all
+ // events are properly unregistered...
+#endif
+#ifdef __linux__
+ event_base_loopbreak(loop);
+#endif /* __linux__ */
+ loop = NULL;
+}
static struct option long_options[] =
{
@@ -101,106 +135,305 @@ int parse_cmdline(int argc, char ** argv, facemgr_options_t * opts)
return 0;
}
-int parse_config_file(const char * cfgpath, facemgr_t * facemgr)
+int
+parse_config_global(facemgr_cfg_t * cfg, config_setting_t * setting)
{
- /* Reading configuration file */
- config_t cfg;
- config_setting_t *setting;
+ /* - face_type */
+
+ const char *face_type_str;
+ facemgr_face_type_t face_type;
+ if (config_setting_lookup_string(setting, "face_type", &face_type_str)) {
+ if (strcasecmp(face_type_str, "auto") == 0) {
+ face_type = FACEMGR_FACE_TYPE_DEFAULT;
+ } else
+ if (strcasecmp(face_type_str, "native-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_UDP;
+ } else
+ if (strcasecmp(face_type_str, "native-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
+ } else
+ if (strcasecmp(face_type_str, "overlay-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
+ } else
+ if (strcasecmp(face_type_str, "overlay-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
+ } else {
+ ERROR("Invalid face type in section 'global'");
+ return -1;
+ }
- config_init(&cfg);
+ int rc = facemgr_cfg_set_face_type(cfg, &face_type);
+ if (rc < 0)
+ goto ERR;
+ }
- /* Read the file. If there is an error, report it and exit. */
- if(!config_read_file(&cfg, cfgpath))
- goto ERR_FILE;
+ /* - disable_discovery */
- setting = config_lookup(&cfg, "log");
- if (setting) {
- const char *log_level_str;
- if (config_setting_lookup_string(setting, "log_level", &log_level_str)) {
- if (strcmp(log_level_str, "FATAL") == 0) {
- log_conf.log_level = LOG_FATAL;
- } else
- if (strcmp(log_level_str, "ERROR") == 0) {
- log_conf.log_level = LOG_ERROR;
- } else
- if (strcmp(log_level_str, "WARN") == 0) {
- log_conf.log_level = LOG_WARN;
- } else
- if (strcmp(log_level_str, "INFO") == 0) {
- log_conf.log_level = LOG_INFO;
- } else
- if (strcmp(log_level_str, "DEBUG") == 0) {
- log_conf.log_level = LOG_DEBUG;
- } else
- if (strcmp(log_level_str, "TRACE") == 0) {
- log_conf.log_level = LOG_TRACE;
- } else {
- printf("Ignored unknown log level\n");
- }
- }
+ int disable_discovery;
+ if (config_setting_lookup_bool(setting, "disable_discovery",
+ &disable_discovery)) {
+ int rc = facemgr_cfg_set_discovery(cfg, !disable_discovery);
+ if (rc < 0)
+ goto ERR;
}
- setting = config_lookup(&cfg, "faces.overlay.ipv4");
- if (setting) {
- const char * ip_address;
- int local_port, remote_port;
- if (config_setting_lookup_int(setting, "local_port", &local_port)) {
- if ((local_port < 0) || (local_port > MAX_PORT))
+ /* - disable_ipv4 */
+
+ int disable_ipv4;
+ if (config_setting_lookup_bool(setting, "disable_ipv4",
+ &disable_ipv4)) {
+ INFO("Ignored setting 'disable_ipv4' in section 'global' (not implemented).");
+#if 0
+ int rc = facemgr_cfg_set_ipv4(cfg, !disable_ipv4);
+ if (rc < 0)
+ goto ERR;
+#endif
+ }
+
+ /* - disable ipv6 */
+
+ int disable_ipv6;
+ if (config_setting_lookup_bool(setting, "disable_ipv6",
+ &disable_ipv6)) {
+ INFO("Ignored setting 'disable_ipv6' in section 'global': (not implemented).");
+#if 0
+ int rc = facemgr_cfg_set_ipv6(cfg, !disable_ipv6);
+ if (rc < 0)
+ goto ERR;
+#endif
+ }
+
+ /* - overlay */
+ config_setting_t *overlay = config_setting_get_member(setting, "overlay");
+ if (overlay) {
+
+ /* ipv4 */
+ config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4");
+ if (overlay_v4) {
+ const char * local_addr_str, * remote_addr_str;
+ ip_address_t local_addr, remote_addr;
+ ip_address_t * local_addr_p = NULL;
+ ip_address_t * remote_addr_p = NULL;
+ int local_port = 0;
+ int remote_port = 0;
+
+ if (config_setting_lookup_string(overlay_v4, "local_addr", &local_addr_str)) {
+ ip_address_pton(local_addr_str, &local_addr);
+ local_addr_p = &local_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) {
+ if (!IS_VALID_PORT(local_port))
+ goto ERR;
+ }
+
+ if (config_setting_lookup_string(overlay_v4, "remote_addr", &remote_addr_str)) {
+ ip_address_pton(remote_addr_str, &remote_addr);
+ remote_addr_p = &remote_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v4, "remote_port", &remote_port)) {
+ if (!IS_VALID_PORT(remote_port))
+ goto ERR;
+ }
+ int rc = facemgr_cfg_set_overlay(cfg, AF_INET,
+ local_addr_p, local_port,
+ remote_addr_p, remote_port);
+ if (rc < 0)
goto ERR;
- facemgr->overlay_v4_local_port = (uint16_t)local_port;
}
- if (config_setting_lookup_int(setting, "remote_port", &remote_port)) {
- if ((remote_port < 0) || (remote_port > MAX_PORT))
+ /* ipv6 */
+ config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6");
+ if (overlay_v6) {
+ const char * local_addr_str, * remote_addr_str;
+ ip_address_t local_addr, remote_addr;
+ ip_address_t * local_addr_p = NULL;
+ ip_address_t * remote_addr_p = NULL;
+ int local_port = 0;
+ int remote_port = 0;
+
+ if (config_setting_lookup_string(overlay_v6, "local_addr", &local_addr_str)) {
+ ip_address_pton(local_addr_str, &local_addr);
+ local_addr_p = &local_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) {
+ if (!IS_VALID_PORT(local_port))
+ goto ERR;
+ }
+
+ if (config_setting_lookup_string(overlay_v6, "remote_addr", &remote_addr_str)) {
+ ip_address_pton(remote_addr_str, &remote_addr);
+ remote_addr_p = &remote_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v6, "remote_port", &remote_port)) {
+ if (!IS_VALID_PORT(remote_port))
+ goto ERR;
+ }
+ int rc = facemgr_cfg_set_overlay(cfg, AF_INET6,
+ local_addr_p, local_port,
+ remote_addr_p, remote_port);
+ if (rc < 0)
goto ERR;
- facemgr->overlay_v4_remote_port = (uint16_t)remote_port;
}
- if (config_setting_lookup_string(setting, "remote_addr", &ip_address)) {
- ip_address_pton(ip_address, &facemgr->overlay_v4_remote_addr);
- printf("got v4 remote addr\n");
+ } /* overlay */
+
+ return 0;
+
+ERR:
+ return -1;
+}
+
+int
+parse_config_rules(facemgr_cfg_t * cfg, config_setting_t * setting)
+{
+ /* List of match-override tuples */
+ facemgr_cfg_rule_t * rule;
+
+ int count = config_setting_length(setting);
+ for (unsigned i = 0; i < count; ++i) {
+ config_setting_t * rule_setting = config_setting_get_elem(setting, i);
+
+ /* Sanity check */
+
+ config_setting_t * match_setting = config_setting_get_member(rule_setting, "match");
+ if (!match_setting) {
+ ERROR("Missing match section in rule #%d", i);
+ goto ERR_CHECK;
}
- }
- setting = config_lookup(&cfg, "faces.overlay.ipv6");
- if (setting) {
- const char * ip_address;
- int local_port, remote_port;
- if (config_setting_lookup_int(setting, "local_port", &local_port)) {
- if ((local_port < 0) || (local_port > MAX_PORT))
+ config_setting_t * override_setting = config_setting_get_member(rule_setting, "override");
+ if (!override_setting) {
+ ERROR("Missing override section in rule #%d", i);
+ goto ERR_CHECK;
+ }
+
+ rule = facemgr_cfg_rule_create();
+ if (!rule)
+ goto ERR_RULE;
+
+ /* Parse match */
+
+ const char * interface_name = NULL;
+ config_setting_lookup_string(match_setting, "interface_name", &interface_name);
+
+ const char * interface_type_str;
+ netdevice_type_t interface_type = NETDEVICE_TYPE_UNDEFINED;
+ if (config_setting_lookup_string(match_setting, "interface_type", &interface_type_str)) {
+ if (strcasecmp(interface_type_str, "wired") == 0) {
+ interface_type = NETDEVICE_TYPE_WIRED;
+ } else
+ if (strcasecmp(interface_type_str, "wifi") == 0) {
+ interface_type = NETDEVICE_TYPE_WIFI;
+ } else
+ if (strcasecmp(interface_type_str, "cellular") == 0) {
+ interface_type = NETDEVICE_TYPE_CELLULAR;
+ } else {
+ ERROR("Unknown interface type in rule #%d", i);
goto ERR;
- facemgr->overlay_v6_local_port = (uint16_t)local_port;
+ }
}
- if (config_setting_lookup_int(setting, "remote_port", &remote_port)) {
- if ((remote_port < 0) || (remote_port > MAX_PORT))
+ if ((!interface_name) && (interface_type == NETDEVICE_TYPE_UNDEFINED)) {
+ ERROR("Empty match section in rule #%d", i);
+ goto ERR;
+ }
+
+ /* Associate match to rule */
+
+ int rc = facemgr_cfg_rule_set_match(rule, interface_name, interface_type);
+ if (rc < 0)
+ goto ERR;
+
+ /* Parse override */
+
+ /* - face_type */
+
+ const char *face_type_str;
+ facemgr_face_type_t face_type;
+ if (config_setting_lookup_string(override_setting, "face_type", &face_type_str)) {
+ if (strcasecmp(face_type_str, "auto")) {
+ /* We currently hardcode different behaviours based on the OS */
+#ifdef __ANDROID__
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
+#else
+ face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
+#endif
+ } else
+ if (strcasecmp(face_type_str, "native-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_UDP;
+ } else
+ if (strcasecmp(face_type_str, "native-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_NATIVE_TCP;
+ } else
+ if (strcasecmp(face_type_str, "overlay-udp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_UDP;
+ } else
+ if (strcasecmp(face_type_str, "overlay-tcp") == 0) {
+ face_type = FACEMGR_FACE_TYPE_OVERLAY_TCP;
+ } else {
+ ERROR("Invalid face type in section 'global'");
+ return -1;
+ }
+
+ int rc = facemgr_cfg_rule_set_face_type(rule, &face_type);
+ if (rc < 0)
goto ERR;
- facemgr->overlay_v6_remote_port = (uint16_t)remote_port;
}
- if (config_setting_lookup_string(setting, "remote_addr", &ip_address))
- ip_address_pton(ip_address, &facemgr->overlay_v6_remote_addr);
- }
+ /* - disable_discovery */
- setting = config_lookup(&cfg, "faces.rules");
- if (setting) {
- int count = config_setting_length(setting);
- for(unsigned i = 0; i < count; ++i) {
- const char *interface_name;
- policy_tags_t tags = POLICY_TAGS_EMPTY;
+ int disable_discovery;
+ if (config_setting_lookup_bool(override_setting, "disable_discovery",
+ &disable_discovery)) {
+ int rc = facemgr_cfg_rule_set_discovery(rule, !disable_discovery);
+ if (rc < 0)
+ goto ERR;
+ }
- config_setting_t *rule = config_setting_get_elem(setting, i);
+ /* - disable_ipv4 */
- /* Interface name */
- if(!(config_setting_lookup_string(rule, "name", &interface_name)))
- continue;
+ int disable_ipv4;
+ if (config_setting_lookup_bool(override_setting, "disable_ipv4",
+ &disable_ipv4)) {
+ INFO("Ignored setting 'disable_ipv4' in rule #%d (not implemented).", i);
+#if 0
+ int rc = facemgr_cfg_rule_set_ipv4(rule, !disable_ipv4);
+ if (rc < 0)
+ goto ERR;
+#endif
+ }
- /* Associated tags */
- config_setting_t *tag_settings = config_setting_get_member(rule, "tags");
- if (!tag_settings)
+ /* - disable ipv6 */
+
+ int disable_ipv6;
+ if (config_setting_lookup_bool(override_setting, "disable_ipv6",
+ &disable_ipv6)) {
+ INFO("Ignored setting 'disable_ipv6' in rule #%d (not implemented).", i);
+#if 0
+ int rc = facemgr_cfg_rule_set_ipv6(rule, !disable_ipv6);
+ if (rc < 0)
goto ERR;
+#endif
+ }
+ /* - ignore */
+ int ignore;
+ if (config_setting_lookup_bool(override_setting, "ignore", &ignore)) {
+ int rc = facemgr_cfg_rule_set_ignore(rule, !!ignore);
+ if (rc < 0)
+ goto ERR;
+ }
+ /* - tags */
+ config_setting_t *tag_settings = config_setting_get_member(override_setting, "tags");
+ if (tag_settings) {
+ INFO("Ignored setting 'tags' in rule #%d (not implemented).", i);
+#if 0
+ policy_tags_t tags = POLICY_TAGS_EMPTY;
for (unsigned j = 0; j < config_setting_length(tag_settings); j++) {
const char * tag_str = config_setting_get_string_elem(tag_settings, j);
policy_tag_t tag = policy_tag_from_str(tag_str);
@@ -209,41 +442,267 @@ int parse_config_file(const char * cfgpath, facemgr_t * facemgr)
policy_tags_add(&tags, tag);
}
- /* debug */
+ int rc = facemgr_cfg_rule_set_tags(rule, tags);
+ if (rc < 0)
+ goto ERR;
+
+#if 0
char tags_str[MAXSZ_POLICY_TAGS];
policy_tags_snprintf(tags_str, MAXSZ_POLICY_TAGS, tags);
- printf("Rule #%d interface_name=%s, tags=%s\n", i, interface_name, tags_str);
- face_rules_add(&facemgr->rules, strdup(interface_name), tags);
+ DEBUG("Added tags tags=%s", tags_str);
+#endif
+#endif
}
+
+ /* - overlay */
+ config_setting_t *overlay = config_setting_get_member(override_setting, "overlay");
+ if (overlay) {
+
+ /* ipv4 */
+ config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4");
+ if (overlay_v4) {
+ const char * local_addr_str, * remote_addr_str;
+ ip_address_t local_addr, remote_addr;
+ ip_address_t * local_addr_p = NULL;
+ ip_address_t * remote_addr_p = NULL;
+ int local_port = 0;
+ int remote_port = 0;
+
+ if (config_setting_lookup_string(overlay_v4, "local_addr", &local_addr_str)) {
+ ip_address_pton(local_addr_str, &local_addr);
+ local_addr_p = &local_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) {
+ if (!IS_VALID_PORT(local_port))
+ goto ERR;
+ }
+
+ if (config_setting_lookup_string(overlay_v4, "remote_addr", &remote_addr_str)) {
+ ip_address_pton(remote_addr_str, &remote_addr);
+ remote_addr_p = &remote_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v4, "remote_port", &remote_port)) {
+ if (!IS_VALID_PORT(remote_port))
+ goto ERR;
+ }
+ int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET,
+ local_addr_p, local_port,
+ remote_addr_p, remote_port);
+ if (rc < 0)
+ goto ERR;
+ }
+
+ /* ipv6 */
+ config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6");
+ if (overlay_v6) {
+ const char * local_addr_str, * remote_addr_str;
+ ip_address_t local_addr, remote_addr;
+ ip_address_t * local_addr_p = NULL;
+ ip_address_t * remote_addr_p = NULL;
+ int local_port = 0;
+ int remote_port = 0;
+
+ if (config_setting_lookup_string(overlay_v6, "local_addr", &local_addr_str)) {
+ ip_address_pton(local_addr_str, &local_addr);
+ local_addr_p = &local_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) {
+ if (!IS_VALID_PORT(local_port))
+ goto ERR;
+ }
+
+ if (config_setting_lookup_string(overlay_v6, "remote_addr", &remote_addr_str)) {
+ ip_address_pton(remote_addr_str, &remote_addr);
+ remote_addr_p = &remote_addr;
+ }
+
+ if (config_setting_lookup_int(overlay_v6, "remote_port", &remote_port)) {
+ if (!IS_VALID_PORT(remote_port))
+ goto ERR;
+ }
+ int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET6,
+ local_addr_p, local_port,
+ remote_addr_p, remote_port);
+ if (rc < 0)
+ goto ERR;
+ }
+
+ } /* overlay */
+
+ /* Add newly created rule */
+
+ rc = facemgr_cfg_add_rule(cfg, rule);
+ if (rc < 0)
+ goto ERR;
}
+ return 0;
+
+ERR:
+ facemgr_cfg_rule_free(rule);
+ERR_RULE:
+ERR_CHECK:
+ return -1;
+}
- config_destroy(&cfg);
+/* Currently not using facemgr_cfg_t */
+int
+parse_config_log(facemgr_cfg_t * cfg, config_setting_t * setting)
+{
+ const char *log_level_str;
+ if (config_setting_lookup_string(setting, "log_level", &log_level_str)) {
+ if (strcasecmp(log_level_str, "FATAL") == 0) {
+ log_conf.log_level = LOG_FATAL;
+ } else
+ if (strcasecmp(log_level_str, "ERROR") == 0) {
+ log_conf.log_level = LOG_ERROR;
+ } else
+ if (strcasecmp(log_level_str, "WARN") == 0) {
+ log_conf.log_level = LOG_WARN;
+ } else
+ if (strcasecmp(log_level_str, "INFO") == 0) {
+ log_conf.log_level = LOG_INFO;
+ } else
+ if (strcasecmp(log_level_str, "DEBUG") == 0) {
+ log_conf.log_level = LOG_DEBUG;
+ } else
+ if (strcasecmp(log_level_str, "TRACE") == 0) {
+ log_conf.log_level = LOG_TRACE;
+ } else {
+ ERROR("Invalid log level in section 'log'");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+parse_config_file(const char * cfgpath, facemgr_cfg_t * cfg)
+{
+ /* Reading configuration file */
+ config_t cfgfile;
+ config_setting_t *setting;
+
+ config_init(&cfgfile);
+
+ /* Read the file. If there is an error, report it and exit. */
+ if(!config_read_file(&cfgfile, cfgpath))
+ goto ERR_FILE;
+
+ setting = config_lookup(&cfgfile, "global");
+ if (setting) {
+ int rc = parse_config_global(cfg, setting);
+ if (rc < 0)
+ goto ERR_PARSE;
+ }
+
+ setting = config_lookup(&cfgfile, "rules");
+ if (setting) {
+ int rc = parse_config_rules(cfg, setting);
+ if (rc < 0)
+ goto ERR_PARSE;
+ }
+
+ setting = config_lookup(&cfgfile, "log");
+ if (setting) {
+ int rc = parse_config_log(cfg, setting);
+ if (rc < 0)
+ goto ERR_PARSE;
+ }
+
+ config_destroy(&cfgfile);
return 0;
ERR_FILE:
- printf("Could not read configuration file %s\n", cfgpath);
- fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg),
- config_error_line(&cfg), config_error_text(&cfg));
- config_destroy(&cfg);
+ ERROR("Could not read configuration file %s", cfgpath);
+ fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile),
+ config_error_line(&cfgfile), config_error_text(&cfgfile));
+ config_destroy(&cfgfile);
exit(EXIT_FAILURE);
return -1;
-ERR:
- fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg),
- config_error_line(&cfg), config_error_text(&cfg));
- config_destroy(&cfg);
+ERR_PARSE:
+ fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile),
+ config_error_line(&cfgfile), config_error_text(&cfgfile));
+ config_destroy(&cfgfile);
return -1;
}
-#ifndef APPLE
-void dummy_handler(int fd, short event, void *arg) { }
-#endif /* APPLE */
+#ifdef __linux__
+typedef struct {
+ void (*cb)(void *, ...);
+ void * args;
+} cb_wrapper_args_t;
+
+void cb_wrapper(evutil_socket_t fd, short what, void * arg) {
+ cb_wrapper_args_t * cb_wrapper_args = arg;
+ cb_wrapper_args->cb(cb_wrapper_args->args);
+}
-int main(int argc, char **argv)
+struct event *
+loop_register_fd(struct event_base * loop, int fd, void * cb, void * cb_args)
{
- facemgr_t * facemgr = facemgr_create();
- if (!facemgr)
- goto ERR_FACEMGR;
+ // TODO: not freed
+ cb_wrapper_args_t * cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t));
+ *cb_wrapper_args = (cb_wrapper_args_t) {
+ .cb = cb,
+ .args = cb_args,
+ };
+
+ evutil_make_socket_nonblocking(fd);
+ struct event * event = event_new(loop, fd, EV_READ | EV_PERSIST, cb_wrapper, cb_wrapper_args);
+ if (!event)
+ goto ERR_EVENT_NEW;
+
+ if (event_add(event, NULL) < 0)
+ goto ERR_EVENT_ADD;
+
+ return event;
+
+ERR_EVENT_ADD:
+ event_free(event);
+ERR_EVENT_NEW:
+ return NULL;
+}
+
+int
+loop_unregister_event(struct event_base * loop, struct event * event)
+{
+ if (!event)
+ return 0;
+
+ event_del(event);
+ event_free(event);
+
+ return 0;
+}
+
+
+void * start_dispatch(void * loop_ptr)
+{
+ struct event_base * loop = (struct event_base *) loop_ptr;
+ event_base_dispatch(loop);
+
+ return NULL;
+}
+
+#endif /* __linux__ */
+
+int main(int argc, char ** argv)
+{
+ facemgr_cfg_t * cfg = NULL;
+ facemgr_t * facemgr;
+#ifdef WITH_THREAD
+ pthread_t facemgr_thread;
+#endif /* WITH_THREAD */
+
+ struct sigaction sigIntHandler;
+ sigIntHandler.sa_handler = facemgr_signal_handler;
+ sigemptyset(&sigIntHandler.sa_mask);
+ sigIntHandler.sa_flags = 0;
+ sigaction(SIGINT, &sigIntHandler, NULL);
char cfgfile[PATH_MAX];
@@ -252,7 +711,7 @@ int main(int argc, char **argv)
/* Commandline */
facemgr_options_t cmdline_opts = {0};
if (parse_cmdline(argc, argv, &cmdline_opts) < 0) {
- ERROR("Error parsing commandline\n");
+ ERROR("Error parsing commandline");
goto ERR_CMDLINE;
}
@@ -260,7 +719,7 @@ int main(int argc, char **argv)
//facemgr_options_t cfgfile_opts;
if (cmdline_opts.cfgfile) {
- if (strcmp(cmdline_opts.cfgfile, "none") == 0)
+ if (strcasecmp(cmdline_opts.cfgfile, "none") == 0)
goto NO_CFGFILE;
if (!realpath(cmdline_opts.cfgfile, (char*)&cfgfile))
@@ -274,76 +733,118 @@ int main(int argc, char **argv)
if (probe_cfgfile(cfgfile) < 0)
goto NO_CFGFILE;
- printf("Using configuration file %s\n", cfgfile);
-
PARSE_CFGFILE:
- if (parse_config_file(cfgfile, facemgr) < 0) {
- ERROR("Error parsing configuration file %s\n", cfgfile);
+ DEBUG("Using configuration file %s", cfgfile);
+ cfg = facemgr_cfg_create();
+ if (!cfg)
+ goto ERR_FACEMGR_CFG;
+
+ if (parse_config_file(cfgfile, cfg) < 0) {
+ ERROR("Error parsing configuration file %s", cfgfile);
goto ERR_PARSE;
}
+ facemgr = facemgr_create_with_config(cfg);
+ if (!facemgr)
+ goto ERR_FACEMGR_CONFIG;
+
+ goto MAIN_LOOP;
+
NO_CFGFILE:
+ facemgr = facemgr_create();
+ if (!facemgr)
+ goto ERR_FACEMGR;
+
+MAIN_LOOP:
+
+ /* Main loop */
+
+
+#ifdef WITH_THREAD
+ evthread_use_pthreads();
+#endif /* WITH_THREAD */
+
#ifdef __linux__
- facemgr->loop = event_base_new();
- if (!facemgr->loop)
- fatal("Could not create an event base");
-
- /* Main loop
- *
- * To avoid the loop to exit when empty, we might either rely on an option
- * introduced from versions 2.1.x:
- * event_base_loop(loop->base, EVLOOP_NO_EXIT_ON_EMPTY);
- * or use this workaround:
- * http://archives.seul.org/libevent/users/Sep-2012/msg00056.html
- *
- * TODO:
- * - HUP should interrupt the main loop
- */
- {
- struct event *ev;
- struct timeval tv;
- tv.tv_sec = FACEMGR_TIMEOUT;
- tv.tv_usec = 0;
-
- ev = event_new(facemgr->loop, fileno(stdin), EV_TIMEOUT | EV_PERSIST, dummy_handler, NULL);
- event_add(ev, &tv);
- }
+ /* Event loop */
+ loop = event_base_new();
+ if (!loop)
+ goto ERR_EVENT;
+
+ facemgr_set_event_loop_handler(facemgr, loop, loop_register_fd, loop_unregister_event);
#endif /* __linux__ */
- DEBUG("Bootstrap...\n");
+#ifdef __ANDROID__
+ facemgr_set_jvm(facemgr, NULL, NULL); // FIXME
+#endif /* __ ANDROID__ */
+
+ DEBUG("Bootstrap...");
+
if (facemgr_bootstrap(facemgr) < 0 )
goto ERR_BOOTSTRAP;
#ifdef __linux__
event_set_log_callback(NULL);
- event_base_dispatch(facemgr->loop);
- event_base_free(facemgr->loop);
+#ifdef WITH_THREAD
+ if (pthread_create(&facemgr_thread, NULL, start_dispatch, loop)) {
+ fprintf(stderr, "Error creating thread\n");
+ return EXIT_FAILURE;
+ }
+#else
+ event_base_dispatch(loop);
+#endif /* WITH_THREAD */
+
#endif /* __linux__ */
#ifdef __APPLE__
/* Main loop */
- facemgr->loop = NULL;
dispatch_main();
#endif /* __APPLE__ */
- /* Clean up */
- //interface_delete_all();
+#ifdef __linux__
+#ifdef WITH_THREAD
+ for(;;) {
+ facemgr_list_faces(facemgr, NULL, NULL);
+ sleep(5);
+ }
+#endif /* WITH_THREAD */
+#endif /* __linux__ */
+
+ facemgr_stop(facemgr);
+#ifdef __linux__
+#ifdef WITH_THREAD
+ DEBUG("Waiting for loop to terminate...");
+ if(pthread_join(facemgr_thread, NULL)) {
+ fprintf(stderr, "Error joining thread\n");
+ return EXIT_FAILURE;
+ }
+ DEBUG("Loop terminated !");
+#endif /* WITH_THREAD */
+#endif /* __linux__ */
facemgr_free(facemgr);
return EXIT_SUCCESS;
ERR_BOOTSTRAP:
+#ifdef __linux__
+ERR_EVENT:
+#endif /* __linux__ */
+
+ facemgr_free(facemgr);
+ERR_FACEMGR_CONFIG:
+ if (cfg)
+ facemgr_cfg_free(cfg);
+ERR_FACEMGR:
+ERR_FACEMGR_CFG:
+
ERR_PARSE:
ERR_PATH:
ERR_CMDLINE:
- facemgr_free(facemgr);
-ERR_FACEMGR:
return EXIT_FAILURE;
-}
+}