summaryrefslogtreecommitdiffstats
path: root/ctrl/facemgr
diff options
context:
space:
mode:
authorJordan Augé <jordan.auge+fdio@cisco.com>2019-10-23 17:55:00 +0200
committerJordan Augé <jordan.auge+fdio@cisco.com>2019-10-24 00:21:47 +0200
commit8e12c8e42cc9ea9d12e55a3a0d8fbcb211504c04 (patch)
tree1556919c967bd1b6ea664c1f80d6d43efb805f59 /ctrl/facemgr
parentcf3d6ef0cbda50c9917421213a77097250f3d67b (diff)
[HICN-352] facemgr event loop enhancement; timer support & async hicn-light interface
Change-Id: I920a0eb091d826e1eb0d1f786fb0b437487f7ff7 Signed-off-by: Jordan Augé <jordan.auge+fdio@cisco.com>
Diffstat (limited to 'ctrl/facemgr')
-rw-r--r--ctrl/facemgr/doc/interface.md2
-rwxr-xr-xctrl/facemgr/examples/run-bonjour.sh16
-rw-r--r--ctrl/facemgr/examples/updownsrv/updownsrv.c8
-rw-r--r--ctrl/facemgr/includes/CMakeLists.txt2
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/api.h18
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/cfg.h6
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/loop.h90
-rw-r--r--ctrl/facemgr/src/CMakeLists.txt16
-rw-r--r--ctrl/facemgr/src/api.c221
-rw-r--r--ctrl/facemgr/src/cfg.c48
-rw-r--r--ctrl/facemgr/src/cfg_file.c548
-rw-r--r--ctrl/facemgr/src/cfg_file.h42
-rw-r--r--ctrl/facemgr/src/common.h3
-rw-r--r--ctrl/facemgr/src/facelet.c46
-rw-r--r--ctrl/facemgr/src/facelet.h23
-rw-r--r--ctrl/facemgr/src/interface.c87
-rw-r--r--ctrl/facemgr/src/interface.h69
-rw-r--r--ctrl/facemgr/src/interfaces/android_utility/android_utility.c2
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/bonjour.c14
-rw-r--r--ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c224
-rw-r--r--ctrl/facemgr/src/interfaces/netlink/netlink.c55
-rw-r--r--ctrl/facemgr/src/interfaces/network_framework/network_framework.c167
-rw-r--r--ctrl/facemgr/src/interfaces/updown/updown.c2
-rw-r--r--ctrl/facemgr/src/loop_dispatcher.c75
-rw-r--r--ctrl/facemgr/src/loop_libevent.c425
-rw-r--r--ctrl/facemgr/src/main.c704
-rw-r--r--ctrl/facemgr/src/util/map.h68
-rw-r--r--ctrl/facemgr/src/util/set.h39
28 files changed, 2065 insertions, 955 deletions
diff --git a/ctrl/facemgr/doc/interface.md b/ctrl/facemgr/doc/interface.md
index 11c8da275..c7168ef23 100644
--- a/ctrl/facemgr/doc/interface.md
+++ b/ctrl/facemgr/doc/interface.md
@@ -281,7 +281,7 @@ The facelet event can then be defined and raised to the face maanger for further
processing through the following code:
```
facelet_set_event(facelet, EVENT_TYPE_CREATE);
- facelet_raise_event(facelet, interface);
+ interface_raise_event(interface, facelet);
```
Here the event is a facelet creation (`EVENT_TYPE_CREATE`). The full facelet API
diff --git a/ctrl/facemgr/examples/run-bonjour.sh b/ctrl/facemgr/examples/run-bonjour.sh
index c6c317b42..cc1c28e27 100755
--- a/ctrl/facemgr/examples/run-bonjour.sh
+++ b/ctrl/facemgr/examples/run-bonjour.sh
@@ -1,5 +1,21 @@
#!/bin/bash
+# Notes for MacOS:
+#
+# - Browse all discoverable services
+# dns-sd -B _services._dns-sd._udp local.
+#
+# - Browse all hICN services
+# dns-sd -B _hicn._udp local.
+#
+# - Lookup for specific options
+# dns-sd -L "hicn node" _hicn._udp local.
+#
+# - Lookup addresses
+# dns-sd -G v4v6 adreena.local.
+#
+# NOTE: trailing dot '.' is optional
+
set -e
PORT=9695
diff --git a/ctrl/facemgr/examples/updownsrv/updownsrv.c b/ctrl/facemgr/examples/updownsrv/updownsrv.c
index e10247860..5d624583b 100644
--- a/ctrl/facemgr/examples/updownsrv/updownsrv.c
+++ b/ctrl/facemgr/examples/updownsrv/updownsrv.c
@@ -112,6 +112,12 @@ int main() {
fd = create_unix_server(UNIX_PATH);
if (fd < 0)
exit(EXIT_FAILURE);
+
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ perror("fcntl");
+ exit(EXIT_FAILURE);
+ }
+
FD_SET (fd, &active_fd_set);
/* Create timer */
@@ -121,7 +127,7 @@ int main() {
exit(EXIT_FAILURE);
}
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ if (fcntl(tfd, F_SETFL, O_NONBLOCK) < 0) {
perror("fcntl");
exit(EXIT_FAILURE);
}
diff --git a/ctrl/facemgr/includes/CMakeLists.txt b/ctrl/facemgr/includes/CMakeLists.txt
index 566424c67..e7265eebb 100644
--- a/ctrl/facemgr/includes/CMakeLists.txt
+++ b/ctrl/facemgr/includes/CMakeLists.txt
@@ -22,8 +22,10 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
set(TO_INSTALL_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/facemgr.h
+
${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/api.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/cfg.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/loop.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/log.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/android_utility/android_utility.h
PARENT_SCOPE
diff --git a/ctrl/facemgr/includes/hicn/facemgr/api.h b/ctrl/facemgr/includes/hicn/facemgr/api.h
index c5c29c219..e6151da11 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/api.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/api.h
@@ -26,6 +26,18 @@
#include <hicn/android_utility/android_utility.h>
#endif
+/* facemgr callbacks */
+
+typedef enum {
+ FACEMGR_CB_TYPE_REGISTER_FD,
+ FACEMGR_CB_TYPE_UNREGISTER_FD,
+ FACEMGR_CB_TYPE_REGISTER_TIMER,
+ FACEMGR_CB_TYPE_UNREGISTER_TIMER,
+} facemgr_cb_type_t;
+
+typedef int (*facemgr_cb_t)(void * loop, facemgr_cb_type_t type, void * data);
+
+
/*
* \brief Manual overlay settings (alternative to service discovery)
*/
@@ -64,11 +76,11 @@ facemgr_t * facemgr_create_with_config(facemgr_cfg_t * cfg);
void facemgr_stop(facemgr_t *);
void facemgr_free(facemgr_t *);
+
+void facemgr_set_callback(facemgr_t * facemgr, void * callback_owner, facemgr_cb_t callback);
+
int facemgr_set_config(facemgr_t * facemgr, facemgr_cfg_t * cfg);
int facemgr_reset_config(facemgr_t * facemgr);
-void facemgr_set_event_loop_handler(facemgr_t * facemgr, void * loop,
- void * loop_register_fd,
- void * loop_unregister_event);
int facemgr_bootstrap(facemgr_t * facemgr);
#ifdef __ANDROID__
void facemgr_set_jvm(facemgr_t * facemgr, JavaVM *jvm);
diff --git a/ctrl/facemgr/includes/hicn/facemgr/cfg.h b/ctrl/facemgr/includes/hicn/facemgr/cfg.h
index c121c687f..525e1a9e3 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/cfg.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/cfg.h
@@ -91,7 +91,7 @@ typedef struct {
#define FACEMGR_CFG_DEFAULT_DISCOVERY true
//#define DEFAULT_IGNORE "lo"
#define FACEMGR_CFG_DEFAULT_IPV4 true
-#define FACEMGR_CFG_DEFAULT_IPV6 true
+#define FACEMGR_CFG_DEFAULT_IPV6 false
@@ -140,6 +140,10 @@ int facemgr_cfg_set_face_type(facemgr_cfg_t * cfg, facemgr_face_type_t * face_ty
int facemgr_cfg_unset_face_type(facemgr_cfg_t * cfg);
int facemgr_cfg_set_discovery(facemgr_cfg_t * cfg, bool status);
int facemgr_cfg_unset_discovery(facemgr_cfg_t * cfg);
+int facemgr_cfg_set_ipv4(facemgr_cfg_t * cfg, bool status);
+int facemgr_cfg_unset_ipv4(facemgr_cfg_t * cfg);
+int facemgr_cfg_set_ipv6(facemgr_cfg_t * cfg, bool status);
+int facemgr_cfg_unset_ipv6(facemgr_cfg_t * cfg);
int facemgr_cfg_set_overlay(facemgr_cfg_t * cfg, int family,
ip_address_t * local_addr, uint16_t local_port,
diff --git a/ctrl/facemgr/includes/hicn/facemgr/loop.h b/ctrl/facemgr/includes/hicn/facemgr/loop.h
new file mode 100644
index 000000000..77cbedb21
--- /dev/null
+++ b/ctrl/facemgr/includes/hicn/facemgr/loop.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file loop.h
+ * \brief Face manager main loop
+ */
+
+#ifndef FACEMGR_LOOP_H
+#define FACEMGR_LOOP_H
+
+#include <hicn/facemgr/api.h>
+
+/* fd & timer callbacks */
+
+typedef int (*fd_callback_t)(void * owner, int fd, void * data);
+
+typedef struct {
+ int fd;
+ void *owner;
+ fd_callback_t callback;
+ //int (*callback)(void * owner, int fd, void * data);
+ void *data;
+} fd_callback_data_t;
+
+/* timer callbacks */
+typedef struct {
+ unsigned delay_ms;
+ void *owner;
+ fd_callback_t callback;
+ //int (*callback)(void * owner, int fd, void * data);
+ void *data;
+} timer_callback_data_t;
+
+/* loop */
+
+typedef struct loop_s loop_t;
+
+/**
+ * \brief Creates a main loop
+ * \return Pointer to the newly created loop, or NULL in case of error
+ */
+loop_t * loop_create();
+
+/**
+ * \brief Releases a loop instance and frees all associated memory
+ * \param [in] loop - Pointer to the loop instance to free
+ */
+void loop_free(loop_t * loop);
+
+/**
+ * \brief Runs the loop instance to process events
+ * \param [in] loop - Pointer to the loop instance
+ */
+void loop_dispatch(loop_t * loop);
+
+/**
+ * \brief Terminates the dispatching of events
+ * \param [in] loop - Pointer to the loop instance
+ */
+void loop_undispatch(loop_t * loop);
+
+/**
+ * \brief Breaks out of the loop
+ * \param [in] loop - Pointer to the loop instance
+ */
+void loop_break(loop_t * loop);
+
+
+/**
+ * \brief Callback for loop helpers
+ * \param [in] loop - Pointer to the loop instance
+ * \param [in] type - Type of service to be requested
+ * \param [in] data - Service specific data
+ */
+int loop_callback(loop_t * loop, facemgr_cb_type_t type, void * data);
+
+#endif /* FACEMGR_LOOP_H */
diff --git a/ctrl/facemgr/src/CMakeLists.txt b/ctrl/facemgr/src/CMakeLists.txt
index f99e57e07..88f554c40 100644
--- a/ctrl/facemgr/src/CMakeLists.txt
+++ b/ctrl/facemgr/src/CMakeLists.txt
@@ -24,6 +24,7 @@ set(HEADER_FILES
error.h
facelet.h
interface.h
+ loop.h
util/hash.h
util/map.h
util/set.h
@@ -32,12 +33,27 @@ set(HEADER_FILES
set(SOURCE_FILES
api.c
cfg.c
+ cfg_file.c
error.c
facelet.c
interface.c
util/log.c
)
+if(APPLE)
+set(SOURCE_FILES
+ ${SOURCE_FILES}
+ loop_dispatcher.c
+)
+endif()
+
+if (LINUX)
+set(SOURCE_FILES
+ ${SOURCE_FILES}
+ loop_libevent.c
+)
+endif()
+
set(INCLUDE_DIRS
./
../includes/
diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c
index de0f062d3..a1507bd70 100644
--- a/ctrl/facemgr/src/api.c
+++ b/ctrl/facemgr/src/api.c
@@ -49,9 +49,12 @@
#define DEFAULT_PORT 9695
+#define MAX_FDS 10
+
typedef struct {
interface_t * interface;
- void * event;
+ int fds[MAX_FDS];
+ size_t num_fds;
} interface_map_data_t;
TYPEDEF_SET_H(facelet_cache, facelet_t *);
@@ -60,8 +63,6 @@ TYPEDEF_SET(facelet_cache, facelet_t *, facelet_cmp, facelet_snprintf);
TYPEDEF_MAP_H(interface_map, const char *, interface_map_data_t *);
TYPEDEF_MAP(interface_map, const char *, interface_map_data_t *, strcmp, string_snprintf, generic_snprintf);
-int int_cmp(int x, int y) { return x - y; }
-
TYPEDEF_MAP_H(bonjour_map, netdevice_t *, interface_t *);
TYPEDEF_MAP(bonjour_map, netdevice_t *, interface_t *, netdevice_cmp, generic_snprintf, generic_snprintf);
@@ -106,10 +107,9 @@ struct facemgr_s {
JavaVM *jvm;
#endif /* __ANDROID__ */
- /* Event loop support */
- void * loop;
- void * (*loop_register_fd)(void * loop, int fd, void * cb, void * cb_args);
- int (*loop_unregister_event)(void * loop, void * event);
+ /* Callback */
+ facemgr_cb_t callback;
+ void * callback_owner;
/****************************/
/* Internal data structures */
@@ -191,28 +191,42 @@ ERR_INTERFACE_MAP:
int
facemgr_finalize(facemgr_t * facemgr)
{
+ int ret = 0;
int rc;
- /* TODO Free all interfaces: pass free to map */
-
rc = interface_map_finalize(&facemgr->interface_map);
- if (rc < 0)
- goto ERR;
+ if (rc < 0) {
+ ERROR("[facemgr_finalize] Could not finalize interface_map");
+ ret = -1;
+ }
+
+ /* Free all facelets from cache */
+ facelet_t ** facelet_array;
+ int n = facelet_cache_get_array(&facemgr->facelet_cache, &facelet_array);
+ if (n < 0) {
+ ERROR("[facemgr_finalize] Could not retrieve facelets in cache");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ facelet_t * facelet = facelet_array[i];
+ if (facelet_cache_remove(&facemgr->facelet_cache, facelet, NULL)) {
+ ERROR("[facemgr_finalize] Could not purge facelet from cache");
+ }
+ facelet_free(facelet);
+ }
+ free(facelet_array);
+ }
rc = facelet_cache_finalize(&facemgr->facelet_cache);
if (rc < 0)
- goto ERR;
+ ret = -1;
#ifdef __linux__
rc = bonjour_map_finalize(&facemgr->bonjour_map);
if (rc < 0)
- goto ERR;
+ ret = -1;
#endif /* __linux__ */
- return 0;
-
-ERR:
- return -1;
+ return ret;
}
AUTOGENERATE_CREATE_FREE(facemgr);
@@ -251,13 +265,12 @@ facemgr_create_with_config(facemgr_cfg_t * cfg)
return facemgr;
}
-int facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet);
+int facemgr_callback(facemgr_t * facemgr, interface_cb_type_t type, void * data);
int
facemgr_create_interface(facemgr_t * facemgr, const char * name, const char * type, void * cfg, interface_t ** pinterface)
{
- int fd, rc;
- void * event = NULL;
+ int fd;
char rand_name[RAND_NAME_LEN+1];
interface_t * interface;
@@ -276,29 +289,23 @@ facemgr_create_interface(facemgr_t * facemgr, const char * name, const char * ty
ERROR("Error creating interface %s [%s]", name, type);
goto ERR_CREATE;
}
- interface_set_callback(interface, facemgr_on_event, facemgr);
+ interface_set_callback(interface, facemgr, facemgr_callback);
fd = interface_initialize(interface, cfg);
if (fd < 0)
goto ERR_INIT;
- if (fd != 0) {
- event = facemgr->loop_register_fd(facemgr->loop, fd, interface->ops->callback, interface);
- if (event == NULL)
- goto ERR_FD;
- }
interface_map_data_t * interface_map_data = malloc(sizeof(interface_map_data_t));
if (!interface_map_data)
goto ERR_MAP_DATA;
-
*interface_map_data = (interface_map_data_t) {
.interface = interface,
- .event = event,
+ .fds = {0},
+ .num_fds = 0,
};
- rc = interface_map_add(&facemgr->interface_map, interface->name, interface_map_data);
- if (rc < 0)
+ if (interface_map_add(&facemgr->interface_map, interface->name, interface_map_data) < 0)
goto ERR_MAP_ADD;
DEBUG("Interface %s created successfully.", name);
@@ -309,9 +316,6 @@ facemgr_create_interface(facemgr_t * facemgr, const char * name, const char * ty
ERR_MAP_ADD:
free(interface_map_data);
ERR_MAP_DATA:
- if (fd > 0)
- facemgr->loop_unregister_event(facemgr->loop, interface_map_data->event);
-ERR_FD:
interface_finalize(interface);
ERR_INIT:
interface_free(interface);
@@ -328,7 +332,7 @@ facemgr_delete_interface(facemgr_t * facemgr, interface_t * interface)
interface_map_data_t * interface_map_data = NULL;
- DEBUG("Removing interface %s\n", interface->name);
+ DEBUG("Removing interface %s", interface->name);
rc = interface_map_remove(&facemgr->interface_map, interface->name, &interface_map_data);
if (rc < 0)
return -1;
@@ -336,12 +340,14 @@ facemgr_delete_interface(facemgr_t * facemgr, interface_t * interface)
if (!interface_map_data)
return -1;
- free(interface_map_data);
-
- rc = facemgr->loop_unregister_event(facemgr->loop, interface_map_data->event);
- if (rc < 0)
- return -1;
+ for (unsigned i = 0; i < interface_map_data->num_fds; i++) {
+ int fd = interface_map_data->fds[i];
+ facemgr->callback(facemgr->callback_owner, FACEMGR_CB_TYPE_UNREGISTER_FD, &fd);
+ if (rc < 0)
+ WARN("[facemgr_delete_interface] Error unregistering fd %d for interface", fd);
+ }
+ free(interface_map_data);
interface_finalize(interface);
interface_free(interface);
@@ -445,26 +451,18 @@ facelet_cache_lookup(const facelet_cache_t * facelet_cache, facelet_t * facelet,
}
*cached_facelets = malloc(n * sizeof(facelet_t*));
- DEBUG("cache match n = %d", n);
-
int num_match = 0;
for (unsigned i = 0; i < n; i++) {
char buf[128];
facelet_snprintf(buf, 128, facelet_array[i]);
- DEBUG("- facelet_array[%d] %s", i, buf);
facelet_snprintf(buf, 128, facelet);
- DEBUG(" facelet %s", buf);
- DEBUG("match ?");
if (!facelet_match(facelet_array[i], facelet)) {
- DEBUG("no match");
continue;
}
- DEBUG("match!");
(*cached_facelets)[num_match++] = facelet_array[i];
}
free(facelet_array);
- DEBUG("return nummatch=%d", num_match);
return num_match;
}
@@ -519,24 +517,36 @@ facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet)
return -3;
}
- /* IPv4 */
- bool ipv4;
- if (facemgr_cfg_get_ipv4(facemgr->cfg, &netdevice, netdevice_type,
- &ipv4) < 0)
- return -1;
- if (!ipv4) {
- DEBUG("Ignored IPv4...");
- return -3;
- }
+ switch(family) {
+ case AF_INET:
+ {
+ bool ipv4;
+ if (facemgr_cfg_get_ipv4(facemgr->cfg, &netdevice, netdevice_type,
+ &ipv4) < 0)
+ return -1;
+ if (!ipv4) {
+ DEBUG("Ignored IPv4 facelet...");
+ return -3;
+ }
+ break;
+ }
- /* IPv6 */
- bool ipv6;
- if (facemgr_cfg_get_ipv6(facemgr->cfg, &netdevice, netdevice_type,
- &ipv6) < 0)
- return -1;
- if (!ipv6) {
- DEBUG("Ignored IPv6...");
- return -3;
+ case AF_INET6:
+ {
+ bool ipv6;
+ if (facemgr_cfg_get_ipv6(facemgr->cfg, &netdevice, netdevice_type,
+ &ipv6) < 0)
+ return -1;
+ if (!ipv6) {
+ DEBUG("Ignored IPv6 facelet...");
+ return -3;
+ }
+ break;
+ }
+
+ default:
+ DEBUG("Ignored facelet with unknown family");
+ return -2;
}
return 0;
@@ -839,6 +849,7 @@ facemgr_process_create(facemgr_t * facemgr, facelet_t * facelet)
*/
rc = facemgr_facelet_satisfy_rules(facemgr, facelet);
if (rc == -3) {
+ facelet_set_status(facelet, FACELET_STATUS_IGNORED);
/* Does not satisfy rules */
return 0;
}
@@ -884,7 +895,7 @@ facemgr_process_create(facemgr_t * facemgr, facelet_t * facelet)
char facelet_s[MAXSZ_FACELET];
facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
- DEBUG("---[ FACELET CREATE : %s ] ---", facelet_s);
+ //DEBUG("---[ FACELET CREATE : %s ] ---", facelet_s);
/* Do we have enough information about the facelet ? */
if (!facelet_validate_face(facelet)) {
@@ -921,6 +932,7 @@ facemgr_process_create(facemgr_t * facemgr, facelet_t * facelet)
* \param [in] facemgr - Pointer to the face manager instance
* \param [in] facelet - Pointer to the facelet event to process
* \return 0 if everything went correctly, or -1 in case of error.
+ * -2 means we ignored the face purposedly
*/
int
facemgr_process_get(facemgr_t * facemgr, facelet_t * facelet)
@@ -931,10 +943,10 @@ facemgr_process_get(facemgr_t * facemgr, facelet_t * facelet)
if (facelet_get_netdevice(facelet, &netdevice) < 0)
return -1;
if (!IS_VALID_NETDEVICE(netdevice))
- return 0;
+ return -2;
return facelet_cache_add(&facemgr->facelet_cache, facelet);
}
- return 0;
+ return -2;
}
/**
@@ -959,7 +971,7 @@ facemgr_process_update(facemgr_t * facemgr, facelet_t * facelet)
char facelet_s[MAXSZ_FACELET];
facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
- DEBUG("---[ FACELET UPDATE : %s ] ---", facelet_s);
+ //DEBUG("---[ FACELET UPDATE : %s ] ---", facelet_s);
/* Sets face type */
if (!facelet_has_face_type(facelet)) {
@@ -1013,6 +1025,7 @@ facemgr_process_update(facemgr_t * facemgr, facelet_t * facelet)
rc = facemgr_facelet_satisfy_rules(facemgr, facelet);
if (rc == -3) {
+ facelet_set_status(facelet, FACELET_STATUS_IGNORED);
/* Does not satisfy rules */
return 0;
}
@@ -1048,6 +1061,7 @@ facemgr_process_update(facemgr_t * facemgr, facelet_t * facelet)
rc = facemgr_facelet_satisfy_rules(facemgr, facelet);
if (rc == -3) {
+ facelet_set_status(facelet, FACELET_STATUS_IGNORED);
/* Does not satisfy rules */
return 0;
}
@@ -1067,6 +1081,15 @@ facemgr_process_update(facemgr_t * facemgr, facelet_t * facelet)
case FACELET_STATUS_CONFLICT:
ERROR("[facemgr_process_update] Conflict resolution (not) yet implemented");
return -1;
+
+ case FACELET_STATUS_ERROR:
+ ERROR("[facemgr_process_update] Case ERROR (not) yet implemented");
+ break;
+
+ case FACELET_STATUS_IGNORED:
+ ERROR("[facemgr_process_update] Case IGNORED (not) yet implemented");
+ break;
+
case FACELET_STATUS_N:
ERROR("[facemgr_process_update] Facelet in error");
return -1;
@@ -1117,13 +1140,15 @@ facemgr_process_delete(facemgr_t * facemgr, facelet_t * facelet)
int
facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
{
+ bool remove_facelet = true;
int ret = 0;
+ int rc;
assert(facelet_in);
char facelet_s[MAXSZ_FACELET];
facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_in);
- DEBUG("----------------------------------");
- DEBUG("EVENT %s\n", facelet_s);
+ //DEBUG("----------------------------------");
+ DEBUG("EVENT %s", facelet_s);
facelet_t ** cached_facelets = NULL;
int n = facelet_cache_lookup(&facemgr->facelet_cache, facelet_in, &cached_facelets);
@@ -1131,7 +1156,6 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
ERROR("[facemgr_on_event] Error during cache lookup");
goto ERR;
}
- DEBUG("num matches n=%d", n);
if (n == 0) {
/* This is a new facelet... we expect a CREATE event. */
switch(facelet_get_event(facelet_in)) {
@@ -1141,7 +1165,9 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
ERROR("[facemgr_on_event] Error adding facelet to cache");
return -1;
}
- DEBUG("Facelet added to cache");
+ //DEBUG("Facelet added to cache");
+
+ remove_facelet = false;
if (facemgr_process_create(facemgr, facelet_in) < 0) {
ERROR("[facemgr_on_event] Error processing CREATE event");
@@ -1151,7 +1177,10 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
case FACELET_EVENT_GET:
/* Insert new facelet in cached */
- if (facemgr_process_get(facemgr, facelet_in) < 0) {
+ rc = facemgr_process_get(facemgr, facelet_in);
+ if (rc == 0)
+ remove_facelet = false;
+ if (rc == -1) {
ERROR("[facemgr_on_event] Error processing GET event");
goto ERR;
}
@@ -1189,7 +1218,6 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
* reconciliation by sending appropriate updates to the forwarder
*/
facelet_t * facelet = cached_facelets[i];
- DEBUG("... match #%d", i);
switch(facelet_get_event(facelet_in)) {
case FACELET_EVENT_CREATE:
// This case will occur when we try to re-create existing faces,
@@ -1247,14 +1275,41 @@ ERR:
ret = -1;
DUMP_CACHE:
+#if 1
DEBUG(" <CACHE>");
facelet_cache_dump(&facemgr->facelet_cache);
DEBUG(" </CACHE>");
DEBUG("</EVENT ret=%d>", ret);
DEBUG("----------------------------------");
+#endif
+
+ if (remove_facelet)
+ facelet_free(facelet_in);
+
return ret;
}
+int facemgr_callback(facemgr_t * facemgr, interface_cb_type_t type, void * data)
+{
+ switch(type) {
+ case INTERFACE_CB_TYPE_RAISE_EVENT:
+ return facemgr_on_event(facemgr, data);
+ case INTERFACE_CB_TYPE_REGISTER_FD:
+ return facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_REGISTER_FD, data);
+ case INTERFACE_CB_TYPE_REGISTER_TIMER:
+ return facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_REGISTER_TIMER, data);
+ case INTERFACE_CB_TYPE_UNREGISTER_TIMER:
+ return facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_UNREGISTER_TIMER, data);
+ case INTERFACE_CB_TYPE_UNREGISTER_FD:
+ return facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_UNREGISTER_FD, data);
+ }
+ return -1;
+}
+
int
facemgr_bootstrap(facemgr_t * facemgr)
{
@@ -1395,15 +1450,15 @@ void facemgr_stop(facemgr_t * facemgr)
facemgr_delete_interface(facemgr, facemgr->nl);
/* Delete all bonjour interfaces */
- interface_t ** bonjour_array;// = NULL; // NOTE: would allow avoiding tests
+ interface_t ** bonjour_array = NULL;
int n = bonjour_map_get_value_array(&facemgr->bonjour_map, &bonjour_array);
- if (n > 0) {
- netdevice_t ** netdevice_array; // = NULL;
+ if (n >= 0) {
+ netdevice_t ** netdevice_array = NULL;
int m = bonjour_map_get_key_array(&facemgr->bonjour_map, &netdevice_array);
- if (m > 0) {
+ if (m >= 0) {
assert(m == n);
for (int i = 0; i < n; i++) { /* Fail silently */
- DEBUG("Deleting bonjour interface associated to %s (%p)\n",
+ DEBUG("Deleting bonjour interface associated to %s (%p)",
netdevice_array[i]->name, bonjour_array[i]);
facemgr_delete_interface(facemgr, bonjour_array[i]);
}
@@ -1435,11 +1490,11 @@ void facemgr_set_jvm(facemgr_t * facemgr, JavaVM *jvm)
}
#endif /* __ANDROID__ */
-void facemgr_set_event_loop_handler(facemgr_t * facemgr, void * loop, void * loop_register_fd, void * loop_unregister_event)
+void
+facemgr_set_callback(facemgr_t * facemgr, void * callback_owner, facemgr_cb_t callback)
{
- facemgr->loop = loop;
- facemgr->loop_register_fd = loop_register_fd;
- facemgr->loop_unregister_event = loop_unregister_event;
+ facemgr->callback = callback;
+ facemgr->callback_owner = callback_owner;
}
void facemgr_list_faces(facemgr_t * facemgr, facemgr_list_faces_cb_t cb, void * user_data)
diff --git a/ctrl/facemgr/src/cfg.c b/ctrl/facemgr/src/cfg.c
index be7ea33bb..527da54e7 100644
--- a/ctrl/facemgr/src/cfg.c
+++ b/ctrl/facemgr/src/cfg.c
@@ -490,6 +490,20 @@ int
facemgr_cfg_finalize(facemgr_cfg_t * cfg)
{
/* TODO Free all rules */
+ facemgr_cfg_rule_t ** rule_array;
+ int n = facemgr_cfg_rule_set_get_array(cfg->rule_set, &rule_array);
+ if (n < 0) {
+ ERROR("[facemgr_cfg_finalize] Could not retrieve rule set array from configuration");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ facemgr_cfg_rule_t * rule = rule_array[i];
+ if (facemgr_cfg_rule_set_remove(cfg->rule_set, rule, NULL) < 0) {
+ ERROR("[facemgr_cfg_finalize] Could not remove rule from set");
+ }
+ facemgr_cfg_rule_free(rule);
+ }
+ free(rule_array);
+ }
facemgr_cfg_rule_set_free(cfg->rule_set);
return facemgr_cfg_override_finalize(&cfg->global);
}
@@ -531,6 +545,38 @@ facemgr_cfg_unset_discovery(facemgr_cfg_t * cfg)
return 0;
}
+int facemgr_cfg_set_ipv4(facemgr_cfg_t * cfg, bool status)
+{
+ cfg->global.is_ipv4 = true;
+ cfg->global.ipv4 = status;
+ DEBUG("<global>");
+ DEBUG(" <ipv4>%d</ipv4>", cfg->global.ipv4);
+ DEBUG("</global>");
+ return 0;
+}
+
+int facemgr_cfg_unset_ipv4(facemgr_cfg_t * cfg)
+{
+ cfg->global.is_ipv4 = false;
+ return 0;
+}
+
+int facemgr_cfg_set_ipv6(facemgr_cfg_t * cfg, bool status)
+{
+ cfg->global.is_ipv6 = true;
+ cfg->global.ipv6 = status;
+ DEBUG("<global>");
+ DEBUG(" <ipv6>%d</ipv6>", cfg->global.ipv6);
+ DEBUG("</global>");
+ return 0;
+}
+
+int facemgr_cfg_unset_ipv6(facemgr_cfg_t * cfg)
+{
+ cfg->global.is_ipv6 = false;
+ return 0;
+}
+
int
facemgr_cfg_set_overlay(facemgr_cfg_t * cfg, int family,
ip_address_t * local_addr, uint16_t local_port,
@@ -689,12 +735,10 @@ facemgr_cfg_get_override(const facemgr_cfg_t * cfg,
#endif /* __ANDROID__ */
}
/* Found match... do we have an override for face_type */
- DEBUG("override found nd=%s, ndt=%s", rule_array[i]->match.interface_name, netdevice_type_str[rule_array[i]->match.interface_type]);
*override = &rule_array[i]->override;
goto FOUND;
}
- DEBUG("override not found");
*override = NULL;
FOUND:
diff --git a/ctrl/facemgr/src/cfg_file.c b/ctrl/facemgr/src/cfg_file.c
new file mode 100644
index 000000000..5c187e0a2
--- /dev/null
+++ b/ctrl/facemgr/src/cfg_file.c
@@ -0,0 +1,548 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file cfg_file.c
+ * \brief Implementation of configuration file parsing
+ */
+
+#include <unistd.h> // access
+#include <libconfig.h>
+#include "cfg_file.h"
+
+#define ARRAYSIZE(x) (sizeof(x)/sizeof(*x))
+
+static const char * DEFAULT_CFGFILES[] = {
+ "/etc/facemgr.conf",
+ "~/facemgr.conf",
+};
+
+int
+probe_cfgfile(char * f)
+{
+ for (unsigned i = 0; i < ARRAYSIZE(DEFAULT_CFGFILES); i++) {
+ if (access(DEFAULT_CFGFILES[i], F_OK ) != -1) {
+ if (!realpath(DEFAULT_CFGFILES[i], f))
+ continue;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int
+parse_config_global(facemgr_cfg_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;
+ }
+
+ int rc = facemgr_cfg_set_face_type(cfg, &face_type);
+ if (rc < 0)
+ goto ERR;
+ }
+
+ /* - disable_discovery */
+
+ 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;
+ }
+
+ /* - disable_ipv4 */
+
+ int disable_ipv4;
+ if (config_setting_lookup_bool(setting, "disable_ipv4",
+ &disable_ipv4)) {
+ int rc = facemgr_cfg_set_ipv4(cfg, !disable_ipv4);
+ if (rc < 0)
+ goto ERR;
+ }
+
+ /* - disable ipv6 */
+
+ int disable_ipv6;
+ if (config_setting_lookup_bool(setting, "disable_ipv6",
+ &disable_ipv6)) {
+ int rc = facemgr_cfg_set_ipv6(cfg, !disable_ipv6);
+ if (rc < 0)
+ goto ERR;
+ }
+
+ /* - 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 = IP_ADDRESS_EMPTY;
+ ip_address_t remote_addr = IP_ADDRESS_EMPTY;
+ 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)) {
+ if (ip_address_pton(local_addr_str, &local_addr) < 0) {
+ ERROR("Error parsing v4 local addr");
+ goto ERR;
+ }
+ 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)) {
+ if (ip_address_pton(remote_addr_str, &remote_addr) < 0) {
+ ERROR("Error parsing v4 remote addr");
+ goto ERR;
+ }
+ 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;
+ }
+
+ /* 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 = IP_ADDRESS_EMPTY;
+ ip_address_t remote_addr = IP_ADDRESS_EMPTY;
+ 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)) {
+ if (ip_address_pton(local_addr_str, &local_addr) < 0) {
+ ERROR("Error parsing v6 local addr");
+ goto ERR;
+ }
+ 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)) {
+ if (ip_address_pton(remote_addr_str, &remote_addr) < 0) {
+ ERROR("Error parsing v6 remote addr");
+ goto ERR;
+ }
+ 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;
+ }
+
+ } /* 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;
+ }
+
+ 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;
+ }
+ }
+
+ 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;
+ }
+
+ /* - disable_discovery */
+
+ 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;
+ }
+
+ /* - disable_ipv4 */
+
+ 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
+ }
+
+ /* - 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);
+ if (tag == POLICY_TAG_N)
+ goto ERR;
+ policy_tags_add(&tags, tag);
+ }
+
+ 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);
+ 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 = IP_ADDRESS_EMPTY;
+ ip_address_t remote_addr = IP_ADDRESS_EMPTY;
+ 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 = IP_ADDRESS_EMPTY;
+ ip_address_t remote_addr = IP_ADDRESS_EMPTY;
+ 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;
+}
+
+/* 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:
+ 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_PARSE:
+ fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile),
+ config_error_line(&cfgfile), config_error_text(&cfgfile));
+ config_destroy(&cfgfile);
+ return -1;
+}
+
diff --git a/ctrl/facemgr/src/cfg_file.h b/ctrl/facemgr/src/cfg_file.h
new file mode 100644
index 000000000..dfce041d8
--- /dev/null
+++ b/ctrl/facemgr/src/cfg_file.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file cfg_file.h
+ * \brief Configuration file parsing
+ */
+
+#ifndef FACEMGR_CFG_FILE_H
+#define FACEMGR_CFG_FILE_H
+
+#include <hicn/facemgr/cfg.h>
+
+/**
+ * \brief Probe for the configuration file location
+ * \param [in] f - File name
+ * \return 0 in case of success, -1 otherwise.
+ */
+int probe_cfgfile(char * f);
+
+/**
+ * \brief Parses the provided configuration file into the facemgr configuration
+ * data structure.
+ * \param [in] cfgpath - Path to the configuration file
+ * \param [out] cfg - Pre-allocated configuration data structure
+ * \return 0 in case of success, -1 otherwise.
+ */
+int parse_config_file(const char * cfgpath, facemgr_cfg_t * cfg);
+
+#endif /* FACEMGR_CFG_FILE_H */
diff --git a/ctrl/facemgr/src/common.h b/ctrl/facemgr/src/common.h
index 9d6e8ca87..56bd706f1 100644
--- a/ctrl/facemgr/src/common.h
+++ b/ctrl/facemgr/src/common.h
@@ -28,9 +28,6 @@
//#define DEBUG
-/* Useful types and macros for comparisons */
-typedef int(*cmp_t)(const void * x, const void * y);
-
#define INT_CMP(x, y) x < y ? -1 : (x == y ? 0 : 1)
/* Dump with indent */
diff --git a/ctrl/facemgr/src/facelet.c b/ctrl/facemgr/src/facelet.c
index def901ff3..6d6d74c2b 100644
--- a/ctrl/facemgr/src/facelet.c
+++ b/ctrl/facemgr/src/facelet.c
@@ -80,7 +80,6 @@ struct facelet_s {
/* Joins */
bool bj_done;
bool au_done;
- int num_pending;
};
const char * facelet_event_str[] = {
@@ -111,7 +110,6 @@ facelet_create()
facelet->bj_done = false;
facelet->au_done = false;
- facelet->num_pending = 0;
facelet->event = FACELET_EVENT_UNDEFINED;
@@ -305,7 +303,6 @@ facelet_create_from_face(face_t * face)
facelet->bj_done = false;
facelet->au_done = false;
- facelet->num_pending = 0;
facelet->event = FACELET_EVENT_UNDEFINED;
@@ -343,7 +340,6 @@ facelet_dup(const facelet_t * current_facelet)
facelet->bj_done = current_facelet->bj_done;
facelet->au_done = current_facelet->au_done;
- facelet->num_pending = current_facelet->num_pending;
return facelet;
@@ -752,32 +748,6 @@ facelet_set_status(facelet_t * facelet, facelet_status_t status)
facelet->status = status;
}
-int
-facelet_add_pending(facelet_t * facelet)
-{
- assert(facelet);
- facelet->num_pending++;
- return 0;
-}
-
-int
-facelet_remove_pending(facelet_t * facelet)
-{
- assert(facelet);
- if (facelet->num_pending == 0)
- return -1;
- facelet->num_pending--;
- return 0;
-}
-
-bool
-facelet_has_pending(const facelet_t * facelet)
-{
- assert(facelet);
- DEBUG("num pending=%d\n", facelet->num_pending);
- return (facelet->num_pending > 0);
-}
-
void
facelet_set_bj_done(facelet_t * facelet)
{
@@ -790,7 +760,6 @@ facelet_unset_bj_done(facelet_t * facelet)
facelet->bj_done = false;
}
-
bool
facelet_is_bj_done(const facelet_t * facelet)
{
@@ -822,14 +791,6 @@ facelet_set_event(facelet_t * facelet, facelet_event_t event)
}
int
-facelet_raise_event(facelet_t * facelet, const interface_t * interface)
-{
- if (interface->callback)
- interface->callback(interface->callback_data, facelet);
- return 0;
-}
-
-int
facelet_snprintf(char * s, size_t size, facelet_t * facelet)
{
char * cur = s;
@@ -838,14 +799,13 @@ facelet_snprintf(char * s, size_t size, facelet_t * facelet)
assert(facelet);
/* Header + key attributes (netdevice + family) */
- rc = snprintf(cur, s + size - cur, "<Facelet %s (%s) [%d]",
+ rc = snprintf(cur, s + size - cur, "<Facelet %s (%s)",
// FIXME, better than the event would be the action to be performed next
facelet_event_str[facelet->event],
(facelet->family == AF_INET) ? "AF_INET" :
(facelet->family == AF_INET6) ? "AF_INET6" :
(facelet->family == AF_UNSPEC) ? "AF_UNSPEC" :
- "unknown",
- facelet->num_pending);
+ "unknown");
if (rc < 0)
return rc;
cur += rc;
@@ -1000,7 +960,7 @@ HEURISTIC_END:
}
if (facelet_has_face_type(facelet)) {
- rc = snprintf(cur, s + size - cur, " face_type=IP%s/%s",
+ rc = snprintf(cur, s + size - cur, " face_type=LAYER%s/%s",
FACEMGR_FACE_TYPE_STR(facelet->face_type));
if (rc < 0)
return rc;
diff --git a/ctrl/facemgr/src/facelet.h b/ctrl/facemgr/src/facelet.h
index e07572e23..16c23b12e 100644
--- a/ctrl/facemgr/src/facelet.h
+++ b/ctrl/facemgr/src/facelet.h
@@ -31,7 +31,7 @@
#include <hicn/ctrl/face.h>
#include <hicn/facemgr.h>
-#include "interface.h"
+#define MAXSZ_FACELET 1024
/* NOTE: Any test should be sufficient */
#define IS_VALID_NETDEVICE(netdevice) ((netdevice.index != 0) && (netdevice.name[0] != '\0'))
@@ -46,6 +46,8 @@ typedef struct facelet_s facelet_t;
_(DIRTY) \
_(CONFLICT) \
_(DELETED) \
+ _(IGNORED) \
+ _(ERROR) \
_(N)
typedef enum {
@@ -170,10 +172,6 @@ int facelet_merge(facelet_t * facelet, const facelet_t * facelet_to_merge);
facelet_status_t facelet_get_status(const facelet_t * facelet);
void facelet_set_status(facelet_t * facelet, facelet_status_t status);
-int facelet_add_pending(facelet_t * facelet);
-int facelet_remove_pending(facelet_t * facelet);
-bool facelet_has_pending(const facelet_t * facelet);
-
void facelet_set_bj_done(facelet_t * facelet);
void facelet_unset_bj_done(facelet_t * facelet);
bool facelet_is_bj_done(const facelet_t * facelet);
@@ -183,17 +181,12 @@ bool facelet_is_au_done(const facelet_t * facelet);
facelet_event_t facelet_get_event(const facelet_t * facelet);
void facelet_set_event(facelet_t * facelet, facelet_event_t event);
-/**
- * \brief Create and raises an event to the face manager
- * \param [in] event_type - Type of the event to create
- * \param [in] facelet - Facelet to communicate with the event
- * \param [in] interface - Interface that raised the event (or NULL if it was
- * created but the face manager itself, or is a joined event)
- */
-int facelet_raise_event(facelet_t * facelet, const interface_t * interface);
-
int facelet_snprintf(char * buf, size_t size, facelet_t * facelet);
-#define MAXSZ_FACELET 1024
+#define DUMP_FACELET(msg, facelet) do { \
+ char buf[MAXSZ_FACELET]; \
+ facelet_snprintf(buf, MAXSZ_FACELET, facelet); \
+ DEBUG("%s : %s", msg, buf); \
+} while(0)
#endif /* FACEMGR_FACELET_H */
diff --git a/ctrl/facemgr/src/interface.c b/ctrl/facemgr/src/interface.c
index 3e6bc0854..5cefcb98c 100644
--- a/ctrl/facemgr/src/interface.c
+++ b/ctrl/facemgr/src/interface.c
@@ -18,10 +18,12 @@
* \brief Implementation of interface base class.
*/
+#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "facelet.h"
#include "interface.h"
+#include <hicn/facemgr/loop.h> /* *_callback_data_t */
#include "util/map.h"
TYPEDEF_MAP_H(interface_ops_map, const char *, const interface_ops_t *);
@@ -41,6 +43,28 @@ interface_register(const interface_ops_t * ops)
return 0;
}
+int
+interface_unregister_all()
+{
+ int ret = 0;
+ const char ** ops_name_array = NULL;
+ int n = interface_ops_map_get_key_array(interface_ops_map, &ops_name_array);
+ if (n < 0) {
+ ERROR("[interface_unregister_all] Could not get interface ops array");
+ ret = -1;
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ const char * ops_name = ops_name_array[i];
+ if (interface_ops_map_remove(interface_ops_map, ops_name, NULL) < 0) {
+ ERROR("[interface_unregister_all] Could not remove %s from interface ops map", ops_name);
+ ret = -1;
+ }
+ }
+ free(ops_name_array);
+ }
+ return ret;
+}
+
interface_t *
interface_create(const char * name, const char * type)
{
@@ -60,7 +84,7 @@ interface_create(const char * name, const char * type)
/* this should use type */
interface->ops = ops;
interface->callback = NULL;
- interface->callback_data = NULL;
+ interface->callback_owner = NULL;
interface->data = NULL;
return interface;
@@ -74,10 +98,11 @@ interface_free(interface_t * interface)
}
void
-_interface_set_callback(interface_t * interface, callback_t callback, void * callback_data)
+interface_set_callback(interface_t * interface, void * callback_owner,
+ interface_cb_t callback)
{
interface->callback = callback;
- interface->callback_data = callback_data;
+ interface->callback_owner = callback_owner;
}
int
@@ -103,3 +128,59 @@ interface_on_event(interface_t * interface, const facelet_t * facelet)
return -1;
return interface->ops->on_event(interface, facelet);
}
+
+int
+interface_raise_event(interface_t * interface, facelet_t * facelet)
+{
+ assert(interface->callback);
+ return interface->callback(interface->callback_owner,
+ INTERFACE_CB_TYPE_RAISE_EVENT, facelet);
+}
+
+int
+interface_register_fd(interface_t * interface, int fd, void * data)
+{
+ assert(interface->callback);
+ fd_callback_data_t fd_callback = {
+ .fd = fd,
+ .owner = interface,
+ .callback = (fd_callback_t)interface->ops->callback,
+ .data = data,
+ };
+ return interface->callback(interface->callback_owner,
+ INTERFACE_CB_TYPE_REGISTER_FD, &fd_callback);
+}
+
+int
+interface_unregister_fd(interface_t * interface, int fd)
+{
+ assert(interface->callback);
+ return interface->callback(interface->callback_owner,
+ INTERFACE_CB_TYPE_UNREGISTER_FD, &fd);
+}
+
+typedef int (*interface_fd_callback_t)(interface_t * interface, int fd, void * unused);
+
+int
+interface_register_timer(interface_t * interface, unsigned delay_ms,
+ interface_fd_callback_t callback, void * data)
+{
+ assert(interface->callback);
+ timer_callback_data_t timer_callback = {
+ .delay_ms = delay_ms,
+ .owner = interface,
+ .callback = (fd_callback_t)callback,
+ .data = data,
+ };
+ int rc = interface->callback(interface->callback_owner,
+ INTERFACE_CB_TYPE_REGISTER_TIMER, &timer_callback);
+ return rc;
+}
+
+int
+interface_unregister_timer(interface_t * interface, int fd)
+{
+ assert(interface->callback);
+ return interface->callback(interface->callback_owner,
+ INTERFACE_CB_TYPE_UNREGISTER_TIMER, &fd);
+}
diff --git a/ctrl/facemgr/src/interface.h b/ctrl/facemgr/src/interface.h
index 331312bde..d99f4fc8e 100644
--- a/ctrl/facemgr/src/interface.h
+++ b/ctrl/facemgr/src/interface.h
@@ -29,15 +29,22 @@
#define FACEMGR_INTERFACE_H
#include <stdbool.h>
+#include <hicn/facemgr/loop.h>
-struct facelet_s;
-typedef int (*callback_t)(struct facelet_s * facelet, void * callback_data);
+typedef enum {
+ INTERFACE_CB_TYPE_REGISTER_FD,
+ INTERFACE_CB_TYPE_UNREGISTER_FD,
+ INTERFACE_CB_TYPE_RAISE_EVENT,
+ INTERFACE_CB_TYPE_REGISTER_TIMER,
+ INTERFACE_CB_TYPE_UNREGISTER_TIMER,
+} interface_cb_type_t;
-struct interface_s;
+typedef int (*interface_cb_t)(facemgr_t * facemgr, interface_cb_type_t type, void * data);
/**
* \brief Interface operations
*/
+struct interface_s;
typedef struct {
/** The type given to the interfaces */
char * type;
@@ -46,7 +53,7 @@ typedef struct {
/* Destructor */
int (*finalize)(struct interface_s * interface);
/* Callback upon file descriptor event (iif previously registered) */
- int (*callback)(struct interface_s * interface);
+ int (*callback)(struct interface_s * interface, int fd, void * data);
/* Callback upon face events coming from the face manager */
int (*on_event)(struct interface_s * interface, const struct facelet_s * facelet);
} interface_ops_t;
@@ -54,8 +61,10 @@ typedef struct {
typedef struct interface_s {
char * name;
const interface_ops_t * ops;
- callback_t callback;
- void * callback_data;
+
+ interface_cb_t callback;
+ void * callback_owner;
+
void * data;
} interface_t;
@@ -83,19 +92,51 @@ interface_t * interface_create(const char * name, const char * type);
*/
void interface_free(interface_t * interface);
-/**
- * This function is equivalent to interface_set_callback, which should be
- * preferred. The difference is the lack of explicit type casts which should
- * simplify the calling syntax.
- */
-void _interface_set_callback(interface_t * interface, callback_t callback, void * callback_data);
-#define interface_set_callback(interface, callback, callback_data) \
- _interface_set_callback(interface, (callback_t)callback, (void*)callback_data)
+void interface_set_callback(interface_t * interface, void * callback_owner, interface_cb_t callback);
int interface_initialize(interface_t * interface, void * cfg);
+
int interface_finalize(interface_t * interface);
int interface_on_event(interface_t * interface, const struct facelet_s * facelet);
+/**
+ * \brief Raises a facelet event to the face manager
+ * \param [in] interface - Interface that raised the event (or NULL if it was
+ * created but the face manager itself, or is a joined event)
+ * \param [in] facelet - Facelet to communicate with the event
+ * \return Error code
+ */
+int interface_callback(interface_t * interface, interface_cb_type_t type, void * data);
+
+int interface_raise_event(interface_t * interface, facelet_t * facelet);
+
+int interface_register_fd(interface_t * interface, int fd, void * data);
+
+int interface_unregister_fd(interface_t * interface, int fd);
+
+typedef int (*interface_fd_callback_t)(interface_t * interface, int fd, void * unused);
+
+/**
+ * \brief Registers a timer event
+ * \param [in] interface - Pointer to the interface responsible for the timer
+ * \param [in] delay_ms - Delay in milliseconds between timer events (first
+ * occurence happends after this delay)
+ * \param [in] callback - Callback function to be triggered
+ * \param [in] data - User data
+ * \return A positive value uniquely identifying the timer, or -1 in case of
+ * error
+ */
+int interface_register_timer(interface_t * interface, unsigned delay_ms,
+ interface_fd_callback_t callback, void * data);
+
+/**
+ * \brief Unregisters a timer event
+ * \param [in] interface - Pointer to the interface responsible for the timer
+ * \param [in] fd - Timer identifier
+ * \return 0 in case of success, -1 otherwise
+ */
+int interface_unregister_timer(interface_t * interface, int fd);
+
#endif /* FACEMGR_INTERFACE_H */
diff --git a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
index bb612507f..a4aa2cbfc 100644
--- a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
+++ b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
@@ -124,7 +124,7 @@ int au_on_event(interface_t * interface, const facelet_t * facelet)
DEBUG("sending AU udpate");
facelet_set_event(facelet_new, FACELET_EVENT_UPDATE);
- facelet_raise_event(facelet_new, interface);
+ interface_raise_event(interface, facelet_new);
return 0;
}
diff --git a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c
index d7b27b995..4d09d89bb 100644
--- a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c
+++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c
@@ -107,7 +107,9 @@ int bj_initialize(interface_t * interface, void * cfg)
WSAStartup(versionWanted, &wsaData);
#endif
- return data->sock;
+ interface_register_fd(interface, data->sock, NULL);
+
+ return 0;
ERR_BUFFER:
#ifndef __ANDROID__
@@ -268,7 +270,7 @@ callback(const struct sockaddr* from, mdns_entry_type_t entry, uint16_t type,
//facelet_set_remote_port(facelet, ((struct sockaddr_in*)&addr)->sin_port);
facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- facelet_raise_event(facelet, interface);
+ interface_raise_event(interface, facelet);
break;
}
@@ -291,7 +293,7 @@ callback(const struct sockaddr* from, mdns_entry_type_t entry, uint16_t type,
//facelet_set_remote_port(facelet, ((struct sockaddr_in6*)&addr)->sin6_port);
facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- facelet_raise_event(facelet, interface);
+ interface_raise_event(interface, facelet);
break;
}
@@ -317,7 +319,7 @@ callback(const struct sockaddr* from, mdns_entry_type_t entry, uint16_t type,
facelet_set_remote_port(facelet, srv.port);
facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- facelet_raise_event(facelet, interface);
+ interface_raise_event(interface, facelet);
facelet = facelet_create();
facelet_set_netdevice(facelet, bj_data->cfg.netdevice);
@@ -325,7 +327,7 @@ callback(const struct sockaddr* from, mdns_entry_type_t entry, uint16_t type,
facelet_set_remote_port(facelet, srv.port);
facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- facelet_raise_event(facelet, interface);
+ interface_raise_event(interface, facelet);
break;
}
@@ -374,7 +376,7 @@ callback(const struct sockaddr* from, mdns_entry_type_t entry, uint16_t type,
* The fact we use a single fd does not allow us to get user_data associated to
* the query.
*/
-int bj_callback(interface_t * interface)
+int bj_callback(interface_t * interface, int fd, void * unused)
{
bj_data_t * data = (bj_data_t*)interface->data;
DEBUG("Got an mDNS reply");
diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
index 2fdc3f7c3..1f20177c2 100644
--- a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
+++ b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
@@ -17,6 +17,7 @@
* \file interfaces/hicn_light/hicn_light.c
* \brief hICN light interface
*/
+#include <assert.h>
#include <stdbool.h>
#include <stdio.h> // snprintf
#include <time.h> // time
@@ -32,34 +33,43 @@
#define DEFAULT_ROUTE_COST 0
+#define INTERVAL_MS 1000
+
typedef enum {
HL_STATE_UNDEFINED,
+ HL_STATE_CONNECTING,
HL_STATE_FACES_SENT,
HL_STATE_DONE,
} hl_state_t;
typedef struct {
- hc_sock_t * s;
+ hc_sock_t * s; /* NULL means no active socket */
hl_state_t state;
+ int timer_fd; /* 0 means no active timer */
} hl_data_t;
+/* Forward declarations */
+int hl_timeout(interface_t * interface, int fd, void * unused);
+
int hl_process_state(interface_t * interface)
{
hl_data_t * data = (hl_data_t *)interface->data;
- hc_data_t * faces;
#if 0
char buf[MAXSZ_FACE];
#endif
switch(data->state)
{
- case HL_STATE_UNDEFINED:
- if (hc_face_list(data->s, &faces) < 0) {
+ case HL_STATE_UNDEFINED: // FIXME
+ case HL_STATE_CONNECTING: // FIXME
+ if (hc_face_list_async(data->s) < 0) {
/* Blocking call */
printf("Could not retrieve face list\n");
return -1;
}
+ break;
+#if 0
foreach_face(f, faces) {
#if 0
hc_face_snprintf(buf, MAXSZ_FACE, f);
@@ -67,9 +77,10 @@ int hl_process_state(interface_t * interface)
#endif
facelet_t * facelet = facelet_create_from_face(&f->face);
facelet_set_event(facelet, FACELET_EVENT_GET);
- facelet_raise_event(facelet, interface);
+ interface_raise_event(interface, facelet);
}
break;
+#endif
case HL_STATE_FACES_SENT:
break;
@@ -81,36 +92,132 @@ int hl_process_state(interface_t * interface)
return 0;
}
-int hl_initialize(interface_t * interface, void * cfg)
+
+int
+hl_after_connect(interface_t * interface)
{
- hl_data_t * data = malloc(sizeof(hl_data_t));
- if (!data) {
- ERROR("[hicn_light] Out of memory!");
- goto ERR_MALLOC;
+ hl_data_t * data = interface->data;
+ // XXX cancel timer
+
+ /* File descriptor for control socket operations */
+ if (interface_register_fd(interface, hc_sock_get_fd(data->s), NULL) < 0) {
+ ERROR("[hc_connect] Error registering fd");
+ goto ERR_FD;
+ }
+
+ data->state = HL_STATE_UNDEFINED;
+
+ hl_process_state(interface);
+
+ return 0;
+
+ //interface_unregister_fd(interface, hc_sock_get_fd(data->s));
+ERR_FD:
+ return -1;
+}
+
+int _hl_connect(interface_t * interface);
+
+int
+hl_connect_timeout(interface_t * interface, int fd, void * unused)
+{
+ int rc = _hl_connect(interface);
+ if (rc < 0) {
+ ERROR("[hl_initialize] Error during connection reattempt; next attempt in %ds", INTERVAL_MS / 1000);
+ return -1;
}
+ if (interface_unregister_timer(interface, fd) < 0) {
+ ERROR("[hl_connect_timeout] Could not cancel timer after successful connect");
+ }
+
+ /* Connect success */
+ return hl_after_connect(interface);
+}
+
+
+int
+_hl_connect(interface_t * interface)
+{
+ hl_data_t * data = interface->data;
+ assert(!data->s);
+
data->s = hc_sock_create();
if (data->s <= 0) {
- ERROR("[hicn_light] Could not create control socket");
+ ERROR("[hc_connect] Could not create control socket");
goto ERR_SOCK;
}
if (hc_sock_connect(data->s) < 0) {
- ERROR("[hicn_light] Could not connect control socket");
+ ERROR("[hc_connect] Could not connect control socket");
goto ERR_CONNECT;
}
- data->state = HL_STATE_UNDEFINED;
+ return hl_after_connect(interface);
+
+ERR_CONNECT:
+ hc_sock_free(data->s);
+ data->s = NULL;
+ERR_SOCK:
+ return -1;
+
+}
+
+int hl_disconnect(interface_t * interface)
+{
+ hl_data_t * data = (hl_data_t *) interface->data;
+ if (data->timer_fd > 0)
+ interface_unregister_timer(interface, data->timer_fd);
+
+ if (data->s) {
+ interface_unregister_fd(interface, hc_sock_get_fd(data->s));
+ hc_sock_free(data->s);
+ }
+
+ return 0;
+}
+
+int
+hl_connect(interface_t * interface)
+{
+ hl_data_t * data = interface->data;
+
+ if (_hl_connect(interface) >= 0)
+ return 0;
+
+ /* Timer for managing the connection to the forwarder */
+ DEBUG("Connection to forwarder failed... next retry in %ds", INTERVAL_MS / 1000);
+ data->timer_fd = interface_register_timer(interface, INTERVAL_MS, hl_connect_timeout, NULL);
+ if (data->timer_fd < 0) {
+ ERROR("[hc_connect] Could not initialize reattempt timer");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+hl_initialize(interface_t * interface, void * cfg)
+{
+ hl_data_t * data = malloc(sizeof(hl_data_t));
+ if (!data) {
+ ERROR("[hicn_light] Out of memory!");
+ goto ERR_MALLOC;
+ }
+
+ data->s = NULL;
+ data->timer_fd = 0;
interface->data = data;
- hl_process_state(interface);
+ if (hl_connect(interface) < 0) {
+ ERROR("[hl_initialize] Error during connection to forwarder");
+ goto ERR_CONNECT;
+ }
return 0;
ERR_CONNECT:
- hc_sock_free(data->s);
-ERR_SOCK:
free(data);
ERR_MALLOC:
return -1;
@@ -118,8 +225,12 @@ ERR_MALLOC:
int hl_finalize(interface_t * interface)
{
- //hc_data_t * data = interface->data;
- //hc_sock_close(data->s);
+ hl_data_t * data = (hl_data_t *) interface->data;
+
+ hl_disconnect(interface);
+
+ free(data);
+
return 0;
}
@@ -131,9 +242,23 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
hl_data_t * data = (hl_data_t *)interface->data;
face_t * face = NULL;
- if (facelet_get_face(facelet, &face) < 0)
+
+ /* NOTE
+ * - One example where this fails (and it is normal) is when we delete a
+ * face that was not completely created, because for instance bonjour did
+ * not give any data
+ */
+ if (facelet_get_face(facelet, &face) < 0) {
+ ERROR("Could not retrieve face from facelet");
+ return -1;
+ }
+
+ if (!data->s) {
+ /* We are not connected to the forwarder */
return -1;
+ }
+
switch(facelet_get_event(facelet)) {
case FACELET_EVENT_CREATE:
@@ -147,10 +272,10 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
}
INFO("Created face id=%d\n", hc_face.id);
-#if 0
- /* Add default route v4 */
+ /* Adding default routs e*/
+#if 1
route = (hc_route_t) {
- .face_id = face.id,
+ .face_id = hc_face.id,
.family = AF_INET,
.remote_addr = IPV4_ANY,
.len = 0,
@@ -161,12 +286,9 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
ERROR("Failed to create default hICN/IPv4 route");
goto ERR;
}
- INFO("Successfully created default hICN/IPv4 route.");
-#endif
-#if 0
route = (hc_route_t) {
- .face_id = face.id,
+ .face_id = hc_face.id,
.family = AF_INET6,
.remote_addr = IPV6_ANY,
.len = 0,
@@ -176,9 +298,8 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
ERROR("Failed to create default hICN/IPv6 route");
goto ERR;
}
-#endif
- /* Adding default route */
+#else
route = (hc_route_t) {
.face_id = hc_face.id,
.family = AF_INET6,
@@ -193,6 +314,8 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
ERROR("Failed to create hICN/IPv6 route");
goto ERR;
}
+#endif
+ INFO("Successfully created default route(s).");
break;
@@ -212,6 +335,8 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
if (facelet_get_admin_state_status(facelet) == FACELET_ATTR_STATUS_DIRTY) {
hc_face.face = *face;
hc_face_t * face_found;
+
+ printf("hc_face_get\n");
rc = hc_face_get(data->s, &hc_face, &face_found);
if (rc < 0) {
ERROR("Failed to find face\n");
@@ -224,7 +349,6 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
char conn_id_or_name[SYMBOLIC_NAME_LEN];
snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id);
free(face_found);
- printf("Face id = %d\n", face_found->id);
face_state_t admin_state;
if (facelet_get_admin_state(facelet, &admin_state) < 0) {
@@ -233,6 +357,7 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
}
printf("Setting admin state");
+ printf("hc_connection_set_admin_state\n");
if (hc_connection_set_admin_state(data->s, conn_id_or_name, admin_state) < 0) {
ERROR("Failed to update admin state");
goto ERR;
@@ -247,15 +372,56 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
goto ERR;
}
+ face_free(face);
return 0;
ERR:
+ face_free(face);
return -1;
}
+int hl_callback(interface_t * interface, int fd, void * unused)
+{
+ hl_data_t * data = (hl_data_t*)interface->data;
+
+ hc_data_t * faces;
+ if (hc_sock_callback(data->s, &faces) < 0){
+ DEBUG("Closing socket... reconnecting...");
+ if (interface_unregister_fd(interface, hc_sock_get_fd(data->s)) < 0) {
+ ERROR("[hl_initialize] Error registering fd");
+ }
+ hc_sock_free(data->s);
+ data->s = NULL;
+ hl_connect(interface);
+ return 0;
+ }
+
+ if (faces->complete) {
+ foreach_face(f, faces) {
+#if 1
+ char buf[MAXSZ_FACE];
+ hc_face_snprintf(buf, MAXSZ_FACE, f);
+ printf("Face: %s\n", buf);
+#else
+ facelet_t * facelet = facelet_create_from_face(&f->face);
+ facelet_set_event(facelet, FACELET_EVENT_GET);
+ interface_raise_event(interface, facelet);
+#endif
+ }
+ }
+ hc_data_free(faces);
+
+ /* XXX how do we know what object we get back */
+
+ /* We have a queue of pending data elements per active query */
+
+ return 0;
+}
+
const interface_ops_t hicn_light_ops = {
.type = "hicn_light",
.initialize = hl_initialize,
.finalize = hl_finalize,
.on_event = hl_on_event,
+ .callback = hl_callback,
};
diff --git a/ctrl/facemgr/src/interfaces/netlink/netlink.c b/ctrl/facemgr/src/interfaces/netlink/netlink.c
index 08cbe4d3b..babf1c305 100644
--- a/ctrl/facemgr/src/interfaces/netlink/netlink.c
+++ b/ctrl/facemgr/src/interfaces/netlink/netlink.c
@@ -67,6 +67,7 @@ int nl_process_state(interface_t * interface)
switch(data->state) {
case NL_STATE_UNDEFINED:
{
+ DEBUG("[nl_process_state] UNDEFINED->LINK_SENT");
struct {
struct nlmsghdr header;
struct rtgenmsg payload;
@@ -93,6 +94,7 @@ int nl_process_state(interface_t * interface)
case NL_STATE_LINK_SENT:
{
+ DEBUG("[nl_process_state] LINK_SENT->ADDR_SENT");
/* Issue a first query to receive static state */
struct {
struct nlmsghdr header;
@@ -120,6 +122,7 @@ int nl_process_state(interface_t * interface)
case NL_STATE_ADDR_SENT:
{
+ DEBUG("[nl_process_state] ADDR_SENT->DONE");
data->state = NL_STATE_DONE;
break;
}
@@ -167,9 +170,13 @@ int nl_initialize(interface_t * interface, void * cfg)
interface->data = data;
+ interface_register_fd(interface, data->fd, NULL);
+
+#if 1
nl_process_state(interface);
+#endif
- return data->fd; // 0;
+ return 0;
ERR_BIND:
close(data->fd);
@@ -205,7 +212,7 @@ int parse_link(struct nlmsghdr * h, facelet_t ** facelet,
*facelet = facelet_create();
netdevice_t * netdevice = netdevice_create_from_name(interface_name);
if (!netdevice)
- goto ERROR;
+ goto ERROR_ND;
int rc = facelet_set_netdevice(*facelet, *netdevice);
if (rc < 0)
goto ERROR;
@@ -237,9 +244,12 @@ int parse_link(struct nlmsghdr * h, facelet_t ** facelet,
// - ifi_change
// - IFLA_PROTINFO
+ netdevice_free(netdevice);
return 0;
ERROR:
+ netdevice_free(netdevice);
+ERROR_ND:
facelet_free(*facelet);
*facelet = NULL;
@@ -303,7 +313,7 @@ int parse_addr(struct nlmsghdr * h, facelet_t ** facelet,
netdevice_t * netdevice = netdevice_create_from_index(ifa->ifa_index);
if (!netdevice) {
ERROR("[netlink.parse_addr] error creating netdevice '%s'", interface_name);
- goto ERROR;
+ goto ERROR_ND;
}
if (interface_name) {
@@ -324,16 +334,19 @@ int parse_addr(struct nlmsghdr * h, facelet_t ** facelet,
goto ERROR;
}
+ netdevice_free(netdevice);
return 0;
ERROR:
+ netdevice_free(netdevice);
+ERROR_ND:
facelet_free(*facelet);
*facelet = NULL;
return -1;
}
-int nl_callback(interface_t * interface)
+int nl_callback(interface_t * interface, int fd, void * unused)
{
nl_data_t * data = (nl_data_t*)interface->data;
@@ -403,10 +416,10 @@ int nl_callback(interface_t * interface)
break;
}
- DEBUG("Interface %s: address was removed", interface_name);
+ //DEBUG("Interface %s: address was removed", interface_name);
if (facelet) {
facelet_set_event(facelet, FACELET_EVENT_DELETE);
- facelet_raise_event(facelet, interface);
+ interface_raise_event(interface, facelet);
}
break;
}
@@ -423,11 +436,11 @@ int nl_callback(interface_t * interface)
break;
}
- DEBUG("Interface %s: new address was assigned: %s", interface_name, interface_address);
+ //DEBUG("Interface %s: new address was assigned: %s", interface_name, interface_address);
if (facelet) {
facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- facelet_raise_event(facelet, interface);
+ interface_raise_event(interface, facelet);
}
break;
}
@@ -441,12 +454,15 @@ int nl_callback(interface_t * interface)
ERROR("Error parsing link message");
break;
}
- if (facelet) {
- facelet_set_event(facelet, FACELET_EVENT_DELETE);
- facelet_raise_event(facelet, interface);
- }
- DEBUG("Network interface %s was removed", interface_name);
+ //DEBUG("Network interface %s was removed", interface_name);
+
+ if (!facelet)
+ break;
+
+ facelet_set_event(facelet, FACELET_EVENT_DELETE);
+ interface_raise_event(interface, facelet);
+
break;
}
@@ -464,11 +480,15 @@ int nl_callback(interface_t * interface)
// UP RUNNING
// UP NOT RUNNING
// DOWN NOT RUNNING
+#if 0
DEBUG("New network interface %s, state: %s %s", interface_name,
up ? "UP" : "DOWN",
running ? "RUNNING" : "NOT_RUNNING");
+#endif
- if (facelet && up && running) {
+ if (!facelet)
+ break;
+ if (up && running) {
facelet_set_event(facelet, FACELET_EVENT_CREATE);
facelet_t * facelet6 = facelet_dup(facelet);
if (!facelet6) {
@@ -477,10 +497,12 @@ int nl_callback(interface_t * interface)
}
facelet_set_family(facelet, AF_INET);
- facelet_raise_event(facelet, interface);
+ interface_raise_event(interface, facelet);
facelet_set_family(facelet6, AF_INET6);
- facelet_raise_event(facelet6, interface);
+ interface_raise_event(interface, facelet6);
+ } else {
+ facelet_free(facelet);
}
break;
}
@@ -507,6 +529,7 @@ int nl_finalize(interface_t * interface)
{
nl_data_t * data = (nl_data_t*)interface->data;
close(data->fd);
+ free(interface->data);
return 0;
}
diff --git a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
index ed2f88e9e..f438d34d5 100644
--- a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
+++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
@@ -18,6 +18,8 @@
* \brief Implementation of Network framework interface
*/
+#include "Availability.h"
+
#include <sys/socket.h>
#include <arpa/inet.h>
@@ -36,6 +38,11 @@
#include "network_framework.h"
+#if !defined(MAC_OS_X_VERSION_10_14)
+#error "Network frameork requires MacOSX 10.14+"
+#endif /* !defined(MAC_OS_X_VERSION_10_14) */
+
+
/*
* Bonjour service discovery for hICN forwarder
*
@@ -59,7 +66,7 @@
#define BONJOUR_PROTOCOL udp
#define BONJOUR_SERVICE_DOMAIN "local"
-#define BONJOUR_SERVICE_NAME "hicn"
+#define BONJOUR_SERVICE_NAME "hicn node"
/* Generated variables */
#define BONJOUR_SERVICE_TYPE "_hicn._" STRINGIZE(BONJOUR_PROTOCOL)
@@ -80,7 +87,7 @@ const char * interface_type_str[] = {
"OTHER", "WIFI", "CELLULAR", "WIRED", "LOOPBACK",
};
-#if 0
+#if 1
typedef enum {
PATH_STATUS_INVALID,
PATH_STATUS_SATISTIED,
@@ -212,6 +219,28 @@ dump_connection(nw_connection_t connection, int indent)
nw_release(path);
}
+#if defined(MAC_OS_X_VERSION_10_15)
+void
+dump_browse_result(nw_browse_result_t result, int indent)
+{
+ /* Endpoint */
+ nw_endpoint_t browse_endpoint = nw_browse_result_copy_endpoint(result);
+ if (!bendpoint) {
+ ERROR("[network_framework.dump_result] Failed to retrieve endpoint from Bonjour browse result");
+ return;
+ }
+ printfi(indent + 1, "Endpoint:")
+ dump_endpoint(browse_endpoint, indent + 2);
+
+ /* Interfaces */
+ printfi(indent + 1, "Interfaces:")
+ nw_browse_result_enumerate_interfaces(result, ^(nw_interface_t interface) {
+ dump_interface(interface, index + 2);
+ return true;
+ });
+}
+#endif /* defined(MAC_OS_X_VERSION_10_15) */
+
facelet_t *
facelet_create_from_connection(nw_connection_t connection)
{
@@ -302,7 +331,7 @@ void
on_connection_state_event(interface_t * interface, nw_interface_t iface,
nw_connection_t cnx, nw_connection_state_t state, nw_error_t error)
{
-#if 0
+#if 1
DEBUG("Connection [new state = %s]:\n", connection_state_str[state]);
nw_path_t path = nw_connection_copy_current_path(cnx);
nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t interface) {
@@ -331,7 +360,9 @@ on_connection_state_event(interface_t * interface, nw_interface_t iface,
case nw_connection_state_ready:
{
-#if 0
+ printf("info:\n");
+ warn("connection ready");
+#if 1
WITH_DEBUG({
dump_connection(cnx, 1);
});
@@ -340,7 +371,7 @@ on_connection_state_event(interface_t * interface, nw_interface_t iface,
if (!facelet)
return;
facelet_set_event(facelet, FACELET_EVENT_CREATE);
- facelet_raise_event(facelet, interface);
+ interface_raise_event(interface, facelet);
break;
}
case nw_connection_state_failed:
@@ -371,10 +402,10 @@ void
on_connection_path_event(interface_t * interface, nw_interface_t iface,
nw_connection_t cnx, nw_path_t path)
{
-#if 0
+#if 1
DEBUG("Connection [path changed]:\n");
WITH_DEBUG({
- //dump_connection(cnx, 1);
+ dump_connection(cnx, 1);
});
#endif
/* redundant *//*
@@ -418,15 +449,7 @@ void on_interface_event(interface_t * interface, nw_interface_t iface)
* time, if none is discovered, we cannot do any tunnel face.
*/
- nw_endpoint_t endpoint;
-
- endpoint = nw_endpoint_create_bonjour_service(
- BONJOUR_SERVICE_NAME,
- BONJOUR_SERVICE_TYPE,
- BONJOUR_SERVICE_DOMAIN);
-
- if (!endpoint)
- goto ERR;
+ // OLD CODE
/* nw_parameters_create_secure_{udp,tcp} */
nw_parameters_t parameters = nw_parameters_create_fn(
@@ -434,14 +457,93 @@ void on_interface_event(interface_t * interface, nw_interface_t iface)
NW_PARAMETERS_DEFAULT_CONFIGURATION /* default udp/tcp */);
if (!parameters)
- goto ERR;
+ goto ERR_PARAMETERS;
nw_parameters_require_interface(parameters, iface);
nw_parameters_set_reuse_local_address(parameters, true);
+#if defined(MAC_OS_X_VERSION_10_15)
+ /*
+ * Before being able to create a bonjour endpoint, we need to browse for
+ * available services on the local network using the parameters specified
+ * before.
+ */
+ nw_browse_descriptor_t descriptor = nw_browse_descriptor_create_bonjour_service(BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN);
+ if (!descriptor) {
+ ERROR("[network_framework.on_interface_event] Failed to create a bonjour browse descriptor");
+ goto ERR_DESCRIPTOR;
+ }
+
+ nw_browser_t browser = nw_browser_create(descriptor, parameters);
+ nw_browser_set_queue(browser, dispatch_get_main_queue());
+ nw_browser_set_browse_results_changed_handler(browser, ^(nw_browse_result_t result, nw_browse_result_t result2, bool flag) {
+ /* Dump result */
+ printfi(0, "NEW BROWSE RESULT");
+ printfi(1, "Result:");
+ dump_browse_result(result, 2);
+ printfi(1, "Result2:");
+ dump_browse_result(result2, 2);
+ printfi("Flag: %s\n", flag?"ON":"OFF");
+
+ /* Changes */
+ nw_browse_result_change_t change = nw_browse_result_get_changes(result, result2);
+ switch(change) {
+ case nw_browse_result_change_identical:
+ printfi("The compared services are identical.");
+ break;
+ case nw_browse_result_change_result_added:
+ printfi(2, "A new service was discovered.");
+ break;
+
+ case nw_browse_result_change_result_removed:
+ printfi(2, "A previously discovered service was removed.");
+ break;
+
+ case nw_browse_result_change_txt_record_changed:
+ printfi(2, "The service's associated TXT record changed.");
+ break;
+
+ case nw_browse_result_change_interface_added:
+ printfi(2, "The service was discovered over a new interface.");
+ break;
+
+nw_browse_result_change_interface_removed
+ printfi(2, "The service was no longer discovered over a certain interface.");
+ break;
+ }
+ });
+
+ browser.browseResultsChangedHandler = { browseResults, _ in
+ for browseResult in browseResults {
+ print("Discovered \(browseResult.endpoint) over \(browseResult.interfaces)")
+ }
+ }
+ nw_browser_start(browser);
+//#else
+//#warning "Bonjour discovery only available in MacOS 10.15+"
+#endif /* defined(MAC_OS_X_VERSION_10_15) */
+
+ /*
+ * Now that we have resolve the name of a bonjour remote, we can create a
+ * connection to the corresponding endpoint identified by its name.
+ */
+ nw_endpoint_t endpoint;
+
+ DEBUG("Creating bonjour service towards NAME=%s TYPE=%s DOMAIN=%s",
+ BONJOUR_SERVICE_NAME, BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN);
+ endpoint = nw_endpoint_create_bonjour_service(
+ BONJOUR_SERVICE_NAME,
+ BONJOUR_SERVICE_TYPE,
+ BONJOUR_SERVICE_DOMAIN);
+
+ if (!endpoint) {
+ ERROR("[network_framework.on_interface_event] Failed to create bound Bonjour connection");
+ goto ERR_ENDPOINT;
+ }
+
nw_connection_t connection = nw_connection_create(endpoint, parameters);
if (!connection)
- goto ERR;
+ goto ERR_CONNECTION;
nw_release(endpoint);
nw_release(parameters);
@@ -460,7 +562,7 @@ void on_interface_event(interface_t * interface, nw_interface_t iface)
});
nw_connection_set_better_path_available_handler(connection, ^(bool value) {
-#if 0
+#if 1
DEBUG("Connection [better path = %s]\n", (value ? "true" : "false"));
WITH_DEBUG({
dump_connection(connection, 1);
@@ -469,7 +571,7 @@ void on_interface_event(interface_t * interface, nw_interface_t iface)
});
nw_connection_set_viability_changed_handler(connection, ^(bool value) {
-#if 0
+#if 1
DEBUG("Connection [viable = %s]\n", (value ? "true" : "false"));
WITH_DEBUG({
//dump_connection(connection, 1);
@@ -484,7 +586,7 @@ void on_interface_event(interface_t * interface, nw_interface_t iface)
if (!facelet)
return;
facelet_set_event(facelet, value ? FACELET_EVENT_CREATE : FACELET_EVENT_DELETE);
- facelet_raise_event(facelet, interface);
+ interface_raise_event(interface, facelet);
});
@@ -493,14 +595,26 @@ void on_interface_event(interface_t * interface, nw_interface_t iface)
nw_connection_set_queue(connection, dispatch_get_main_queue());
nw_retain(connection); // Hold a reference until cancelled
-#if 0
- DEBUG("Created Bonjour cnx on interface:\n");
+#if 1
+ DEBUG("Created Bonjour cnx on interface:");
WITH_DEBUG({
dump_interface(iface, 1);
});
#endif
-ERR:
+ return;
+
+ nw_release(connection);
+ERR_CONNECTION:
+ nw_release(endpoint);
+ERR_ENDPOINT:
+#if defined(MAC_OS_X_VERSION_10_15)
+ nw_release(descriptor);
+ERR_DESCRIPTOR:
+#endif /* defined(MAC_OS_X_VERSION_10_15) */
+ nw_release(parameters);
+
+ERR_PARAMETERS:
return;
}
@@ -509,7 +623,7 @@ void on_path_event(interface_t * interface, nw_path_t path)
/* Simplification: we handle path event only once.
* Ideally, test whether we discover new interfaces or not
*/
-#if 0
+#if 1
DEBUG("Path [event]:\n");
WITH_DEBUG({
dump_path(path, 1);
@@ -529,6 +643,9 @@ int nf_initialize(interface_t * interface, void * cfg)
if (!data)
goto ERR_MALLOC;
+ if (cfg)
+ data->cfg = * (network_framework_cfg_t *)cfg;
+
data->pm = nw_path_monitor_create();
if (!data->pm)
goto ERR_PM;
diff --git a/ctrl/facemgr/src/interfaces/updown/updown.c b/ctrl/facemgr/src/interfaces/updown/updown.c
index f5a813cd4..c864c8c04 100644
--- a/ctrl/facemgr/src/interfaces/updown/updown.c
+++ b/ctrl/facemgr/src/interfaces/updown/updown.c
@@ -125,7 +125,7 @@ int updown_callback(interface_t * interface)
facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- facelet_raise_event(facelet, interface);
+ interface_raise_event(interface, facelet);
return 0;
}
diff --git a/ctrl/facemgr/src/loop_dispatcher.c b/ctrl/facemgr/src/loop_dispatcher.c
new file mode 100644
index 000000000..7e7f9d667
--- /dev/null
+++ b/ctrl/facemgr/src/loop_dispatcher.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file loop_dispatcher.c
+ * \brief Implementation of facemgr main loop using Apple Dispatcher framework
+ */
+
+#ifndef __APPLE__
+#error "This implementation only supports Apple platforms"
+#endif /* __APPLE__ */
+
+#ifdef WITH_THREAD
+#error "Multithreaded implementation is not (yet) supported on Apple platforms"
+#endif /* WITH_THREAD */
+
+#include <stdlib.h>
+
+#include <Dispatch/Dispatch.h>
+
+#include <hicn/facemgr/loop.h>
+#include <hicn/util/log.h>
+
+struct loop_s {
+};
+
+loop_t *
+loop_create()
+{
+ /* Nothing to do */
+ return NULL;
+}
+
+void
+loop_free(loop_t * loop)
+{
+ /* Nothing to do */
+}
+
+void
+loop_dispatch(loop_t * loop)
+{
+ dispatch_main();
+}
+
+void
+loop_undispatch(loop_t * loop)
+{
+ /* Nothing to do */
+}
+
+void
+loop_break(loop_t * loop)
+{
+ exit(0);
+}
+
+int
+loop_callback(loop_t * loop, facemgr_cb_type_t type, void * data)
+{
+ INFO("loop_callback not (yet) implemented");
+ return 0;
+}
diff --git a/ctrl/facemgr/src/loop_libevent.c b/ctrl/facemgr/src/loop_libevent.c
new file mode 100644
index 000000000..4042c717a
--- /dev/null
+++ b/ctrl/facemgr/src/loop_libevent.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file loop_libevent.c
+ * \brief Implementation of facemgr main loop using libevent
+ */
+
+#ifndef __linux__
+#error "Only linux is supported"
+#endif /* __linux__ */
+
+#include <assert.h>
+#include <event2/event.h>
+#include <event2/thread.h>
+#include <fcntl.h> // fcntl
+#ifdef WITH_THREAD
+#include <pthread.h>
+#endif /* WITH_THREAD */
+#include <stdlib.h>
+#include <sys/timerfd.h>
+#include <unistd.h> // fcntl
+
+#include <hicn/facemgr/api.h>
+#include <hicn/util/log.h>
+
+#include <hicn/facemgr/loop.h>
+#include "util/map.h"
+
+/**
+ * \brief Holds all callback parameters
+ */
+typedef struct {
+ void * owner;
+ fd_callback_t callback;
+ void * data;
+} cb_wrapper_args_t;
+
+TYPEDEF_MAP_H(event_map, int, struct event *);
+TYPEDEF_MAP(event_map, int, struct event *, int_cmp, int_snprintf, generic_snprintf);
+
+/* Map that associates timer fds with their associated cb_wrapper_args_t */
+TYPEDEF_MAP_H(timer_fd_map, int, cb_wrapper_args_t *);
+TYPEDEF_MAP(timer_fd_map, int, cb_wrapper_args_t *, int_cmp, int_snprintf, generic_snprintf);
+
+struct loop_s {
+ struct event_base * event_base;
+ event_map_t * event_map;
+ timer_fd_map_t * timer_fd_map;
+#ifdef WITH_THREAD
+ pthread_t thread;
+#endif /* WITH_THREAD */
+};
+
+/* Forward declarations */
+int _loop_unregister_fd(loop_t * loop, int fd);
+int _loop_unregister_timer(loop_t * loop, int fd);
+
+loop_t *
+loop_create()
+{
+ loop_t * loop = malloc(sizeof(loop_t));
+ if (!loop) {
+ ERROR("[loop_create] Failed to allocate memory");
+ goto ERR_MALLOC;
+ }
+
+#ifdef WITH_THREAD
+ evthread_use_pthreads();
+#endif /* WITH_THREAD */
+
+ loop->event_base = event_base_new();
+ if (!loop)
+ goto ERR_EVENT;
+
+ loop->event_map = event_map_create();
+ if (!loop->event_map) {
+ ERROR("[loop_create] Failed to create event_map");
+ goto ERR_EVENT_MAP;
+ }
+
+ loop->timer_fd_map = timer_fd_map_create();
+ if (!loop->timer_fd_map) {
+ ERROR("[loop_create] Failed to create timer_fd_map");
+ goto ERR_TIMER_FD_MAP;
+ }
+
+ event_set_log_callback(NULL);
+
+ return loop;
+
+ timer_fd_map_free(loop->timer_fd_map);
+ERR_TIMER_FD_MAP:
+ event_map_free(loop->event_map);
+ERR_EVENT_MAP:
+ event_base_free(loop->event_base);
+ERR_EVENT:
+ free(loop);
+ERR_MALLOC:
+ return NULL;
+}
+
+void
+loop_free(loop_t * loop)
+{
+ /*
+ * Release all timer cb_wrapper_args_t
+ *
+ * We need to stop all timers, this should release associated fd events at
+ * the same time... for that reason, this code has to be called before
+ * releasing events
+ */
+
+ int * timer_fd_map_array;
+ int n = timer_fd_map_get_key_array(loop->timer_fd_map, &timer_fd_map_array);
+ if (n < 0) {
+ ERROR("[loop_free] Could not get event map array");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ int fd = timer_fd_map_array[i];
+ if (_loop_unregister_timer(loop, fd) < 0) {
+ ERROR("[loop_free] Could not unregister timer");
+ }
+ }
+ free(timer_fd_map_array);
+ }
+ timer_fd_map_free(loop->timer_fd_map);
+
+ /* Release all events */
+
+ int * event_map_array;
+ n = event_map_get_key_array(loop->event_map, &event_map_array);
+ if (n < 0) {
+ ERROR("[loop_free] Could not get event map array");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ int fd = event_map_array[i];
+ if (_loop_unregister_fd(loop, fd) < 0) {
+ ERROR("[loop_free] Could not unregister fd");
+ }
+ }
+ free(event_map_array);
+ }
+ event_map_free(loop->event_map);
+
+ event_base_free(loop->event_base);
+
+ free(loop);
+}
+
+void
+loop_dispatch(loop_t * loop)
+{
+#ifdef WITH_THREAD
+ if (pthread_create(loop->thread, NULL, start_dispatch, loop)) {
+ fprintf(stderr, "Error creating thread\n");
+ return EXIT_FAILURE;
+ }
+#else
+ event_base_dispatch(loop->event_base);
+#endif /* WITH_THREAD */
+}
+
+void
+loop_undispatch(loop_t * loop)
+{
+#ifdef WITH_THREAD
+ DEBUG("Waiting for loop to terminate...");
+ if(pthread_join(loop->thread, NULL)) {
+ fprintf(stderr, "Error joining thread\n");
+ return EXIT_FAILURE;
+ }
+ DEBUG("Loop terminated !");
+#endif /* WITH_THREAD */
+}
+
+void
+loop_break(loop_t * loop)
+{
+ event_base_loopbreak(loop->event_base);
+}
+
+void cb_wrapper(evutil_socket_t fd, short what, void * arg) {
+ cb_wrapper_args_t * cb_wrapper_args = arg;
+ cb_wrapper_args->callback(cb_wrapper_args->owner, fd, cb_wrapper_args->data);
+}
+
+/**
+ * \brief Registers a new file descriptor to the event loop
+ * \param [in] fd - File descriptor to register
+ * \param [in] callback_owner - Pointer to the owner of the callack (first
+ * parameter of callback function)
+ * \param [in] callback - Callback function
+ * \param [in] callback_data - User data to pass alongside callback invocation
+ * \return 0 in case of success, -1 otherwise
+ */
+int
+_loop_register_fd(loop_t * loop, int fd, void * callback_owner,
+ fd_callback_t callback, void * callback_data)
+{
+ /* This will be freed with the event */
+ cb_wrapper_args_t * cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t));
+ *cb_wrapper_args = (cb_wrapper_args_t) {
+ .owner = callback_owner,
+ .callback = callback,
+ .data = callback_data,
+ };
+
+ evutil_make_socket_nonblocking(fd);
+ struct event * event = event_new(loop->event_base, 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;
+
+ if (event_map_add(loop->event_map, fd, event) < 0)
+ goto ERR_EVENT_MAP;
+
+ return 0;
+
+ERR_EVENT_MAP:
+ERR_EVENT_ADD:
+ event_free(event);
+ERR_EVENT_NEW:
+ return -1;
+}
+
+/**
+ * \brief Unregisters a file descriptor from the event loop
+ * \param [in] fd - File descriptor to unregister
+ * \return 0 in case of success, -1 otherwise
+ */
+int
+_loop_unregister_fd(loop_t * loop, int fd)
+{
+ struct event * event = NULL;
+
+ if (event_map_remove(loop->event_map, fd, &event) < 0) {
+ ERROR("[loop_unregister_fd] Error removing event associated to fd");
+ return -1;
+ }
+
+ assert(event);
+
+ cb_wrapper_args_t * cb_wrapper_args = event_get_callback_arg(event);
+ free(cb_wrapper_args);
+
+ event_del(event);
+ event_free(event);
+
+ return 0;
+}
+
+int
+loop_timer_callback(loop_t * loop, int fd, void * data)
+{
+ char buf[1024]; /* size is not important */
+ cb_wrapper_args_t * cb_wrapper_args = data;
+ while (read(fd, &buf, sizeof(buf)) > 0)
+ ;
+
+ int rc = cb_wrapper_args->callback(cb_wrapper_args->owner, fd,
+ cb_wrapper_args->data);
+
+ return rc;
+}
+
+int
+_loop_register_timer(loop_t * loop, timer_callback_data_t * timer_callback_data)
+{
+ int fd = timerfd_create(CLOCK_MONOTONIC, 0);
+ if (fd == -1) {
+ perror("timerfd_create");
+ return -1;
+ }
+
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ perror("fcntl");
+ return -1;
+ }
+
+ struct itimerspec ts = {
+ .it_interval = {
+ .tv_sec = 1, //timer_callback_data->delay_ms / 1000,
+ .tv_nsec = (timer_callback_data->delay_ms % 1000) * 1000000,
+ },
+ .it_value = {
+ .tv_sec = 1, //timer_callback_data->delay_ms / 1000,
+ .tv_nsec = (timer_callback_data->delay_ms % 1000) * 1000000,
+ }
+ };
+
+ if (timerfd_settime(fd, 0, &ts, NULL) == -1) {
+ perror("timerfd_settime");
+ return -1;
+ }
+
+ /* This should be freed together with the timer release */
+ cb_wrapper_args_t * cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t));
+ *cb_wrapper_args = (cb_wrapper_args_t) {
+ .owner = timer_callback_data->owner,
+ .callback = timer_callback_data->callback,
+ .data = timer_callback_data->data,
+ };
+
+ if (timer_fd_map_add(loop->timer_fd_map, fd, cb_wrapper_args) < 0) {
+ ERROR("[loop_callback] Could not add cb_wrapper to timer map");
+ return -1;
+ }
+
+ if (_loop_register_fd(loop, fd, loop,
+ (fd_callback_t) loop_timer_callback, cb_wrapper_args) < 0) {
+ ERROR("[loop_callback] Error registering fd to event loop");
+ return -1;
+ }
+
+ return fd;
+}
+
+int
+_loop_unregister_timer(loop_t * loop, int fd)
+{
+ struct itimerspec ts = {
+ .it_interval = {
+ .tv_sec = 0,
+ .tv_nsec = 0,
+ },
+ .it_value = { /* This value disables the timer */
+ .tv_sec = 0,
+ .tv_nsec = 0,
+ }
+ };
+ ts.it_value.tv_sec = 0;
+
+ if (timerfd_settime(fd, 0, &ts, NULL) == -1) {
+ perror("timerfd_settime");
+ return -1;
+ }
+
+ cb_wrapper_args_t * cb_wrapper_args;
+ if (timer_fd_map_remove(loop->timer_fd_map, fd, &cb_wrapper_args) < 0) {
+ ERROR("[loop_callback] Could not remove cb_wrapper from timer map");
+ return -1;
+ }
+ assert(cb_wrapper_args);
+ free(cb_wrapper_args);
+
+ if (_loop_unregister_fd(loop, fd) < 0) {
+ ERROR("[loop_callback] Error unregistering fd from event loop");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+loop_callback(loop_t * loop, facemgr_cb_type_t type, void * data)
+{
+ switch(type) {
+ case FACEMGR_CB_TYPE_REGISTER_FD:
+ {
+ fd_callback_data_t * fd_callback_data = (fd_callback_data_t *)data;
+ if (_loop_register_fd(loop, fd_callback_data->fd,
+ fd_callback_data->owner,
+ fd_callback_data->callback,
+ fd_callback_data->data) < 0) {
+
+ ERROR("[loop_callback] Error registering fd to event loop");
+ return -1;
+ }
+ break;
+ }
+
+ case FACEMGR_CB_TYPE_UNREGISTER_FD:
+ {
+ int fd = *(int*)data;
+ /* We need a map to associate fd and events */
+ if (_loop_unregister_fd(loop, fd) < 0) {
+ ERROR("[loop_callback] Error registering fd to event loop");
+ return -1;
+ }
+ break;
+ }
+
+ case FACEMGR_CB_TYPE_REGISTER_TIMER:
+ {
+ timer_callback_data_t * timer_callback_data = (timer_callback_data_t *)data;
+
+ int fd = _loop_register_timer(loop, timer_callback_data);
+ if (fd < 0) {
+ ERROR("[loop_callback] Error registering timer to event loop");
+ return -1;
+ }
+ return fd;
+
+ }
+
+ case FACEMGR_CB_TYPE_UNREGISTER_TIMER:
+ {
+ int fd = *(int*)data;
+
+ if (_loop_unregister_timer(loop, fd) < 0) {
+ ERROR("[loop_callback] Error unregistering timer from event loop");
+ return -1;
+ }
+ return 0;
+
+ }
+ }
+ return 0;
+}
+
diff --git a/ctrl/facemgr/src/main.c b/ctrl/facemgr/src/main.c
index 307d05236..be5ff3c68 100644
--- a/ctrl/facemgr/src/main.c
+++ b/ctrl/facemgr/src/main.c
@@ -18,33 +18,12 @@
* \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>
-#include <unistd.h> // faccess
-
-#include <libconfig.h>
-
-#ifdef __APPLE__
-#include <Dispatch/Dispatch.h>
-#else
-#include <event2/event.h>
-#endif
#include <hicn/facemgr.h>
#include <hicn/policy.h>
@@ -53,28 +32,17 @@
#include <hicn/util/log.h>
#include <hicn/facemgr/cfg.h>
+#include <hicn/facemgr/loop.h>
-#define FACEMGR_TIMEOUT 3
+#include "cfg_file.h"
+#include "util/map.h"
-static struct event_base * loop;
+#define FACEMGR_TIMEOUT 3
-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...
+static struct event_base * loop;
#endif
-#ifdef __linux__
- event_base_loopbreak(loop);
-#endif /* __linux__ */
- loop = NULL;
-}
+static loop_t * loop = NULL;
static struct option long_options[] =
{
@@ -86,13 +54,6 @@ typedef struct {
char * cfgfile;
} facemgr_options_t;
-static const char * DEFAULT_CFGFILES[] = {
- "/etc/facemgr.conf",
- "~/facemgr.conf",
-};
-
-#define ARRAYSIZE(x) (sizeof(x)/sizeof(*x))
-
void usage(const char * progname)
{
printf("%s: Face manager daemon\n", progname);
@@ -104,16 +65,11 @@ void usage(const char * progname)
printf("\n");
}
-int probe_cfgfile(char * f)
-{
- for (unsigned i = 0; i < ARRAYSIZE(DEFAULT_CFGFILES); i++) {
- if (access(DEFAULT_CFGFILES[i], F_OK ) != -1) {
- if (!realpath(DEFAULT_CFGFILES[i], f))
- continue;
- return 0;
- }
+void facemgr_signal_handler(int signal) {
+ fprintf(stderr, "Received ^C... quitting !\n");
+ if (loop) {
+ loop_break(loop);
}
- return -1;
}
int parse_cmdline(int argc, char ** argv, facemgr_options_t * opts)
@@ -122,7 +78,7 @@ int parse_cmdline(int argc, char ** argv, facemgr_options_t * opts)
while ((c = getopt_long(argc, argv, "c:", long_options, NULL)) != -1) {
switch(c) {
case 'c':
- opts->cfgfile = strdup(optarg);
+ opts->cfgfile = optarg;
break;
case ':':
case '?':
@@ -135,596 +91,14 @@ int parse_cmdline(int argc, char ** argv, facemgr_options_t * opts)
return 0;
}
-int
-parse_config_global(facemgr_cfg_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;
- }
-
- int rc = facemgr_cfg_set_face_type(cfg, &face_type);
- if (rc < 0)
- goto ERR;
- }
-
- /* - disable_discovery */
-
- 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;
- }
-
- /* - 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 = IP_ADDRESS_EMPTY;
- ip_address_t remote_addr = IP_ADDRESS_EMPTY;
- 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)) {
- if (ip_address_pton(local_addr_str, &local_addr) < 0) {
- ERROR("Error parsing v4 local addr");
- goto ERR;
- }
- 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)) {
- if (ip_address_pton(remote_addr_str, &remote_addr) < 0) {
- ERROR("Error parsing v4 remote addr");
- goto ERR;
- }
- 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;
- }
-
- /* 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 = IP_ADDRESS_EMPTY;
- ip_address_t remote_addr = IP_ADDRESS_EMPTY;
- 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)) {
- if (ip_address_pton(local_addr_str, &local_addr) < 0) {
- ERROR("Error parsing v6 local addr");
- goto ERR;
- }
- 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)) {
- if (ip_address_pton(remote_addr_str, &remote_addr) < 0) {
- ERROR("Error parsing v6 remote addr");
- goto ERR;
- }
- 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;
- }
-
- } /* 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;
- }
-
- 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;
- }
- }
-
- 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;
- }
-
- /* - disable_discovery */
-
- 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;
- }
-
- /* - disable_ipv4 */
-
- 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
- }
-
- /* - 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);
- if (tag == POLICY_TAG_N)
- goto ERR;
- policy_tags_add(&tags, tag);
- }
-
- 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);
- 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 = IP_ADDRESS_EMPTY;
- ip_address_t remote_addr = IP_ADDRESS_EMPTY;
- 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)) {
- if (ip_address_pton(local_addr_str, &local_addr) < 0) {
- ERROR("Error parsing v4 local addr");
- goto ERR;
- }
- 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)) {
- if (ip_address_pton(remote_addr_str, &remote_addr) < 0) {
- ERROR("Error parsing v4 remote addr");
- goto ERR;
- }
- 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 = IP_ADDRESS_EMPTY;
- ip_address_t remote_addr = IP_ADDRESS_EMPTY;
- 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)) {
- if (ip_address_pton(local_addr_str, &local_addr) < 0) {
- ERROR("Error parsing v6 local addr");
- goto ERR;
- }
- 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)) {
- if (ip_address_pton(remote_addr_str, &remote_addr) < 0) {
- ERROR("Error parsing v6 remote addr");
- goto ERR;
- }
- 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;
-}
-
-/* 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:
- 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_PARSE:
- fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfgfile),
- config_error_line(&cfgfile), config_error_text(&cfgfile));
- config_destroy(&cfgfile);
- return -1;
-}
-
#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);
-}
-
-struct event *
-loop_register_fd(struct event_base * loop, int fd, void * cb, void * cb_args)
-{
- // 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;
@@ -788,19 +162,9 @@ NO_CFGFILE:
MAIN_LOOP:
/* Main loop */
-
-
-#ifdef WITH_THREAD
- evthread_use_pthreads();
-#endif /* WITH_THREAD */
-
+ loop = loop_create();
#ifdef __linux__
- /* Event loop */
- loop = event_base_new();
- if (!loop)
- goto ERR_EVENT;
-
- facemgr_set_event_loop_handler(facemgr, loop, loop_register_fd, loop_unregister_event);
+ facemgr_set_callback(facemgr, loop, (void*)loop_callback);
#endif /* __linux__ */
#ifdef __ANDROID__
@@ -812,24 +176,7 @@ MAIN_LOOP:
if (facemgr_bootstrap(facemgr) < 0 )
goto ERR_BOOTSTRAP;
-#ifdef __linux__
- event_set_log_callback(NULL);
-
-#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 */
- dispatch_main();
-#endif /* __APPLE__ */
+ loop_dispatch(loop);
#ifdef __linux__
#ifdef WITH_THREAD
@@ -842,34 +189,27 @@ MAIN_LOOP:
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__ */
+ loop_undispatch(loop);
facemgr_free(facemgr);
+ if (cfg)
+ facemgr_cfg_free(cfg);
+
+ loop_free(loop);
+
return EXIT_SUCCESS;
ERR_BOOTSTRAP:
-#ifdef __linux__
-ERR_EVENT:
-#endif /* __linux__ */
facemgr_free(facemgr);
ERR_FACEMGR_CONFIG:
+ERR_FACEMGR:
+ERR_PARSE:
if (cfg)
facemgr_cfg_free(cfg);
-ERR_FACEMGR:
ERR_FACEMGR_CFG:
-ERR_PARSE:
ERR_PATH:
ERR_CMDLINE:
return EXIT_FAILURE;
diff --git a/ctrl/facemgr/src/util/map.h b/ctrl/facemgr/src/util/map.h
index b6773f209..b113954a6 100644
--- a/ctrl/facemgr/src/util/map.h
+++ b/ctrl/facemgr/src/util/map.h
@@ -18,7 +18,6 @@
#include <stdlib.h>
-#include "../common.h"
#include "set.h"
#define ERR_MAP_EXISTS -2
@@ -112,7 +111,30 @@ NAME ## _finalize(NAME ## _t * map)
return NAME ## _pair_set_finalize(&map->pair_set); \
} \
\
-AUTOGENERATE_CREATE_FREE(NAME) \
+NAME ## _t * \
+NAME ## _create() \
+{ \
+ NAME ## _t * map = malloc(sizeof(NAME ## _t)); \
+ if (!map) \
+ goto ERR_MALLOC; \
+ \
+ if (NAME ## _initialize(map) < 0) \
+ goto ERR_INITIALIZE; \
+ \
+ return map; \
+ \
+ERR_INITIALIZE: \
+ free(map); \
+ERR_MALLOC: \
+ return NULL; \
+} \
+ \
+void \
+NAME ## _free(NAME ## _t * map) \
+{ \
+ NAME ## _finalize(map); \
+ free(map); \
+} \
\
int \
NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value) \
@@ -122,22 +144,22 @@ NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value)
\
NAME ## _pair_t * pair = NAME ## _pair_create(key, value); \
if (!pair) \
- return -1; \
+ return -1; \
\
rc = NAME ## _pair_set_get(&map->pair_set, pair, &found); \
- if (rc < 0) \
- return -1; \
+ if (rc < 0) \
+ return -1; \
if (found) { \
NAME ## _pair_free(pair); \
return ERR_MAP_EXISTS; \
} \
\
rc = NAME ## _pair_set_add(&map->pair_set, pair); \
- if (rc < 0) { \
+ if (rc < 0) { \
NAME ## _pair_free(pair); \
- return -1; \
+ return -1; \
} \
- return 0; \
+ return 0; \
} \
\
int \
@@ -146,12 +168,12 @@ NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value)
NAME ## _pair_t * found = NULL; \
NAME ## _pair_t search = { .key = key }; \
int rc = NAME ## _pair_set_remove(&map->pair_set, &search, &found); \
- if (rc < 0) \
+ if (rc < 0) \
return ERR_MAP_NOT_FOUND; \
if (value) \
*value = found->value; \
NAME ## _pair_free(found); \
- return 0; \
+ return 0; \
} \
\
int \
@@ -159,11 +181,11 @@ NAME ## _get(NAME ## _t * map, KEY_T key, VAL_T * value)
{ \
NAME ## _pair_t * found = NULL, search = { .key = key }; \
int rc = NAME ## _pair_set_get(&map->pair_set, &search, &found); \
- if (rc < 0) \
- return -1; \
+ if (rc < 0) \
+ return -1; \
if (found) \
*value = found->value; \
- return 0; \
+ return 0; \
} \
\
void \
@@ -176,18 +198,18 @@ NAME ## _get_key_array(NAME ## _t * map, KEY_T **array) {
NAME ## _pair_t ** pair_array; \
int n = NAME ## _pair_set_get_array(&map->pair_set, &pair_array); \
if (n < 0) \
- return -1; \
+ return -1; \
/* Allocate result array */ \
- array = malloc(n * sizeof(KEY_T)); \
+ *array = malloc(n * sizeof(KEY_T)); \
if (!array) { \
free(pair_array); \
- return -1; \
+ return -1; \
} \
/* Copy keys */ \
for (int i = 0; i < n; i++) \
- array[i] = &pair_array[i]->key; \
+ (*array)[i] = pair_array[i]->key; \
free(pair_array); \
- return 0; \
+ return 0; \
} \
\
int \
@@ -195,18 +217,18 @@ NAME ## _get_value_array(NAME ## _t * map, VAL_T **array) {
NAME ## _pair_t ** pair_array; \
int n = NAME ## _pair_set_get_array(&map->pair_set, &pair_array); \
if (n < 0) \
- return -1; \
+ return -1; \
/* Allocate result array */ \
- array = malloc(n * sizeof(VAL_T)); \
+ *array = malloc(n * sizeof(VAL_T)); \
if (!array) { \
free(pair_array); \
- return -1; \
+ return -1; \
} \
/* Copy values */ \
for (int i = 0; i < n; i++) \
- array[i] = &pair_array[i]->value; \
+ (*array)[i] = pair_array[i]->value; \
free(pair_array); \
- return 0; \
+ return 0; \
}
#endif /* UTIL_MAP_H */
diff --git a/ctrl/facemgr/src/util/set.h b/ctrl/facemgr/src/util/set.h
index 61df209ab..0dad17423 100644
--- a/ctrl/facemgr/src/util/set.h
+++ b/ctrl/facemgr/src/util/set.h
@@ -24,7 +24,6 @@
//#else
#define thread_local _Thread_local
//#endif /* ! __ANDROID__ */
-#include "../common.h"
#define ERR_SET_EXISTS -2
#define ERR_SET_NOT_FOUND -3
@@ -34,6 +33,13 @@
static inline
int
+int_cmp(const int x, const int y)
+{
+ return x - y;
+}
+
+static inline
+int
int_snprintf(char * buf, size_t size, int value) {
return snprintf(buf, size, "%d", value);
}
@@ -50,6 +56,8 @@ generic_snprintf(char * buf, size_t size, const void * value) {
return snprintf(buf, BUFSIZE, "%p", value);
}
+typedef int(*cmp_t)(const void * x, const void * y);
+
#define TYPEDEF_SET_H(NAME, T) \
\
typedef struct { \
@@ -87,8 +95,33 @@ NAME ## _initialize(NAME ## _t * set) \
return 0; \
} \
\
-NO_FINALIZE(NAME); \
-AUTOGENERATE_CREATE_FREE(NAME); \
+int \
+NAME ## _finalize(NAME ## _t * set) { return 0; } \
+ \
+NAME ## _t * \
+NAME ## _create() \
+{ \
+ NAME ## _t * set = malloc(sizeof(NAME ## _t)); \
+ if (!set) \
+ goto ERR_MALLOC; \
+ \
+ if (NAME ## _initialize(set) < 0) \
+ goto ERR_INITIALIZE; \
+ \
+ return set; \
+ \
+ERR_INITIALIZE: \
+ free(set); \
+ERR_MALLOC: \
+ return NULL; \
+} \
+ \
+void \
+NAME ## _free(NAME ## _t * set) \
+{ \
+ NAME ## _finalize(set); \
+ free(set); \
+} \
\
int \
NAME ## _add(NAME ## _t * set, const T element) \