aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmake/Modules/Packager.cmake6
-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.c290
-rw-r--r--ctrl/facemgr/src/cfg.c53
-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.c54
-rw-r--r--ctrl/facemgr/src/facelet.h28
-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.c229
-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.c676
-rw-r--r--ctrl/facemgr/src/util/map.h68
-rw-r--r--ctrl/facemgr/src/util/set.h39
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/api.h118
-rwxr-xr-xctrl/libhicnctrl/includes/hicn/ctrl/commands.h2
-rw-r--r--ctrl/libhicnctrl/src/CMakeLists.txt1
-rw-r--r--ctrl/libhicnctrl/src/api.c1003
-rw-r--r--ctrl/libhicnctrl/src/cli.c457
-rw-r--r--ctrl/libhicnctrl/src/util/map.h234
-rw-r--r--ctrl/libhicnctrl/src/util/set.h213
-rw-r--r--hicn-light/cmake/Modules/Packaging.cmake17
-rw-r--r--hicn-light/config/hicn-light.service4
-rwxr-xr-xhicn-light/config/post3
-rwxr-xr-xhicn-light/config/postinst3
-rwxr-xr-xhicn-light/config/prerm3
-rwxr-xr-xhicn-light/config/preun3
-rw-r--r--hicn-light/src/hicn/config/configuration.c8
-rw-r--r--hicn-light/src/hicn/config/configurationListeners.c10
-rw-r--r--hicn-light/src/hicn/config/controlAddListener.c2
-rw-r--r--hicn-light/src/hicn/config/controlListListeners.c12
-rw-r--r--hicn-light/src/hicn/config/controlRemoveListener.c2
-rw-r--r--hicn-light/src/hicn/utils/commands.h34
-rw-r--r--hicn-plugin/README.md3
-rw-r--r--lib/src/util/ip_address.c8
50 files changed, 3811 insertions, 1419 deletions
diff --git a/cmake/Modules/Packager.cmake b/cmake/Modules/Packager.cmake
index 6f77fd3a8..e5e3fa731 100644
--- a/cmake/Modules/Packager.cmake
+++ b/cmake/Modules/Packager.cmake
@@ -136,7 +136,7 @@ macro(make_packages)
set(CPACK_${type}_${uc}_PACKAGE_NAME "${lc}")
set(CPACK_COMPONENT_${uc}_DESCRIPTION "${${lc}_DESCRIPTION}")
- if (NOT ${${lc}_DEB_PACKAGE_CONTROL_EXTRA} STREQUAL "")
+ if (${lc}_DEB_PACKAGE_CONTROL_EXTRA)
set(CPACK_DEBIAN_${uc}_PACKAGE_CONTROL_EXTRA "${${lc}_DEB_PACKAGE_CONTROL_EXTRA}")
endif()
endforeach()
@@ -183,6 +183,10 @@ macro(make_packages)
if (NOT ${${lc}_RPM_POST_UNINSTALL_SCRIPT_FILE} STREQUAL "")
set(CPACK_RPM_${uc}_POST_UNINSTALL_SCRIPT_FILE "${${lc}_RPM_POST_UNINSTALL_SCRIPT_FILE}")
endif()
+
+ if (NOT ${${lc}_RPM_PRE_UNINSTALL_SCRIPT_FILE} STREQUAL "")
+ set(CPACK_RPM_${uc}_PRE_UNINSTALL_SCRIPT_FILE "${${lc}_RPM_PRE_UNINSTALL_SCRIPT_FILE}")
+ endif()
endforeach()
endif()
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 88595a9bc..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;
@@ -833,18 +843,13 @@ facemgr_process_create(facemgr_t * facemgr, facelet_t * facelet)
*/
int rc;
- if (facelet_cache_add(&facemgr->facelet_cache, facelet) < 0) {
- ERROR("[facemgr_process_create] Error adding facelet to cache");
- return -1;
- }
- DEBUG("Facelet added to cache");
-
/*
* If the facelet does not satisfy filters, we do not lose any information
* but do not take any action to complement the face
*/
rc = facemgr_facelet_satisfy_rules(facemgr, facelet);
if (rc == -3) {
+ facelet_set_status(facelet, FACELET_STATUS_IGNORED);
/* Does not satisfy rules */
return 0;
}
@@ -890,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)) {
@@ -927,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)
@@ -937,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;
}
/**
@@ -965,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)) {
@@ -998,6 +1004,7 @@ facemgr_process_update(facemgr_t * facemgr, facelet_t * facelet)
}
/* Process GET/UDPATE... */
+ int rc;
switch(facelet_get_status(facelet)) {
case FACELET_STATUS_UNDEFINED:
ERROR("[facemgr_process_update] Unexpected facelet status");
@@ -1015,6 +1022,14 @@ facemgr_process_update(facemgr_t * facemgr, facelet_t * facelet)
return -1;
}
}
+
+ rc = facemgr_facelet_satisfy_rules(facemgr, facelet);
+ if (rc == -3) {
+ facelet_set_status(facelet, FACELET_STATUS_IGNORED);
+ /* Does not satisfy rules */
+ return 0;
+ }
+
if (!facelet_validate_face(facelet))
return 0;
@@ -1044,6 +1059,13 @@ 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;
+ }
+
if (!facelet_validate_face(facelet))
return 0;
@@ -1059,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;
@@ -1075,15 +1106,30 @@ facemgr_process_update(facemgr_t * facemgr, facelet_t * facelet)
int
facemgr_process_delete(facemgr_t * facemgr, facelet_t * facelet)
{
+
+ DEBUG("[facemgr_process_delete] Deleting facelet on hicn-light");
if (interface_on_event(facemgr->hl, facelet) < 0)
return -1;
+ /*
+ * It might be tempting to cache old information, but for now we reset the
+ * facelet state that might change (such as IP addresses etc).
+ * netdevice, netdevice_type and admin_state should not be affected.
+ */
+ DEBUG("[facemgr_process_delete] Cleaning cached data");
+ facelet_unset_local_addr(facelet);
+ facelet_unset_local_port(facelet);
+ facelet_unset_remote_addr(facelet);
+ facelet_unset_remote_port(facelet);
+
facelet_set_status(facelet, FACELET_STATUS_DELETED);
- //facelet_set_bj_done(facelet, false);
+
+ facelet_unset_bj_done(facelet);
return 0;
}
+
/**
* \brief Process incoming events from interfaces
*
@@ -1094,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);
@@ -1108,21 +1156,32 @@ 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)) {
case FACELET_EVENT_CREATE:
+
+ if (facelet_cache_add(&facemgr->facelet_cache, facelet_in) < 0) {
+ ERROR("[facemgr_on_event] Error adding facelet to cache");
+ return -1;
+ }
+ //DEBUG("Facelet added to cache");
+
+ remove_facelet = false;
+
if (facemgr_process_create(facemgr, facelet_in) < 0) {
- ERROR("[facemgr_process_cached_facelet] Error processing CREATE event");
+ ERROR("[facemgr_on_event] Error processing CREATE event");
goto ERR;
}
break;
case FACELET_EVENT_GET:
/* Insert new facelet in cached */
- if (facemgr_process_get(facemgr, facelet_in) < 0) {
- ERROR("[facemgr_process_cached_facelet] Error processing GET event");
+ 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;
}
break;
@@ -1159,13 +1218,19 @@ 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:
- // FIXME, this might occur if the facemgr restarts and we try to
- // re-create existing faces
- ERROR("[facemgr_on_event] CREATE event for a face that already exists...");
- ret = -1;
+ // This case will occur when we try to re-create existing faces,
+ // eg. in the situation of a forwarder restarting.
+ // likely this occurs when the interface receives a (potentially new) address
+ if (facelet_merge(facelet, facelet_in) < 0) {
+ ERROR("[facemgr_on_event] Error merging facelets");
+ continue;
+ }
+ if (facemgr_process_create(facemgr, facelet) < 0) {
+ ERROR("[facemgr_on_event] Error processing CREATE event");
+ ret = -1;
+ }
continue;
case FACELET_EVENT_GET: /* should be an INFORM message */
@@ -1176,14 +1241,6 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
continue;
case FACELET_EVENT_UPDATE:
- {
- DEBUG("FACELET_EVENT_UPDATE");
- char buf[128];
- facelet_snprintf(buf, 128, facelet_in);
- DEBUG("MERGE %s", buf);
- facelet_snprintf(buf, 128, facelet);
- DEBUG(" ON %s", buf);
- }
if (facelet_merge(facelet, facelet_in) < 0) {
ERROR("[facemgr_on_event] Error merging facelets");
continue;
@@ -1218,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)
{
@@ -1366,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]);
}
@@ -1406,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 6b04208bb..527da54e7 100644
--- a/ctrl/facemgr/src/cfg.c
+++ b/ctrl/facemgr/src/cfg.c
@@ -112,6 +112,11 @@ facemgr_cfg_override_initialize(facemgr_cfg_override_t * override)
override->is_discovery = false;
override->discovery = false;
+ override->is_ipv4 = false;
+ override->ipv6 = false;
+ override->is_ipv6 = false;
+ override->ipv6 = false;
+
override->overlays.v4 = NULL;
override->overlays.v6 = NULL;
@@ -485,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);
}
@@ -526,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,
@@ -684,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 8a3074d2a..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;
@@ -518,6 +514,11 @@ facelet_set_ ## NAME(facelet_t * facelet, TYPE NAME)
return facelet_set_local_ ## NAME(facelet, NAME); \
} \
\
+int \
+facelet_unset_ ## NAME(facelet_t * facelet) \
+{ \
+ return facelet->NAME ## _status = FACELET_ATTR_STATUS_UNSET; \
+}
#define _(TYPE, NAME) FACELET_ACCESSORS(TYPE, NAME)
foreach_facelet_attr
@@ -747,36 +748,16 @@ 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)
+void
+facelet_set_bj_done(facelet_t * facelet)
{
- assert(facelet);
- DEBUG("num pending=%d\n", facelet->num_pending);
- return (facelet->num_pending > 0);
+ facelet->bj_done = true;
}
void
-facelet_set_bj_done(facelet_t * facelet)
+facelet_unset_bj_done(facelet_t * facelet)
{
- facelet->bj_done = true;
+ facelet->bj_done = false;
}
bool
@@ -810,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;
@@ -826,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;
@@ -988,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 fecee8641..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 {
@@ -152,12 +154,12 @@ bool facelet_match(const facelet_t * facelet, const facelet_t * facelet_match);
*/
bool facelet_has_key(const facelet_t * facelet);
-
#define FACELET_ACCESSORS_H(TYPE, NAME) \
bool facelet_has_ ## NAME(const facelet_t * facelet); \
facelet_attr_status_t facelet_get_ ## NAME ## _status(const facelet_t * facelet);\
int facelet_get_ ## NAME(const facelet_t * facelet, TYPE * NAME); \
-int facelet_set_ ## NAME(facelet_t * facelet, TYPE NAME);
+int facelet_set_ ## NAME(facelet_t * facelet, TYPE NAME); \
+int facelet_unset_ ## NAME(facelet_t * facelet);
#define _(TYPE, NAME) FACELET_ACCESSORS_H(TYPE, NAME)
foreach_facelet_attr
@@ -170,11 +172,8 @@ 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);
void facelet_set_au_done(facelet_t * facelet);
bool facelet_is_au_done(const facelet_t * facelet);
@@ -182,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 e42c6c6ae..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;
@@ -205,7 +328,6 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
ERROR("Failed to delete face\n");
goto ERR;
}
- INFO("Deleted face id=%d\n", hc_face.id);
break;
case FACELET_EVENT_UPDATE:
@@ -213,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");
@@ -222,10 +346,9 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
ERROR("Face to update has not been found");
goto ERR;
}
- char conn_id_or_name[NAME_LEN];
- snprintf(conn_id_or_name, NAME_LEN, "%d", face_found->id);
+ 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) {
@@ -234,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;
@@ -248,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 2a336db8f..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,568 +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, remote_addr;
- ip_address_t * local_addr_p = NULL;
- ip_address_t * remote_addr_p = NULL;
- int local_port = 0;
- int remote_port = 0;
-
- if (config_setting_lookup_string(overlay_v4, "local_addr", &local_addr_str)) {
- ip_address_pton(local_addr_str, &local_addr);
- local_addr_p = &local_addr;
- }
-
- if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) {
- if (!IS_VALID_PORT(local_port))
- goto ERR;
- }
-
- if (config_setting_lookup_string(overlay_v4, "remote_addr", &remote_addr_str)) {
- ip_address_pton(remote_addr_str, &remote_addr);
- remote_addr_p = &remote_addr;
- }
-
- if (config_setting_lookup_int(overlay_v4, "remote_port", &remote_port)) {
- if (!IS_VALID_PORT(remote_port))
- goto ERR;
- }
- int rc = facemgr_cfg_set_overlay(cfg, AF_INET,
- local_addr_p, local_port,
- remote_addr_p, remote_port);
- if (rc < 0)
- goto ERR;
- }
-
- /* ipv6 */
- config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6");
- if (overlay_v6) {
- const char * local_addr_str, * remote_addr_str;
- ip_address_t local_addr, remote_addr;
- ip_address_t * local_addr_p = NULL;
- ip_address_t * remote_addr_p = NULL;
- int local_port = 0;
- int remote_port = 0;
-
- if (config_setting_lookup_string(overlay_v6, "local_addr", &local_addr_str)) {
- ip_address_pton(local_addr_str, &local_addr);
- local_addr_p = &local_addr;
- }
-
- if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) {
- if (!IS_VALID_PORT(local_port))
- goto ERR;
- }
-
- if (config_setting_lookup_string(overlay_v6, "remote_addr", &remote_addr_str)) {
- ip_address_pton(remote_addr_str, &remote_addr);
- remote_addr_p = &remote_addr;
- }
-
- if (config_setting_lookup_int(overlay_v6, "remote_port", &remote_port)) {
- if (!IS_VALID_PORT(remote_port))
- goto ERR;
- }
- int rc = facemgr_cfg_set_overlay(cfg, AF_INET6,
- local_addr_p, local_port,
- remote_addr_p, remote_port);
- if (rc < 0)
- goto ERR;
- }
-
- } /* 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, remote_addr;
- ip_address_t * local_addr_p = NULL;
- ip_address_t * remote_addr_p = NULL;
- int local_port = 0;
- int remote_port = 0;
-
- if (config_setting_lookup_string(overlay_v4, "local_addr", &local_addr_str)) {
- ip_address_pton(local_addr_str, &local_addr);
- local_addr_p = &local_addr;
- }
-
- if (config_setting_lookup_int(overlay_v4, "local_port", &local_port)) {
- if (!IS_VALID_PORT(local_port))
- goto ERR;
- }
-
- if (config_setting_lookup_string(overlay_v4, "remote_addr", &remote_addr_str)) {
- ip_address_pton(remote_addr_str, &remote_addr);
- remote_addr_p = &remote_addr;
- }
-
- if (config_setting_lookup_int(overlay_v4, "remote_port", &remote_port)) {
- if (!IS_VALID_PORT(remote_port))
- goto ERR;
- }
- int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET,
- local_addr_p, local_port,
- remote_addr_p, remote_port);
- if (rc < 0)
- goto ERR;
- }
-
- /* ipv6 */
- config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6");
- if (overlay_v6) {
- const char * local_addr_str, * remote_addr_str;
- ip_address_t local_addr, remote_addr;
- ip_address_t * local_addr_p = NULL;
- ip_address_t * remote_addr_p = NULL;
- int local_port = 0;
- int remote_port = 0;
-
- if (config_setting_lookup_string(overlay_v6, "local_addr", &local_addr_str)) {
- ip_address_pton(local_addr_str, &local_addr);
- local_addr_p = &local_addr;
- }
-
- if (config_setting_lookup_int(overlay_v6, "local_port", &local_port)) {
- if (!IS_VALID_PORT(local_port))
- goto ERR;
- }
-
- if (config_setting_lookup_string(overlay_v6, "remote_addr", &remote_addr_str)) {
- ip_address_pton(remote_addr_str, &remote_addr);
- remote_addr_p = &remote_addr;
- }
-
- if (config_setting_lookup_int(overlay_v6, "remote_port", &remote_port)) {
- if (!IS_VALID_PORT(remote_port))
- goto ERR;
- }
- int rc = facemgr_cfg_rule_set_overlay(rule, AF_INET6,
- local_addr_p, local_port,
- remote_addr_p, remote_port);
- if (rc < 0)
- goto ERR;
- }
-
- } /* overlay */
-
- /* Add newly created rule */
-
- rc = facemgr_cfg_add_rule(cfg, rule);
- if (rc < 0)
- goto ERR;
- }
- return 0;
-
-ERR:
- facemgr_cfg_rule_free(rule);
-ERR_RULE:
-ERR_CHECK:
- return -1;
-}
-
-/* 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;
@@ -760,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__
@@ -784,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
@@ -814,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) \
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
index a0ee828b9..62cf98927 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
@@ -43,7 +43,7 @@
* | MAP-Me | | |
* +------------+---------------------+-----------------+---------------------------
* | connection | O O ! O O | O O O | state [-S]
- * | listener | O O ! - O | O O O O |
+ * | listener | O O ! O O | O O O O |
* +------------+---------------------+-----------------+---------------------------
*
* LEGEND: [O] implemented, [!] in progress / TODO, [-] not supported
@@ -73,11 +73,6 @@
#define HICN_DEFAULT_PORT 9695
-#define LIBHICNCTRL_SUCCESS 0
-#define LIBHICNCTRL_FAILURE -1
-#define LIBHICNCTRL_NOT_IMPLEMENTED -99
-#define LIBHICNCTRL_IS_ERROR(x) (x < 0)
-
/* Helper for avoiding warnings about type-punning */
#define UNION_CAST(x, destType) \
(((union {__typeof__(x) a; destType b;})x).b)
@@ -219,11 +214,11 @@ hc_ ## TYPE ## _find(hc_data_t * data, const hc_ ## TYPE ## _t * element, \
foreach_type(hc_ ## TYPE ## _t, x, data) { \
if (hc_ ## TYPE ## _cmp(x, element) >= 0) { \
*found = x; \
- return LIBHICNCTRL_SUCCESS; \
+ return 0; \
} \
}; \
*found = NULL; /* this is optional */ \
- return LIBHICNCTRL_SUCCESS; \
+ return 0; \
}
/******************************************************************************
@@ -236,113 +231,103 @@ hc_ ## TYPE ## _find(hc_data_t * data, const hc_ ## TYPE ## _t * element, \
/**
* \brief Holds the state of an hICN control socket
*/
-typedef struct {
- char * url;
- int fd;
- u32 seq;
-
- /* Partial receive buffer */
- u8 buf[RECV_BUFLEN];
- size_t roff; /**< Read offset */
- size_t woff; /**< Write offset */
-
- /*
- * Because received messages are potentially unbounded in size, we might not
- * guarantee that we can store a full packet before processing it. We must
- * implement a very simple state machine remembering the current parsing
- * status in order to partially process the packet.
- */
- size_t remaining;
- u32 send_id;
- u32 send_seq;
- u32 recv_seq;
-} hc_sock_t;
+typedef struct hc_sock_s hc_sock_t;
/**
* \brief Create an hICN control socket using the specified URL.
* \param [in] url - The URL to connect to.
* \return an hICN control socket
*/
-hc_sock_t *
-hc_sock_create_url(const char * url);
+hc_sock_t * hc_sock_create_url(const char * url);
/**
* \brief Create an hICN control socket using the default connection type.
* \return an hICN control socket
*/
-hc_sock_t *
-hc_sock_create(void);
+hc_sock_t * hc_sock_create(void);
/**
* \brief Frees an hICN control socket
+ * \param [in] s - hICN control socket
*/
-void
-hc_sock_free(hc_sock_t *s);
+void hc_sock_free(hc_sock_t * s);
+
+/**
+ * \brief Returns the next available sequence number to use for requests to the
+ * API.
+ * \param [in] s - hICN control socket
+ */
+int hc_sock_get_next_seq(hc_sock_t * s);
/**
* \brief Sets the socket as non-blocking
+ * \param [in] s - hICN control socket
* \return Error code
*/
-int
-hc_sock_set_nonblocking(hc_sock_t *s);
+int hc_sock_set_nonblocking(hc_sock_t * s);
+
+/**
+ * \brief Return the file descriptor associated to the hICN contorl sock
+ * \param [in] s - hICN control socket
+ * \return The file descriptor (positive value), or a negative integer in case
+ * of error
+ */
+int hc_sock_get_fd(hc_sock_t * s);
/**
* \brief Connect the socket
* \return Error code
*/
int
-hc_sock_connect(hc_sock_t *s);
+hc_sock_connect(hc_sock_t * s);
/**
* \brief Return the offset and size of available buffer space
- * \param [in] sock - hICN control socket
+ * \param [in] s - hICN control socket
* \param [out] buffer - Offset in buffer
* \param [out] size - Remaining size
* \return Error code
*/
-int
-hc_sock_get_available(hc_sock_t * s, u8 ** buffer, size_t * size);
+int hc_sock_get_available(hc_sock_t * s, u8 ** buffer, size_t * size);
/**
* \brief Write/read iexchance on the control socket (internal helper function)
- * \param [in] sock - hICN control socket
+ * \param [in] s - hICN control socket
* \param [in] msg - Message to send
* \param [in] msglen - Length of the message to send
* \return Error code
*/
-int
-hc_sock_send(hc_sock_t * s, hc_msg_t * msg, size_t msglen);
+int hc_sock_send(hc_sock_t * s, hc_msg_t * msg, size_t msglen, int seq);
/**
* \brief Helper for reading socket contents
- * \param [in] sock - hICN control socket
- * \param [in] data - Result data buffer
- * \param [in] parse - Parse function to convert remote types into lib native
- * types, or NULL not to perform any translation.
+ * \param [in] s - hICN control socket
* \return Error code
*/
-int
-hc_sock_recv(hc_sock_t * s, hc_data_t * data);
+int hc_sock_recv(hc_sock_t * s);
/**
* \brief Processing data received by socket
- * \param [in] sock - hICN control socket
- * \param [in] data - Result data buffer
+ * \param [in] s - hICN control socket
* \param [in] parse - Parse function to convert remote types into lib native
* types, or NULL not to perform any translation.
* \return Error code
*/
-int
-hc_sock_process(hc_sock_t * s, hc_data_t * data,
- int (*parse)(const u8 * src, u8 * dst));
+int hc_sock_process(hc_sock_t * s, hc_data_t ** data);
+
+/**
+ * \brief Callback used in async mode when data is available on the socket
+ * \param [in] s - hICN control socket
+ * \return Error code
+ */
+int hc_sock_callback(hc_sock_t * s, hc_data_t ** data);
/**
* \brief Reset the state of the sock (eg. to handle a reconnecton)
- * \param [in] sock - hICN control socket
+ * \param [in] s - hICN control socket
* \return Error code
*/
-int
-hc_sock_reset(hc_sock_t * s);
+int hc_sock_reset(hc_sock_t * s);
/******************************************************************************
* Command-specific structures and functions
@@ -395,9 +380,9 @@ hc_sock_reset(hc_sock_t * s);
#define NULLTERM 1
#endif
-#define NAME_LEN 16 /* NULL-terminated right ? */
+#define SYMBOLIC_NAME_LEN 16 /* NULL-terminated right ? */
#define INTERFACE_LEN 16
-#define MAXSZ_HC_NAME_ NAME_LEN
+#define MAXSZ_HC_NAME_ SYMBOLIC_NAME_LEN
#define MAXSZ_HC_NAME MAXSZ_HC_NAME_ + NULLTERM
#define MAXSZ_HC_ID_ 10 /* Number of digits for MAX_INT */
@@ -460,7 +445,7 @@ typedef int (*HC_PARSE)(const u8 *, u8 *);
// FIXME the listener should not require any port for hICN...
typedef struct {
- char name[NAME_LEN]; /* K.w */ // XXX clarify what used for
+ char name[SYMBOLIC_NAME_LEN]; /* K.w */ // XXX clarify what used for
char interface_name[INTERFACE_LEN]; /* Kr. */
u32 id;
hc_connection_type_t type; /* .rw */
@@ -471,7 +456,7 @@ typedef struct {
int hc_listener_create(hc_sock_t * s, hc_listener_t * listener);
/* listener_found might eventually be allocated, and needs to be freed */
-int hc_listener_get(hc_sock_t *s, hc_listener_t * listener,
+int hc_listener_get(hc_sock_t * s, hc_listener_t * listener,
hc_listener_t ** listener_found);
int hc_listener_delete(hc_sock_t * s, hc_listener_t * listener);
int hc_listener_list(hc_sock_t * s, hc_data_t ** pdata);
@@ -500,7 +485,7 @@ int hc_listener_snprintf(char * s, size_t size, hc_listener_t * listener);
*/
typedef struct {
u32 id; /* Kr. */
- char name[NAME_LEN]; /* K.w */
+ char name[SYMBOLIC_NAME_LEN]; /* K.w */
char interface_name[INTERFACE_LEN]; /* Kr. */
hc_connection_type_t type; /* .rw */
int family; /* .rw */
@@ -518,7 +503,7 @@ typedef struct {
int hc_connection_create(hc_sock_t * s, hc_connection_t * connection);
/* connection_found will be allocated, and must be freed */
-int hc_connection_get(hc_sock_t *s, hc_connection_t * connection,
+int hc_connection_get(hc_sock_t * s, hc_connection_t * connection,
hc_connection_t ** connection_found);
int hc_connection_update_by_id(hc_sock_t * s, int hc_connection_id,
hc_connection_t * connection);
@@ -562,7 +547,7 @@ int hc_connection_snprintf(char * s, size_t size, const hc_connection_t * connec
typedef struct {
u8 id;
- char name[NAME_LEN];
+ char name[SYMBOLIC_NAME_LEN];
face_t face; // or embed ?
//face_id_t parent; /* Pointer from connection to listener */
} hc_face_t;
@@ -579,13 +564,14 @@ int hc_face_create(hc_sock_t * s, hc_face_t * face);
int hc_face_get(hc_sock_t * s, hc_face_t * face, hc_face_t ** face_found);
int hc_face_delete(hc_sock_t * s, hc_face_t * face);
int hc_face_list(hc_sock_t * s, hc_data_t ** pdata);
+int hc_face_list_async(hc_sock_t * s); //, hc_data_t ** pdata);
#define foreach_face(VAR, data) foreach_type(hc_face_t, VAR, data)
#define MAX_FACE_ID 255
#define MAXSZ_FACE_ID_ 3
#define MAXSZ_FACE_ID MAXSZ_FACE_ID_ + NULLTERM
-#define MAXSZ_FACE_NAME_ NAMELEN
+#define MAXSZ_FACE_NAME_ SYMBOLIC_NAME_LEN
#define MAXSZ_FACE_NAME MAXSZ_FACE_NAME_ + NULLTERM
#define MAXSZ_HC_FACE_ MAXSZ_FACE_ID_ + MAXSZ_FACE_NAME_ + MAXSZ_FACE_ + 5
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
index 75f05988f..e69c93932 100755
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
@@ -168,8 +168,8 @@ typedef struct {
uint32_t connid;
uint8_t state;
uint8_t admin_state;
- char connectionName[16];
char interfaceName[16];
+ char connectionName[16];
} list_connections_command;
// SIZE=64
diff --git a/ctrl/libhicnctrl/src/CMakeLists.txt b/ctrl/libhicnctrl/src/CMakeLists.txt
index 7b4413d55..4708595e0 100644
--- a/ctrl/libhicnctrl/src/CMakeLists.txt
+++ b/ctrl/libhicnctrl/src/CMakeLists.txt
@@ -24,6 +24,7 @@ set(HEADER_FILES
set(UTIL_HEADER_FILES
face.h
util/log.h
+ util/map.h
)
set(SOURCE_FILES
diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c
index 769c96076..0e5b529c5 100644
--- a/ctrl/libhicnctrl/src/api.c
+++ b/ctrl/libhicnctrl/src/api.c
@@ -20,6 +20,7 @@
#include <assert.h> // assert
#include <math.h> // log2
+#include <stdbool.h>
#include <stdio.h> // snprintf
#include <string.h> // memmove, strcasecmp
#include <sys/socket.h> // socket
@@ -30,10 +31,83 @@
#include <hicn/ctrl/commands.h>
#include <hicn/util/token.h>
#include "util/log.h"
+#include "util/map.h"
#include <strings.h>
#define PORT 9695
+/*
+ * Internal state associated to a pending request
+ */
+typedef struct {
+ int seq;
+ hc_data_t * data;
+ /* Information used to process results */
+ int size_in;
+ int (*parse)(const u8 * src, u8 * dst);
+} hc_sock_request_t;
+
+/**
+ * Messages to the forwarder might be multiplexed thanks to the seqNum fields in
+ * the header_control_message structure. The forwarder simply answers back the
+ * original sequence number. We maintain a map of such sequence number to
+ * outgoing queries so that replied can be demultiplexed and treated
+ * appropriately.
+ */
+TYPEDEF_MAP_H(hc_sock_map, int, hc_sock_request_t *);
+TYPEDEF_MAP(hc_sock_map, int, hc_sock_request_t *, int_cmp, int_snprintf, generic_snprintf);
+
+struct hc_sock_s {
+ char * url;
+ int fd;
+
+ /* Partial receive buffer */
+ u8 buf[RECV_BUFLEN];
+ size_t roff; /**< Read offset */
+ size_t woff; /**< Write offset */
+
+ /*
+ * Because received messages are potentially unbounded in size, we might not
+ * guarantee that we can store a full packet before processing it. We must
+ * implement a very simple state machine remembering the current parsing
+ * status in order to partially process the packet.
+ */
+ size_t remaining;
+ u32 send_id;
+
+ /* Next sequence number to be used for requests */
+ int seq;
+
+ /* Request being parsed (NULL if none) */
+ hc_sock_request_t * cur_request;
+
+ bool async;
+ hc_sock_map_t * map;
+};
+
+
+hc_sock_request_t *
+hc_sock_request_create(int seq, hc_data_t * data, HC_PARSE parse)
+{
+ assert(seq >= 0);
+ assert(data);
+
+ hc_sock_request_t * request = malloc(sizeof(hc_sock_request_t));
+ if (!request)
+ return NULL;
+ request->seq = seq;
+ request->data = data;
+ request->parse = parse;
+ return request;
+}
+
+void
+hc_sock_request_free(hc_sock_request_t * request)
+{
+ free(request);
+}
+
+
#if 0
#ifdef __APPLE__
#define RANDBYTE() (u8)(arc4random() & 0xFF)
@@ -239,7 +313,7 @@ hc_data_create(size_t in_element_size, size_t out_element_size)
data->in_element_size = in_element_size;
data->out_element_size = out_element_size;
data->size = 0;
- data->complete = 0;
+ data->complete = false;
data->command_id = 0; // TODO this could also be a busy mark in the socket
/* No callback needed in blocking code for instance */
data->complete_cb = NULL;
@@ -274,21 +348,21 @@ hc_data_ensure_available(hc_data_t * data, size_t count)
data->max_size_log = new_size_log;
data->buffer = realloc(data->buffer, (1 << new_size_log) * data->out_element_size);
if (!data->buffer)
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
int
hc_data_push_many(hc_data_t * data, const void * elements, size_t count)
{
if (hc_data_ensure_available(data, count) < 0)
- return LIBHICNCTRL_FAILURE;
+ return -1;
memcpy(data->buffer + data->size * data->out_element_size, elements,
count * data->out_element_size);
data->size += count;
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
int
@@ -316,7 +390,7 @@ hc_data_set_callback(hc_data_t * data, data_callback_t cb, void * cb_data)
{
data->complete_cb = cb;
data->complete_cb_data = cb_data;
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
int
@@ -325,14 +399,14 @@ hc_data_set_complete(hc_data_t * data)
data->complete = true;
if (data->complete_cb)
return data->complete_cb(data, data->complete_cb_data);
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
int
hc_data_reset(hc_data_t * data)
{
data->size = 0;
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/******************************************************************************
@@ -377,10 +451,10 @@ hc_sock_parse_url(const char * url, struct sockaddr * sa)
break;
}
default:
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
hc_sock_t *
@@ -399,9 +473,20 @@ hc_sock_create_url(const char * url)
if (hc_sock_reset(s) < 0)
goto ERR_RESET;
+ s->seq = 0;
+ s->cur_request = NULL;
+
+ s->map = hc_sock_map_create();
+ if (!s->map)
+ goto ERR_MAP;
+
return s;
+ //hc_sock_map_free(s->map);
+ERR_MAP:
ERR_RESET:
+ if (s->url)
+ free(s->url);
close(s->fd);
ERR_SOCKET:
free(s);
@@ -418,6 +503,19 @@ hc_sock_create(void)
void
hc_sock_free(hc_sock_t * s)
{
+ hc_sock_request_t ** request_array = NULL;
+ int n = hc_sock_map_get_value_array(s->map, &request_array);
+ if (n < 0) {
+ ERROR("Could not retrieve pending request array for freeing up resources");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ hc_sock_request_t * request = request_array[i];
+ hc_sock_request_free(request);
+ }
+ free(request_array);
+ }
+
+ hc_sock_map_free(s->map);
if (s->url)
free(s->url);
close(s->fd);
@@ -425,13 +523,25 @@ hc_sock_free(hc_sock_t * s)
}
int
-hc_sock_set_nonblocking(hc_sock_t *s)
+hc_sock_get_next_seq(hc_sock_t * s)
+{
+ return s->seq++;
+}
+
+int
+hc_sock_set_nonblocking(hc_sock_t * s)
{
return (fcntl(s->fd, F_SETFL, fcntl(s->fd, F_GETFL) | O_NONBLOCK) < 0);
}
int
-hc_sock_connect(hc_sock_t *s)
+hc_sock_get_fd(hc_sock_t * s)
+{
+ return s->fd;
+}
+
+int
+hc_sock_connect(hc_sock_t * s)
{
struct sockaddr_storage ss = { 0 };
@@ -444,17 +554,18 @@ hc_sock_connect(hc_sock_t *s)
if (connect(s->fd, (struct sockaddr *)&ss, size) < 0) //sizeof(struct sockaddr)) < 0)
goto ERR_CONNECT;
- return LIBHICNCTRL_SUCCESS;
+ return 0;
ERR_CONNECT:
ERR_PARSE:
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
int
-hc_sock_send(hc_sock_t * s, hc_msg_t * msg, size_t msglen)
+hc_sock_send(hc_sock_t * s, hc_msg_t * msg, size_t msglen, int seq)
{
int rc;
+ msg->hdr.seqNum = seq;
rc = send(s->fd, msg, msglen, 0);
if (rc < 0) {
perror("hc_sock_send");
@@ -469,11 +580,11 @@ hc_sock_get_available(hc_sock_t * s, u8 ** buffer, size_t * size)
*buffer = s->buf + s->woff;
*size = RECV_BUFLEN - s->woff;
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
int
-hc_sock_recv(hc_sock_t * s, hc_data_t * data)
+hc_sock_recv(hc_sock_t * s)
{
int rc;
@@ -485,24 +596,24 @@ hc_sock_recv(hc_sock_t * s, hc_data_t * data)
rc = recv(s->fd, s->buf + s->woff, RECV_BUFLEN - s->woff, 0);
if (rc == 0) {
- return LIBHICNCTRL_FAILURE;
/* Connection has been closed */
- // XXX
+ return 0;
}
if (rc < 0) {
+ /*
+ * Let's not return 0 which currently means the socket has been closed
+ */
+ if (errno == EWOULDBLOCK)
+ return -1;
perror("hc_sock_recv");
- /* Error occurred */
- // XXX check for EWOULDBLOCK;
- // XXX
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
s->woff += rc;
- return LIBHICNCTRL_SUCCESS;
+ return rc;
}
int
-hc_sock_process(hc_sock_t * s, hc_data_t * data,
- int (*parse)(const u8 * src, u8 * dst))
+hc_sock_process(hc_sock_t * s, hc_data_t ** data)
{
int err = 0;
@@ -511,7 +622,7 @@ hc_sock_process(hc_sock_t * s, hc_data_t * data,
while(available > 0) {
- if (s->remaining == 0) {
+ if (!s->cur_request) { // No message being parsed, alternatively (remaining == 0)
hc_msg_t * msg = (hc_msg_t*)(s->buf + s->roff);
/* We expect a message header */
@@ -519,74 +630,82 @@ hc_sock_process(hc_sock_t * s, hc_data_t * data,
break;
/* Sanity checks (might instead raise warnings) */
- // TODO: sync check ?
assert((msg->hdr.messageType == RESPONSE_LIGHT) ||
(msg->hdr.messageType == ACK_LIGHT) ||
(msg->hdr.messageType == NACK_LIGHT));
- //assert(msg->hdr.commandID == data->command_id); // FIXME
- assert(msg->hdr.seqNum == s->recv_seq++);
+ hc_sock_request_t * request = NULL;
+ if (hc_sock_map_get(s->map, msg->hdr.seqNum, &request) < 0) {
+ ERROR("[hc_sock_process] Error searching for matching request");
+ return -1;
+ }
+ if (!request) {
+ ERROR("[hc_sock_process] No request matching received sequence number");
+ return -1;
+ }
s->remaining = msg->hdr.length;
if (s->remaining == 0) {
- /*
- * The protocol expects all sequence number to be reset after
- * each transaction. We reset before running the callback in
- * case it triggers new exchanges.
- */
- s->send_seq = HICN_CTRL_SEND_SEQ_INIT;
- s->recv_seq = HICN_CTRL_RECV_SEQ_INIT;
-
- // TODO : check before even sending ?
- /* Complete message without payload */
- // TODO : is this correct ? no error code ?
- hc_data_set_complete(data);
+ if (data) {
+ *data = request->data;
+// } else {
+// free(request->data);
+ }
+ hc_data_set_complete(request->data);
+ hc_sock_request_free(request);
+ } else {
+ /* We only remember it if there is still data to parse */
+ s->cur_request = request;
}
available -= sizeof(hc_msg_header_t);
s->roff += sizeof(hc_msg_header_t);
} else {
/* We expect the complete payload, or at least a chunk of it */
- size_t num_chunks = available / data->in_element_size;
+ size_t num_chunks = available / s->cur_request->data->in_element_size;
if (num_chunks == 0)
break;
if (num_chunks > s->remaining)
num_chunks = s->remaining;
- if (!parse) {
- hc_data_push_many(data, s->buf + s->roff, num_chunks);
+ if (!s->cur_request->parse) {
+ /* If we don't need to parse results, then we can directly push
+ * all of them into the result data structure */
+ hc_data_push_many(s->cur_request->data, s->buf + s->roff, num_chunks);
} else {
int rc;
- rc = hc_data_ensure_available(data, num_chunks);
+ rc = hc_data_ensure_available(s->cur_request->data, num_chunks);
if (rc < 0)
- return LIBHICNCTRL_FAILURE;
+ return -1;
for (int i = 0; i < num_chunks; i++) {
- u8 * dst = hc_data_get_next(data);
+ u8 * dst = hc_data_get_next(s->cur_request->data);
if (!dst)
- return LIBHICNCTRL_FAILURE;
+ return -1;
- rc = parse(s->buf + s->roff + i * data->in_element_size, dst);
+ rc = s->cur_request->parse(s->buf + s->roff + i * s->cur_request->data->in_element_size, dst);
if (rc < 0)
err = -1; /* FIXME we let the loop complete (?) */
- data->size++;
+ s->cur_request->data->size++;
}
}
-
s->remaining -= num_chunks;
+ available -= num_chunks * s->cur_request->data->in_element_size;
+ s->roff += num_chunks * s->cur_request->data->in_element_size;
if (s->remaining == 0) {
- /*
- * The protocol expects all sequence number to be reset after
- * each transaction. We reset before running the callback in
- * case it triggers new exchanges.
- */
- s->send_seq = HICN_CTRL_SEND_SEQ_INIT;
- s->recv_seq = HICN_CTRL_RECV_SEQ_INIT;
-
- hc_data_set_complete(data);
+ if (hc_sock_map_remove(s->map, s->cur_request->seq, NULL) < 0) {
+ ERROR("[hc_sock_process] Error removing request from map");
+ return -1;
+ }
+ if (data) {
+ *data = s->cur_request->data;
+// } else {
+// free(s->cur_request->data);
+ }
+ hc_data_set_complete(s->cur_request->data);
+ hc_sock_request_free(s->cur_request);
+ s->cur_request = NULL;
}
- available -= num_chunks * data->in_element_size;
- s->roff += num_chunks * data->in_element_size;
}
}
@@ -605,13 +724,47 @@ hc_sock_process(hc_sock_t * s, hc_data_t * data,
}
int
+hc_sock_callback(hc_sock_t * s, hc_data_t ** data)
+{
+ *data = NULL;
+
+ for (;;) {
+ int n = hc_sock_recv(s);
+ if (n == 0) {
+ goto ERR_EOF;
+ }
+ if (n < 0) {
+ switch(errno) {
+ case ECONNRESET:
+ case ENODEV:
+ /* Forwarder restarted */
+ WARN("Forwarder likely restarted: not (yet) implemented");
+ goto ERR_EOF;
+ case EWOULDBLOCK:
+ //DEBUG("Would block... stop reading from socket");
+ goto END;
+ default:
+ perror("hc_sock_recv");
+ goto ERR_EOF;
+ }
+ }
+ if (hc_sock_process(s, data) < 0) {
+ return -1;
+ }
+ }
+END:
+ return 0;
+
+ERR_EOF:
+ return -1;
+}
+
+int
hc_sock_reset(hc_sock_t * s)
{
s->roff = s->woff = 0;
- s->send_seq = HICN_CTRL_SEND_SEQ_INIT;
- s->recv_seq = HICN_CTRL_RECV_SEQ_INIT;
s->remaining = 0;
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/******************************************************************************
@@ -630,8 +783,11 @@ typedef struct {
int
hc_execute_command(hc_sock_t * s, hc_msg_t * msg, size_t msg_len,
- hc_command_params_t * params, hc_data_t ** pdata)
+ hc_command_params_t * params, hc_data_t ** pdata, bool async)
{
+ if (async)
+ assert(!pdata);
+
/* Sanity check */
switch(params->cmd) {
case ACTION_CREATE:
@@ -655,35 +811,70 @@ hc_execute_command(hc_sock_t * s, hc_msg_t * msg, size_t msg_len,
assert(params->parse == NULL);
break;
default:
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
- hc_sock_reset(s);
+ //hc_sock_reset(s);
/* XXX data will at least store the result (complete) */
hc_data_t * data = hc_data_create(params->size_in, params->size_out);
- if (!data)
+ if (!data) {
+ ERROR("[hc_execute_command] Could not create data storage");
goto ERR_DATA;
+ }
+
+ int seq = hc_sock_get_next_seq(s);
+ if (seq < 0) {
+ ERROR("[hc_execute_command] Could not get next sequence number");
+ goto ERR_SEQ;
+ }
+
+ /* Create state used to process the request */
+ hc_sock_request_t * request = NULL;
+ request = hc_sock_request_create(seq, data, params->parse);
+ if (!request) {
+ ERROR("[hc_execute_command] Could not create request state");
+ goto ERR_REQUEST;
+ }
+
+ /* Add state to map */
+ if (hc_sock_map_add(s->map, seq, request) < 0) {
+ ERROR("[hc_execute_command] Error adding request state to map");
+ goto ERR_MAP;
+ }
- if (hc_sock_send(s, msg, msg_len) < 0)
+ if (hc_sock_send(s, msg, msg_len, seq) < 0) {
+ ERROR("[hc_execute_command] Error sending message");
goto ERR_PROCESS;
+ }
+
+ if (async)
+ return 0;
+
while(!data->complete) {
- if (hc_sock_recv(s, data) < 0)
- break;
- if (hc_sock_process(s, data, params->parse) < 0) {
+ /*
+ * As the socket is non blocking it might happen that we need to read
+ * several times before success... shall we alternate between blocking
+ * and non-blocking mode ?
+ */
+ if (hc_sock_recv(s) < 0)
+ continue; //break;
+ if (hc_sock_process(s, pdata) < 0) {
+ ERROR("[hc_execute_command] Error processing socket results");
goto ERR_PROCESS;
}
}
- if (pdata)
- *pdata = data;
-
- return LIBHICNCTRL_SUCCESS;
+ return 0;
ERR_PROCESS:
+ERR_MAP:
+ hc_sock_request_free(request);
+ERR_REQUEST:
+ERR_SEQ:
free(data);
ERR_DATA:
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
/*----------------------------------------------------------------------------*
@@ -693,13 +884,13 @@ ERR_DATA:
/* LISTENER CREATE */
int
-hc_listener_create(hc_sock_t * s, hc_listener_t * listener)
+_hc_listener_create(hc_sock_t * s, hc_listener_t * listener, bool async)
{
if (!IS_VALID_FAMILY(listener->family))
- return LIBHICNCTRL_FAILURE;
+ return -1;
if (!IS_VALID_CONNECTION_TYPE(listener->type))
- return LIBHICNCTRL_FAILURE;
+ return -1;
struct {
header_control_message hdr;
@@ -709,7 +900,7 @@ hc_listener_create(hc_sock_t * s, hc_listener_t * listener)
.messageType = REQUEST_LIGHT,
.commandID = ADD_LISTENER,
.length = 1,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
.payload = {
.address = {
@@ -722,7 +913,7 @@ hc_listener_create(hc_sock_t * s, hc_listener_t * listener)
}
};
- snprintf(msg.payload.symbolic, NAME_LEN, "%s", listener->name);
+ snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", listener->name);
snprintf(msg.payload.interfaceName, INTERFACE_LEN, "%s", listener->interface_name);
hc_command_params_t params = {
@@ -733,31 +924,43 @@ hc_listener_create(hc_sock_t * s, hc_listener_t * listener)
.parse = NULL,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+int
+hc_listener_create(hc_sock_t * s, hc_listener_t * listener)
+{
+ return _hc_listener_create(s, listener, false);
+}
+
+int
+hc_listener_create_async(hc_sock_t * s, hc_listener_t * listener)
+{
+ return _hc_listener_create(s, listener, true);
}
/* LISTENER GET */
int
-hc_listener_get(hc_sock_t *s, hc_listener_t * listener,
+hc_listener_get(hc_sock_t * s, hc_listener_t * listener,
hc_listener_t ** listener_found)
{
hc_data_t * listeners;
hc_listener_t * found;
if (hc_listener_list(s, &listeners) < 0)
- return LIBHICNCTRL_FAILURE;
+ return -1;
/* Test */
if (hc_listener_find(listeners, listener, &found) < 0) {
hc_data_free(listeners);
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
if (found) {
*listener_found = malloc(sizeof(hc_listener_t));
if (!*listener_found)
- return LIBHICNCTRL_FAILURE;
+ return -1;
**listener_found = *found;
} else {
*listener_found = NULL;
@@ -765,14 +968,14 @@ hc_listener_get(hc_sock_t *s, hc_listener_t * listener,
hc_data_free(listeners);
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/* LISTENER DELETE */
int
-hc_listener_delete(hc_sock_t * s, hc_listener_t * listener)
+_hc_listener_delete(hc_sock_t * s, hc_listener_t * listener, bool async)
{
struct {
header_control_message hdr;
@@ -782,25 +985,21 @@ hc_listener_delete(hc_sock_t * s, hc_listener_t * listener)
.messageType = REQUEST_LIGHT,
.commandID = REMOVE_LISTENER,
.length = 1,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
};
if (listener->id) {
- printf("Delete by ID\n");
- snprintf(msg.payload.symbolicOrListenerid, NAME_LEN, "%d", listener->id);
+ snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", listener->id);
} else if (*listener->name) {
- printf("Delete by name %s\n", listener->name);
- snprintf(msg.payload.symbolicOrListenerid, NAME_LEN, "%s", listener->name);
+ snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%s", listener->name);
} else {
- printf("Delete after search\n");
hc_listener_t * listener_found;
if (hc_listener_get(s, listener, &listener_found) < 0)
- return LIBHICNCTRL_FAILURE;
+ return -1;
if (!listener_found)
- return LIBHICNCTRL_FAILURE;
- printf("Delete listener ID=%d\n", listener_found->id);
- snprintf(msg.payload.symbolicOrListenerid, NAME_LEN, "%d", listener_found->id);
+ return -1;
+ snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", listener_found->id);
free(listener_found);
}
@@ -812,13 +1011,26 @@ hc_listener_delete(hc_sock_t * s, hc_listener_t * listener)
.parse = NULL,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+int
+hc_listener_delete(hc_sock_t * s, hc_listener_t * listener)
+{
+ return _hc_listener_delete(s, listener, false);
+}
+
+int
+hc_listener_delete_async(hc_sock_t * s, hc_listener_t * listener)
+{
+ return _hc_listener_delete(s, listener, true);
}
+
/* LISTENER LIST */
int
-hc_listener_list(hc_sock_t * s, hc_data_t ** pdata)
+_hc_listener_list(hc_sock_t * s, hc_data_t ** pdata, bool async)
{
struct {
header_control_message hdr;
@@ -827,7 +1039,7 @@ hc_listener_list(hc_sock_t * s, hc_data_t ** pdata)
.messageType = REQUEST_LIGHT,
.commandID = LIST_LISTENERS,
.length = 0,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
};
@@ -839,7 +1051,19 @@ hc_listener_list(hc_sock_t * s, hc_data_t ** pdata)
.parse = (HC_PARSE)hc_listener_parse,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, pdata);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
+}
+
+int
+hc_listener_list(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_listener_list(s, pdata, false);
+}
+
+int
+hc_listener_list_async(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_listener_list(s, pdata, true);
}
/* LISTENER VALIDATE */
@@ -848,12 +1072,12 @@ int
hc_listener_validate(const hc_listener_t * listener)
{
if (!IS_VALID_FAMILY(listener->family))
- return LIBHICNCTRL_FAILURE;
+ return -1;
if (!IS_VALID_CONNECTION_TYPE(listener->type))
- return LIBHICNCTRL_FAILURE;
+ return -1;
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/* LISTENER CMP */
@@ -866,8 +1090,8 @@ hc_listener_cmp(const hc_listener_t * l1, const hc_listener_t * l2)
(strncmp(l1->interface_name, l2->interface_name, INTERFACE_LEN) == 0) &&
(ip_address_cmp(&l1->local_addr, &l2->local_addr, l1->family) == 0) &&
(l1->local_port == l2->local_port))
- ? LIBHICNCTRL_SUCCESS
- : LIBHICNCTRL_FAILURE;
+ ? 0
+ : -1;
}
/* LISTENER PARSE */
@@ -878,18 +1102,18 @@ hc_listener_parse(void * in, hc_listener_t * listener)
list_listeners_command * cmd = (list_listeners_command *)in;
if (!IS_VALID_LIST_LISTENERS_TYPE(cmd->encapType))
- return LIBHICNCTRL_FAILURE;
+ return -1;
hc_connection_type_t type = map_from_encap_type[cmd->encapType];
if (type == CONNECTION_TYPE_UNDEFINED)
- return LIBHICNCTRL_FAILURE;
+ return -1;
if (!IS_VALID_ADDR_TYPE(cmd->addressType))
- return LIBHICNCTRL_FAILURE;
+ return -1;
int family = map_from_addr_type[cmd->addressType];
if (!IS_VALID_FAMILY(family))
- return LIBHICNCTRL_FAILURE;
+ return -1;
*listener = (hc_listener_t) {
.id = cmd->connid,
@@ -898,9 +1122,9 @@ hc_listener_parse(void * in, hc_listener_t * listener)
.local_addr = UNION_CAST(cmd->address, ip_address_t),
.local_port = ntohs(cmd->port),
};
- snprintf(listener->name, NAME_LEN, "%s", cmd->listenerName);
+ snprintf(listener->name, SYMBOLIC_NAME_LEN, "%s", cmd->listenerName);
snprintf(listener->interface_name, INTERFACE_LEN, "%s", cmd->interfaceName);
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
GENERATE_FIND(listener)
@@ -931,10 +1155,10 @@ hc_listener_snprintf(char * s, size_t size, hc_listener_t * listener)
/* CONNECTION CREATE */
int
-hc_connection_create(hc_sock_t * s, hc_connection_t * connection)
+_hc_connection_create(hc_sock_t * s, hc_connection_t * connection, bool async)
{
if (hc_connection_validate(connection) < 0)
- return LIBHICNCTRL_FAILURE;
+ return -1;
struct {
header_control_message hdr;
@@ -944,7 +1168,7 @@ hc_connection_create(hc_sock_t * s, hc_connection_t * connection)
.messageType = REQUEST_LIGHT,
.commandID = ADD_CONNECTION,
.length = 1,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
.payload = {
/* we use IPv6 which is the longest address */
@@ -960,7 +1184,7 @@ hc_connection_create(hc_sock_t * s, hc_connection_t * connection)
.connectionType = (u8)map_to_connection_type[connection->type],
}
};
- snprintf(msg.payload.symbolic, NAME_LEN, "%s", connection->name);
+ snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", connection->name);
hc_command_params_t params = {
.cmd = ACTION_CREATE,
@@ -970,31 +1194,43 @@ hc_connection_create(hc_sock_t * s, hc_connection_t * connection)
.parse = NULL,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+int
+hc_connection_create(hc_sock_t * s, hc_connection_t * connection)
+{
+ return _hc_connection_create(s, connection, false);
+}
+
+int
+hc_connection_create_async(hc_sock_t * s, hc_connection_t * connection)
+{
+ return _hc_connection_create(s, connection, true);
}
/* CONNECTION GET */
int
-hc_connection_get(hc_sock_t *s, hc_connection_t * connection,
+hc_connection_get(hc_sock_t * s, hc_connection_t * connection,
hc_connection_t ** connection_found)
{
hc_data_t * connections;
hc_connection_t * found;
if (hc_connection_list(s, &connections) < 0)
- return LIBHICNCTRL_FAILURE;
+ return -1;
/* Test */
if (hc_connection_find(connections, connection, &found) < 0) {
hc_data_free(connections);
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
if (found) {
*connection_found = malloc(sizeof(hc_connection_t));
if (!*connection_found)
- return LIBHICNCTRL_FAILURE;
+ return -1;
**connection_found = *found;
} else {
*connection_found = NULL;
@@ -1002,14 +1238,14 @@ hc_connection_get(hc_sock_t *s, hc_connection_t * connection,
hc_data_free(connections);
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/* CONNECTION DELETE */
int
-hc_connection_delete(hc_sock_t * s, hc_connection_t * connection)
+_hc_connection_delete(hc_sock_t * s, hc_connection_t * connection, bool async)
{
struct {
header_control_message hdr;
@@ -1019,25 +1255,21 @@ hc_connection_delete(hc_sock_t * s, hc_connection_t * connection)
.messageType = REQUEST_LIGHT,
.commandID = REMOVE_CONNECTION,
.length = 1,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
};
if (connection->id) {
- printf("Delete by ID\n");
- snprintf(msg.payload.symbolicOrConnid, NAME_LEN, "%d", connection->id);
+ snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", connection->id);
} else if (*connection->name) {
- printf("Delete by name %s\n", connection->name);
- snprintf(msg.payload.symbolicOrConnid, NAME_LEN, "%s", connection->name);
+ snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", connection->name);
} else {
- printf("Delete after search\n");
hc_connection_t * connection_found;
if (hc_connection_get(s, connection, &connection_found) < 0)
- return LIBHICNCTRL_FAILURE;
+ return -1;
if (!connection_found)
- return LIBHICNCTRL_FAILURE;
- printf("Delete connection ID=%d\n", connection_found->id);
- snprintf(msg.payload.symbolicOrConnid, NAME_LEN, "%d", connection_found->id);
+ return -1;
+ snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", connection_found->id);
free(connection_found);
}
@@ -1049,14 +1281,25 @@ hc_connection_delete(hc_sock_t * s, hc_connection_t * connection)
.parse = NULL,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
}
+int
+hc_connection_delete(hc_sock_t * s, hc_connection_t * connection)
+{
+ return _hc_connection_delete(s, connection, false);
+}
+
+int
+hc_connection_delete_async(hc_sock_t * s, hc_connection_t * connection)
+{
+ return _hc_connection_delete(s, connection, true);
+}
/* CONNECTION LIST */
int
-hc_connection_list(hc_sock_t * s, hc_data_t ** pdata)
+_hc_connection_list(hc_sock_t * s, hc_data_t ** pdata, bool async)
{
struct {
header_control_message hdr;
@@ -1065,7 +1308,7 @@ hc_connection_list(hc_sock_t * s, hc_data_t ** pdata)
.messageType = REQUEST_LIGHT,
.commandID = LIST_CONNECTIONS,
.length = 0,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
};
@@ -1077,7 +1320,19 @@ hc_connection_list(hc_sock_t * s, hc_data_t ** pdata)
.parse = (HC_PARSE)hc_connection_parse,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, pdata);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
+}
+
+int
+hc_connection_list(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_connection_list(s, pdata, false);
+}
+
+int
+hc_connection_list_async(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_connection_list(s, pdata, true);
}
/* CONNECTION VALIDATE */
@@ -1086,14 +1341,14 @@ int
hc_connection_validate(const hc_connection_t * connection)
{
if (!IS_VALID_FAMILY(connection->family))
- return LIBHICNCTRL_FAILURE;
+ return -1;
if (!IS_VALID_CONNECTION_TYPE(connection->type))
- return LIBHICNCTRL_FAILURE;
+ return -1;
/* TODO assert both local and remote have the right family */
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/* CONNECTION CMP */
@@ -1111,8 +1366,8 @@ int hc_connection_cmp(const hc_connection_t * c1, const hc_connection_t * c2)
(c1->local_port == c2->local_port) &&
(ip_address_cmp(&c1->remote_addr, &c2->remote_addr, c1->family) == 0) &&
(c1->remote_port == c2->remote_port))
- ? LIBHICNCTRL_SUCCESS
- : LIBHICNCTRL_FAILURE;
+ ? 0
+ : -1;
}
/* CONNECTION PARSE */
@@ -1123,25 +1378,25 @@ hc_connection_parse(void * in, hc_connection_t * connection)
list_connections_command * cmd = (list_connections_command *)in;
if (!IS_VALID_LIST_CONNECTIONS_TYPE(cmd->connectionData.connectionType))
- return LIBHICNCTRL_FAILURE;
+ return -1;
hc_connection_type_t type = map_from_list_connections_type[cmd->connectionData.connectionType];
if (type == CONNECTION_TYPE_UNDEFINED)
- return LIBHICNCTRL_FAILURE;
+ return -1;
if (!IS_VALID_LIST_CONNECTIONS_STATE(cmd->state))
- return LIBHICNCTRL_FAILURE;
+ return -1;
hc_connection_state_t state = map_from_list_connections_state[cmd->state];
if (state == HC_CONNECTION_STATE_UNDEFINED)
- return LIBHICNCTRL_FAILURE;
+ return -1;
if (!IS_VALID_ADDR_TYPE(cmd->connectionData.ipType))
- return LIBHICNCTRL_FAILURE;
+ return -1;
int family = map_from_addr_type[cmd->connectionData.ipType];
if (!IS_VALID_FAMILY(family))
- return LIBHICNCTRL_FAILURE;
+ return -1;
*connection = (hc_connection_t) {
.id = cmd->connid,
@@ -1157,9 +1412,9 @@ hc_connection_parse(void * in, hc_connection_t * connection)
#endif /* WITH_POLICY */
.state = state,
};
- snprintf(connection->name, NAME_LEN, "%s", cmd->connectionData.symbolic);
+ snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", cmd->connectionData.symbolic);
snprintf(connection->interface_name, INTERFACE_LEN, "%s", cmd->interfaceName);
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
GENERATE_FIND(connection)
@@ -1196,8 +1451,8 @@ hc_connection_snprintf(char * s, size_t size, const hc_connection_t * connection
/* CONNECTION SET ADMIN STATE */
int
-hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
- face_state_t state)
+_hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
+ face_state_t state, bool async)
{
struct {
header_control_message hdr;
@@ -1207,13 +1462,13 @@ hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
.messageType = REQUEST_LIGHT,
.commandID = CONNECTION_SET_ADMIN_STATE,
.length = 1,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
.payload = {
.admin_state = state,
},
};
- snprintf(msg.payload.symbolicOrConnid, NAME_LEN, "%s", conn_id_or_name);
+ snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%s", conn_id_or_name);
hc_command_params_t params = {
.cmd = ACTION_SET,
@@ -1223,7 +1478,21 @@ hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
.parse = NULL,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+int
+hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
+ face_state_t state)
+{
+ return _hc_connection_set_admin_state(s, conn_id_or_name, state, false);
+}
+
+int
+hc_connection_set_admin_state_async(hc_sock_t * s, const char * conn_id_or_name,
+ face_state_t state)
+{
+ return _hc_connection_set_admin_state(s, conn_id_or_name, state, true);
}
/*----------------------------------------------------------------------------*
@@ -1233,10 +1502,10 @@ hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
/* ROUTE CREATE */
int
-hc_route_create(hc_sock_t * s, hc_route_t * route)
+_hc_route_create(hc_sock_t * s, hc_route_t * route, bool async)
{
if (!IS_VALID_FAMILY(route->family))
- return LIBHICNCTRL_FAILURE;
+ return -1;
struct {
header_control_message hdr;
@@ -1246,7 +1515,7 @@ hc_route_create(hc_sock_t * s, hc_route_t * route)
.messageType = REQUEST_LIGHT,
.commandID = ADD_ROUTE,
.length = 1,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
.payload = {
/* we use IPv6 which is the longest address */
@@ -1261,7 +1530,7 @@ hc_route_create(hc_sock_t * s, hc_route_t * route)
* The route commands expects the ID (or name that we don't use) as part of
* the symbolicOrConnid attribute.
*/
- snprintf(msg.payload.symbolicOrConnid, NAME_LEN, "%d", route->face_id);
+ snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", route->face_id);
hc_command_params_t params = {
.cmd = ACTION_CREATE,
@@ -1271,16 +1540,28 @@ hc_route_create(hc_sock_t * s, hc_route_t * route)
.parse = NULL,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+int
+hc_route_create(hc_sock_t * s, hc_route_t * route)
+{
+ return _hc_route_create(s, route, false);
+}
+
+int
+hc_route_create_async(hc_sock_t * s, hc_route_t * route)
+{
+ return _hc_route_create(s, route, true);
}
/* ROUTE DELETE */
int
-hc_route_delete(hc_sock_t * s, hc_route_t * route)
+_hc_route_delete(hc_sock_t * s, hc_route_t * route, bool async)
{
if (!IS_VALID_FAMILY(route->family))
- return LIBHICNCTRL_FAILURE;
+ return -1;
struct {
header_control_message hdr;
@@ -1290,7 +1571,7 @@ hc_route_delete(hc_sock_t * s, hc_route_t * route)
.messageType = REQUEST_LIGHT,
.commandID = REMOVE_ROUTE,
.length = 1,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
.payload = {
/* we use IPv6 which is the longest address */
@@ -1308,13 +1589,25 @@ hc_route_delete(hc_sock_t * s, hc_route_t * route)
.parse = NULL,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+int
+hc_route_delete(hc_sock_t * s, hc_route_t * route)
+{
+ return _hc_route_delete(s, route, false);
+}
+
+int
+hc_route_delete_async(hc_sock_t * s, hc_route_t * route)
+{
+ return _hc_route_delete(s, route, true);
}
/* ROUTE LIST */
int
-hc_route_list(hc_sock_t * s, hc_data_t ** pdata)
+_hc_route_list(hc_sock_t * s, hc_data_t ** pdata, bool async)
{
struct {
header_control_message hdr;
@@ -1323,7 +1616,7 @@ hc_route_list(hc_sock_t * s, hc_data_t ** pdata)
.messageType = REQUEST_LIGHT,
.commandID = LIST_ROUTES,
.length = 0,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
};
@@ -1335,7 +1628,19 @@ hc_route_list(hc_sock_t * s, hc_data_t ** pdata)
.parse = (HC_PARSE)hc_route_parse,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, pdata);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
+}
+
+int
+hc_route_list(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_route_list(s, pdata, false);
+}
+
+int
+hc_route_list_async(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_route_list(s, pdata, true);
}
/* ROUTE PARSE */
@@ -1346,11 +1651,11 @@ hc_route_parse(void * in, hc_route_t * route)
list_routes_command * cmd = (list_routes_command *) in;
if (!IS_VALID_ADDR_TYPE(cmd->addressType))
- return LIBHICNCTRL_FAILURE;
+ return -1;
int family = map_from_addr_type[cmd->addressType];
if (!IS_VALID_FAMILY(family))
- return LIBHICNCTRL_FAILURE;
+ return -1;
*route = (hc_route_t) {
.face_id = cmd->connid,
@@ -1359,7 +1664,7 @@ hc_route_parse(void * in, hc_route_t * route)
.len = cmd->len,
.cost = cmd->cost,
};
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/* ROUTE SNPRINTF */
@@ -1416,9 +1721,9 @@ hc_face_to_listener(const hc_face_t * face, hc_listener_t * listener)
case FACE_TYPE_UDP_LISTENER:
break;
default:
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
- return LIBHICNCTRL_FAILURE; /* XXX Not implemented */
+ return -1; /* XXX Not implemented */
}
/* LISTENER -> FACE */
@@ -1426,7 +1731,7 @@ hc_face_to_listener(const hc_face_t * face, hc_listener_t * listener)
int
hc_listener_to_face(const hc_listener_t * listener, hc_face_t * face)
{
- return LIBHICNCTRL_FAILURE; /* XXX Not implemented */
+ return -1; /* XXX Not implemented */
}
/* FACE -> CONNECTION */
@@ -1451,7 +1756,7 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool
.tags = f->tags,
#endif /* WITH_POLICY */
};
- snprintf(connection->name, NAME_LEN, "%s",
+ snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s",
f->netdevice.name);
snprintf(connection->interface_name, INTERFACE_LEN, "%s",
f->netdevice.name);
@@ -1471,9 +1776,9 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool
#endif /* WITH_POLICY */
};
if (generate_name) {
- snprintf(connection->name, NAME_LEN, "tcp%u", RANDBYTE());
+ snprintf(connection->name, SYMBOLIC_NAME_LEN, "tcp%u", RANDBYTE());
} else {
- memset(connection->name, 0, NAME_LEN);
+ memset(connection->name, 0, SYMBOLIC_NAME_LEN);
}
snprintf(connection->interface_name, INTERFACE_LEN, "%s",
f->netdevice.name);
@@ -1493,21 +1798,21 @@ hc_face_to_connection(const hc_face_t * face, hc_connection_t * connection, bool
#endif /* WITH_POLICY */
};
if (generate_name) {
- snprintf(connection->name, NAME_LEN, "udp%u", RANDBYTE());
+ snprintf(connection->name, SYMBOLIC_NAME_LEN, "udp%u", RANDBYTE());
} else {
- memset(connection->name, 0, NAME_LEN);
+ memset(connection->name, 0, SYMBOLIC_NAME_LEN);
}
snprintf(connection->interface_name, INTERFACE_LEN, "%s",
f->netdevice.name);
break;
default:
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
snprintf(connection->interface_name, INTERFACE_LEN, "%s",
f->netdevice.name);
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/* CONNECTION -> FACE */
@@ -1570,14 +1875,14 @@ hc_connection_to_face(const hc_connection_t * connection, hc_face_t * face)
};
break;
default:
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
face->face.netdevice.name[0] = '\0';
face->face.netdevice.index = 0;
- snprintf(face->name, NAME_LEN, "%s", connection->name);
+ snprintf(face->name, SYMBOLIC_NAME_LEN, "%s", connection->name);
snprintf(face->face.netdevice.name, INTERFACE_LEN, "%s", connection->interface_name);
netdevice_update_index(&face->face.netdevice);
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/* CONNECTION -> LISTENER */
@@ -1592,9 +1897,9 @@ hc_connection_to_local_listener(const hc_connection_t * connection, hc_listener_
.local_addr = connection->local_addr,
.local_port = connection->local_port,
};
- snprintf(listener->name, NAME_LEN, "lst%u", RANDBYTE()); // generate name
+ snprintf(listener->name, SYMBOLIC_NAME_LEN, "lst%u", RANDBYTE()); // generate name
snprintf(listener->interface_name, INTERFACE_LEN, "%s", connection->interface_name);
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/* FACE CREATE */
@@ -1615,18 +1920,18 @@ hc_face_create(hc_sock_t * s, hc_face_t * face)
case FACE_TYPE_UDP:
if (hc_face_to_connection(face, &connection, true) < 0) {
ERROR("[hc_face_create] Could not convert face to connection.");
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
/* Ensure we have a corresponding local listener */
if (hc_connection_to_local_listener(&connection, &listener) < 0) {
ERROR("[hc_face_create] Could not convert face to local listener.");
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
if (hc_listener_get(s, &listener, &listener_found) < 0) {
ERROR("[hc_face_create] Could not retrieve listener");
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
if (!listener_found) {
@@ -1634,7 +1939,7 @@ hc_face_create(hc_sock_t * s, hc_face_t * face)
if (hc_listener_create(s, &listener) < 0) {
ERROR("[hc_face_create] Could not create listener.");
free(listener_found);
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
} else {
free(listener_found);
@@ -1643,7 +1948,7 @@ hc_face_create(hc_sock_t * s, hc_face_t * face)
/* Create corresponding connection */
if (hc_connection_create(s, &connection) < 0) {
ERROR("[hc_face_create] Could not create connection.");
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
/*
@@ -1652,12 +1957,12 @@ hc_face_create(hc_sock_t * s, hc_face_t * face)
*/
if (hc_connection_get(s, &connection, &connection_found) < 0) {
ERROR("[hc_face_create] Could not retrieve connection");
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
if (!connection_found) {
ERROR("[hc_face_create] Could not find newly created connection.");
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
face->id = connection_found->id;
@@ -1670,21 +1975,21 @@ hc_face_create(hc_sock_t * s, hc_face_t * face)
case FACE_TYPE_UDP_LISTENER:
if (hc_face_to_listener(face, &listener) < 0) {
ERROR("Could not convert face to listener.");
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
if (hc_listener_create(s, &listener) < 0) {
ERROR("[hc_face_create] Could not create listener.");
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
- return LIBHICNCTRL_FAILURE;
+ return -1;
break;
default:
ERROR("[hc_face_create] Unknwon face type.");
- return LIBHICNCTRL_FAILURE;
+ return -1;
};
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
int
@@ -1702,12 +2007,12 @@ hc_face_get(hc_sock_t * s, hc_face_t * face, hc_face_t ** face_found)
case FACE_TYPE_TCP:
case FACE_TYPE_UDP:
if (hc_face_to_connection(face, &connection, false) < 0)
- return LIBHICNCTRL_FAILURE;
+ return -1;
if (hc_connection_get(s, &connection, &connection_found) < 0)
- return LIBHICNCTRL_FAILURE;
+ return -1;
if (!connection_found) {
*face_found = NULL;
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
*face_found = malloc(sizeof(face_t));
hc_connection_to_face(connection_found, *face_found);
@@ -1718,12 +2023,12 @@ hc_face_get(hc_sock_t * s, hc_face_t * face, hc_face_t ** face_found)
case FACE_TYPE_TCP_LISTENER:
case FACE_TYPE_UDP_LISTENER:
if (hc_face_to_listener(face, &listener) < 0)
- return LIBHICNCTRL_FAILURE;
+ return -1;
if (hc_listener_get(s, &listener, &listener_found) < 0)
- return LIBHICNCTRL_FAILURE;
+ return -1;
if (!listener_found) {
*face_found = NULL;
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
*face_found = malloc(sizeof(face_t));
hc_listener_to_face(listener_found, *face_found);
@@ -1731,10 +2036,10 @@ hc_face_get(hc_sock_t * s, hc_face_t * face, hc_face_t ** face_found)
break;
default:
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
@@ -1743,13 +2048,64 @@ hc_face_get(hc_sock_t * s, hc_face_t * face, hc_face_t ** face_found)
int
hc_face_delete(hc_sock_t * s, hc_face_t * face)
{
- /* XXX We currently do not delete the listener */
hc_connection_t connection;
if (hc_face_to_connection(face, &connection, false) < 0) {
ERROR("[hc_face_delete] Could not convert face to connection.");
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
- return hc_connection_delete(s, &connection);
+
+ if (hc_connection_delete(s, &connection) < 0) {
+ ERROR("[hc_face_delete] Error removing connection");
+ return -1;
+ }
+
+ /* If this is the last connection attached to the listener, remove it */
+
+ hc_data_t * connections;
+ hc_listener_t listener = {{0}};
+
+ /*
+ * Ensure we have a corresponding local listener
+ * NOTE: hc_face_to_listener is not appropriate
+ */
+ if (hc_connection_to_local_listener(&connection, &listener) < 0) {
+ ERROR("[hc_face_create] Could not convert face to local listener.");
+ return -1;
+ }
+#if 1
+ /*
+ * The name is generated to prepare listener creation, we need it to be
+ * empty for deletion. The id should not need to be reset though.
+ */
+ listener.id = 0;
+ memset(listener.name, 0, sizeof(listener.name));
+#endif
+ if (hc_connection_list(s, &connections) < 0) {
+ ERROR("[hc_face_delete] Error getting the list of listeners");
+ return -1;
+ }
+
+ bool delete = true;
+ foreach_connection(c, connections) {
+ if ((ip_address_cmp(&c->local_addr, &listener.local_addr, c->family) == 0) &&
+ (c->local_port == listener.local_port) &&
+ (strcmp(c->interface_name, listener.interface_name) == 0)) {
+ delete = false;
+ }
+ }
+
+ if (delete) {
+ if (hc_listener_delete(s, &listener) < 0) {
+ ERROR("[hc_face_delete] Error removing listener");
+ return -1;
+ }
+ }
+
+ hc_data_free(connections);
+
+ return 0;
+
+
}
/* FACE LIST */
@@ -1762,7 +2118,7 @@ hc_face_list(hc_sock_t * s, hc_data_t ** pdata)
if (hc_connection_list(s, &connection_data) < 0) {
ERROR("[hc_face_list] Could not list connections.");
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
hc_data_t * face_data = hc_data_create(sizeof(hc_connection_t), sizeof(hc_face_t));
@@ -1776,11 +2132,55 @@ hc_face_list(hc_sock_t * s, hc_data_t ** pdata)
*pdata = face_data;
hc_data_free(connection_data);
- return LIBHICNCTRL_SUCCESS;
+ return 0;
ERR:
hc_data_free(connection_data);
- return LIBHICNCTRL_FAILURE;
+ return -1;
+}
+
+int
+hc_connection_parse_to_face(void * in, hc_face_t * face)
+{
+ hc_connection_t connection;
+
+ if (hc_connection_parse(in, &connection) < 0) {
+ ERROR("[hc_connection_parse_to_face] Could not parse connection");
+ return -1;
+ }
+
+ if (hc_connection_to_face(&connection, face) < 0) {
+ ERROR("[hc_connection_parse_to_face] Could not convert connection to face.");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+hc_face_list_async(hc_sock_t * s) //, hc_data_t ** pdata)
+{
+ struct {
+ header_control_message hdr;
+ } msg = {
+ .hdr = {
+ .messageType = REQUEST_LIGHT,
+ .commandID = LIST_CONNECTIONS,
+ .length = 0,
+ .seqNum = 0,
+ },
+ };
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = LIST_CONNECTIONS,
+ .size_in = sizeof(list_connections_command),
+ .size_out = sizeof(hc_face_t),
+ .parse = (HC_PARSE)hc_connection_parse_to_face,
+ };
+
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, true);
}
/* /!\ Please update constants in header file upon changes */
@@ -1824,7 +2224,7 @@ hc_face_snprintf(char * s, size_t size, hc_face_t * face)
return rc;
break;
default:
- return LIBHICNCTRL_FAILURE;
+ return -1;
}
// [#ID NAME] TYPE LOCAL_URL REMOTE_URL STATE/ADMIN_STATE (TAGS)
@@ -1852,7 +2252,7 @@ hc_face_snprintf(char * s, size_t size, hc_face_t * face)
face_state_str[face->face.state],
face_state_str[face->face.admin_state]);
#endif /* WITH_POLICY */
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
int
@@ -1866,10 +2266,11 @@ hc_face_set_admin_state(hc_sock_t * s, const char * conn_id_or_name, // XXX wron
* Punting
*----------------------------------------------------------------------------*/
-int hc_punting_create(hc_sock_t * s, hc_punting_t * punting)
+int
+_hc_punting_create(hc_sock_t * s, hc_punting_t * punting, bool async)
{
if (hc_punting_validate(punting) < 0)
- return LIBHICNCTRL_FAILURE;
+ return -1;
struct {
header_control_message hdr;
@@ -1879,7 +2280,7 @@ int hc_punting_create(hc_sock_t * s, hc_punting_t * punting)
.messageType = REQUEST_LIGHT,
.commandID = ADD_PUNTING,
.length = 1,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
.payload = {
/* we use IPv6 which is the longest address */
@@ -1888,7 +2289,7 @@ int hc_punting_create(hc_sock_t * s, hc_punting_t * punting)
.len = punting->prefix_len,
}
};
- snprintf(msg.payload.symbolicOrConnid, NAME_LEN, "%d", punting->face_id);
+ snprintf(msg.payload.symbolicOrConnid, SYMBOLIC_NAME_LEN, "%d", punting->face_id);
hc_command_params_t params = {
.cmd = ACTION_CREATE,
@@ -1898,37 +2299,54 @@ int hc_punting_create(hc_sock_t * s, hc_punting_t * punting)
.parse = NULL,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+int
+hc_punting_create(hc_sock_t * s, hc_punting_t * punting)
+{
+ return _hc_punting_create(s, punting, false);
+}
+
+int
+hc_punting_create_async(hc_sock_t * s, hc_punting_t * punting)
+{
+ return _hc_punting_create(s, punting, true);
}
int hc_punting_get(hc_sock_t * s, hc_punting_t * punting, hc_punting_t ** punting_found)
{
- return LIBHICNCTRL_NOT_IMPLEMENTED;
+ ERROR("hc_punting_get not (yet) implemented.");
+ return -1;
}
int hc_punting_delete(hc_sock_t * s, hc_punting_t * punting)
{
- return LIBHICNCTRL_NOT_IMPLEMENTED;
+ ERROR("hc_punting_delete not (yet) implemented.");
+ return -1;
}
int hc_punting_list(hc_sock_t * s, hc_data_t ** pdata)
{
- return LIBHICNCTRL_NOT_IMPLEMENTED;
+ ERROR("hc_punting_list not (yet) implemented.");
+ return -1;
}
int hc_punting_validate(const hc_punting_t * punting)
{
if (!IS_VALID_FAMILY(punting->family))
- return LIBHICNCTRL_FAILURE;
+ return -1;
/*
* We might use the zero value to add punting on all faces but this is not
* (yet) implemented
*/
- if (punting->face_id == 0)
- return LIBHICNCTRL_NOT_IMPLEMENTED;
+ if (punting->face_id == 0) {
+ ERROR("Punting on all faces is not (yet) implemented.");
+ return -1;
+ }
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
int hc_punting_cmp(const hc_punting_t * p1, const hc_punting_t * p2)
@@ -1937,18 +2355,20 @@ int hc_punting_cmp(const hc_punting_t * p1, const hc_punting_t * p2)
(p1->family == p2->family) &&
(ip_address_cmp(&p1->prefix, &p2->prefix, p1->family) == 0) &&
(p1->prefix_len == p2->prefix_len))
- ? LIBHICNCTRL_SUCCESS
- : LIBHICNCTRL_FAILURE;
+ ? 0
+ : -1;
}
int hc_punting_parse(void * in, hc_punting_t * punting)
{
- return LIBHICNCTRL_NOT_IMPLEMENTED;
+ ERROR("hc_punting_parse not (yet) implemented.");
+ return -1;
}
int hc_punting_snprintf(char * s, size_t size, hc_punting_t * punting)
{
- return LIBHICNCTRL_NOT_IMPLEMENTED;
+ ERROR("hc_punting_snprintf not (yet) implemented.");
+ return -1;
}
@@ -1957,7 +2377,7 @@ int hc_punting_snprintf(char * s, size_t size, hc_punting_t * punting)
*----------------------------------------------------------------------------*/
int
-hc_cache_set_store(hc_sock_t * s, int enabled)
+_hc_cache_set_store(hc_sock_t * s, int enabled, bool async)
{
struct {
header_control_message hdr;
@@ -1967,7 +2387,7 @@ hc_cache_set_store(hc_sock_t * s, int enabled)
.messageType = REQUEST_LIGHT,
.commandID = CACHE_STORE,
.length = 1,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
.payload = {
.activate = enabled,
@@ -1982,11 +2402,23 @@ hc_cache_set_store(hc_sock_t * s, int enabled)
.parse = NULL,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
}
int
-hc_cache_set_serve(hc_sock_t * s, int enabled)
+hc_cache_set_store(hc_sock_t * s, int enabled)
+{
+ return _hc_cache_set_store(s, enabled, false);
+}
+
+int
+hc_cache_set_store_async(hc_sock_t * s, int enabled)
+{
+ return _hc_cache_set_store(s, enabled, true);
+}
+
+int
+_hc_cache_set_serve(hc_sock_t * s, int enabled, bool async)
{
struct {
header_control_message hdr;
@@ -1996,7 +2428,7 @@ hc_cache_set_serve(hc_sock_t * s, int enabled)
.messageType = REQUEST_LIGHT,
.commandID = CACHE_SERVE,
.length = 1,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
.payload = {
.activate = enabled,
@@ -2011,9 +2443,20 @@ hc_cache_set_serve(hc_sock_t * s, int enabled)
.parse = NULL,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
}
+int
+hc_cache_set_serve(hc_sock_t * s, int enabled)
+{
+ return _hc_cache_set_serve(s, enabled, false);
+}
+
+int
+hc_cache_set_serve_async(hc_sock_t * s, int enabled)
+{
+ return _hc_cache_set_serve(s, enabled, true);
+}
/*----------------------------------------------------------------------------*
* Strategy
@@ -2023,7 +2466,7 @@ hc_cache_set_serve(hc_sock_t * s, int enabled)
int
hc_strategy_set(hc_sock_t * s /* XXX */)
{
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/* How to retrieve that from the forwarder ? */
@@ -2042,12 +2485,12 @@ hc_strategy_list(hc_sock_t * s, hc_data_t ** data)
for (unsigned i = 0; i < ARRAY_SIZE(strategies); i++) {
hc_strategy_t * strategy = (hc_strategy_t*)hc_data_get_next(*data);
if (!strategy)
- return LIBHICNCTRL_FAILURE;
+ return -1;
snprintf(strategy->name, MAXSZ_HC_STRATEGY, "%s", strategies[i]);
(*data)->size++;
}
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/* /!\ Please update constants in header file upon changes */
@@ -2065,7 +2508,7 @@ hc_strategy_snprintf(char * s, size_t size, hc_strategy_t * strategy)
int
hc_wldr_set(hc_sock_t * s /* XXX */)
{
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/*----------------------------------------------------------------------------*
@@ -2075,25 +2518,25 @@ hc_wldr_set(hc_sock_t * s /* XXX */)
int
hc_mapme_set(hc_sock_t * s, int enabled)
{
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
int
hc_mapme_set_discovery(hc_sock_t * s, int enabled)
{
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
int
hc_mapme_set_timescale(hc_sock_t * s, double timescale)
{
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
int
hc_mapme_set_retx(hc_sock_t * s, double timescale)
{
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/*----------------------------------------------------------------------------*
@@ -2105,10 +2548,10 @@ hc_mapme_set_retx(hc_sock_t * s, double timescale)
/* POLICY CREATE */
int
-hc_policy_create(hc_sock_t * s, hc_policy_t * policy)
+_hc_policy_create(hc_sock_t * s, hc_policy_t * policy, bool async)
{
if (!IS_VALID_FAMILY(policy->family))
- return LIBHICNCTRL_FAILURE;
+ return -1;
struct {
header_control_message hdr;
@@ -2118,7 +2561,7 @@ hc_policy_create(hc_sock_t * s, hc_policy_t * policy)
.messageType = REQUEST_LIGHT,
.commandID = ADD_POLICY,
.length = 1,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
.payload = {
/* we use IPv6 which is the longest address */
@@ -2137,16 +2580,28 @@ hc_policy_create(hc_sock_t * s, hc_policy_t * policy)
.parse = NULL,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+int
+hc_policy_create(hc_sock_t * s, hc_policy_t * policy)
+{
+ return _hc_policy_create(s, policy, false);
+}
+
+int
+hc_policy_create_async(hc_sock_t * s, hc_policy_t * policy)
+{
+ return _hc_policy_create(s, policy, true);
}
/* POLICY DELETE */
int
-hc_policy_delete(hc_sock_t * s, hc_policy_t * policy)
+_hc_policy_delete(hc_sock_t * s, hc_policy_t * policy, bool async)
{
if (!IS_VALID_FAMILY(policy->family))
- return LIBHICNCTRL_FAILURE;
+ return -1;
struct {
header_control_message hdr;
@@ -2156,7 +2611,7 @@ hc_policy_delete(hc_sock_t * s, hc_policy_t * policy)
.messageType = REQUEST_LIGHT,
.commandID = REMOVE_POLICY,
.length = 1,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
.payload = {
/* we use IPv6 which is the longest address */
@@ -2174,13 +2629,25 @@ hc_policy_delete(hc_sock_t * s, hc_policy_t * policy)
.parse = NULL,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, NULL, async);
+}
+
+int
+hc_policy_delete(hc_sock_t * s, hc_policy_t * policy)
+{
+ return _hc_policy_delete(s, policy, false);
+}
+
+int
+hc_policy_delete_async(hc_sock_t * s, hc_policy_t * policy)
+{
+ return _hc_policy_delete(s, policy, true);
}
/* POLICY LIST */
int
-hc_policy_list(hc_sock_t * s, hc_data_t ** pdata)
+_hc_policy_list(hc_sock_t * s, hc_data_t ** pdata, bool async)
{
struct {
header_control_message hdr;
@@ -2189,7 +2656,7 @@ hc_policy_list(hc_sock_t * s, hc_data_t ** pdata)
.messageType = REQUEST_LIGHT,
.commandID = LIST_POLICIES,
.length = 0,
- .seqNum = s->send_seq,
+ .seqNum = 0,
},
};
@@ -2201,7 +2668,19 @@ hc_policy_list(hc_sock_t * s, hc_data_t ** pdata)
.parse = (HC_PARSE)hc_policy_parse,
};
- return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, pdata);
+ return hc_execute_command(s, (hc_msg_t*)&msg, sizeof(msg), &params, pdata, async);
+}
+
+int
+hc_policy_list(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_policy_list(s, pdata, false);
+}
+
+int
+hc_policy_list_async(hc_sock_t * s, hc_data_t ** pdata)
+{
+ return _hc_policy_list(s, pdata, true);
}
/* POLICY PARSE */
@@ -2212,11 +2691,11 @@ hc_policy_parse(void * in, hc_policy_t * policy)
list_policies_command * cmd = (list_policies_command *) in;
if (!IS_VALID_ADDR_TYPE(cmd->addressType))
- return LIBHICNCTRL_FAILURE;
+ return -1;
int family = map_from_addr_type[cmd->addressType];
if (!IS_VALID_FAMILY(family))
- return LIBHICNCTRL_FAILURE;
+ return -1;
*policy = (hc_policy_t) {
.family = family,
@@ -2224,7 +2703,7 @@ hc_policy_parse(void * in, hc_policy_t * policy)
.len = cmd->len,
.policy = cmd->policy,
};
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
/* POLICY SNPRINTF */
@@ -2233,7 +2712,7 @@ hc_policy_parse(void * in, hc_policy_t * policy)
int
hc_policy_snprintf(char * s, size_t size, hc_policy_t * policy)
{
- return LIBHICNCTRL_SUCCESS;
+ return 0;
}
#endif /* WITH_POLICY */
diff --git a/ctrl/libhicnctrl/src/cli.c b/ctrl/libhicnctrl/src/cli.c
index 6798b5aec..81400f8ee 100644
--- a/ctrl/libhicnctrl/src/cli.c
+++ b/ctrl/libhicnctrl/src/cli.c
@@ -17,6 +17,7 @@
* \file cli.c
* \brief Command line interface
*/
+#include <ctype.h> // isalpha isalnum
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h> // getopt
@@ -34,10 +35,11 @@
#define foreach_object \
_(UNDEFINED) \
- _(LISTENER) \
- _(CONNECTION) \
+ _(FACE) \
_(ROUTE) \
_(STRATEGY) \
+ _(LISTENER) \
+ _(CONNECTION) \
_(N)
typedef enum {
@@ -48,7 +50,26 @@ foreach_object
void usage(const char * prog)
{
- fprintf(stderr, "Usage: %s [ [-d] [-l|-c|-r] PARAMETERS | [-L|-C|-R] ]\n", prog);
+ fprintf(stderr, "Usage: %s [ [-d] [-f|-l|-c|-r] PARAMETERS | [-F|-L|-C|-R] ]\n", prog);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "High-level commands\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "%s -f <NAME> <TYPE> <LOCAL_ADDRESS> <LOCAL_PORT> <REMOTE_ADDRESS> <REMOTE_PORT>\n", prog);
+ fprintf(stderr, " Create a face on specified address and port.\n");
+ fprintf(stderr, "%s -fc ...\n", prog);
+ fprintf(stderr, " Delete a face...\n");
+ fprintf(stderr, "%s -F\n", prog);
+ fprintf(stderr, " List all faces.\n");
+ fprintf(stderr, "%s -r ...>\n", prog);
+ fprintf(stderr, " Create a route...\n");
+ fprintf(stderr, "%s -dr ...\n", prog);
+ fprintf(stderr, " Delete a route...\n");
+ fprintf(stderr, "%s -R\n", prog);
+ fprintf(stderr, " List all routes.\n");
+ fprintf(stderr, "%s -S\n", prog);
+ fprintf(stderr, " List all availble forwarding strategies.\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Low level commands (hicn-light specific)\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s -l <NAME> <TYPE> <ADDRESS> <PORT> <INTERFACE_NAME>\n", prog);
fprintf(stderr, " Create a listener on specified address and port.\n");
@@ -56,73 +77,122 @@ void usage(const char * prog)
fprintf(stderr, " Delete a listener...\n");
fprintf(stderr, "%s -L\n", prog);
fprintf(stderr, " List all listeners.\n");
- fprintf(stderr, "%s -c <TYPE> <LOCAL_ADDRESS> <LOCAL_PORT> <REMOTE_ADDRESS> <REMOTE_PORT>\n", prog);
+ fprintf(stderr, "%s -c <NAME> <TYPE> <LOCAL_ADDRESS> <LOCAL_PORT> <REMOTE_ADDRESS> <REMOTE_PORT>\n", prog);
fprintf(stderr, " Create a connection on specified address and port.\n");
fprintf(stderr, "%s -dc ...\n", prog);
fprintf(stderr, " Delete a connection...\n");
fprintf(stderr, "%s -C\n", prog);
fprintf(stderr, " List all connections.\n");
- fprintf(stderr, "%s -r ...>\n", prog);
- fprintf(stderr, " Create a route...\n");
- fprintf(stderr, "%s -dr ...\n", prog);
- fprintf(stderr, " Delete a route...\n");
- fprintf(stderr, "%s -R\n", prog);
- fprintf(stderr, " List all routes.\n");
- fprintf(stderr, "%s -S\n", prog);
- fprintf(stderr, " List all availble forwarding strategies.\n");
}
typedef struct {
hc_action_t action;
hc_object_t object;
union {
+ hc_face_t face;
+ hc_route_t route;
hc_connection_t connection;
hc_listener_t listener;
- hc_route_t route;
};
} hc_command_t;
+/**
+ * Return true if string is purely an integer
+ */
+static inline
+bool
+is_number(const char *string) {
+ size_t len = strlen(string);
+ for (size_t i = 0; i < len; i++)
+ if (!isdigit(string[i]))
+ return false;
+ return true;
+}
+
+/**
+ * A symbolic name must be at least 1 character and must begin with an alpha.
+ * The remainder must be an alphanum.
+ */
+static inline
+bool
+is_symbolic_name(const char *name)
+{
+ size_t len = strlen(name);
+ if (len <= 0)
+ return false;
+ if (!isalpha(name[0]))
+ return false;
+ for (size_t i = 1; i < len; i++) {
+ if (!isalnum(name[i]))
+ return false;
+ }
+ return true;
+}
+
+face_type_t
+face_type_from_str(const char * str)
+{
+#define _(x) \
+ if (strcasecmp(str, STRINGIZE(x)) == 0) \
+ return FACE_TYPE_ ## x; \
+ else
+foreach_face_type
+#undef _
+ return FACE_TYPE_UNDEFINED;
+}
+
+
int
parse_options(int argc, char *argv[], hc_command_t * command)
{
command->object = OBJECT_UNDEFINED;
command->action = ACTION_CREATE;
- int nargs = 0; /* default for list */
+ int nargs = -1; /* unset */
int opt;
int family;
- while ((opt = getopt(argc, argv, "dlcrLCRSh")) != -1) {
+ while ((opt = getopt(argc, argv, "dflcrFLCRSh")) != -1) {
switch (opt) {
case 'd':
command->action = ACTION_DELETE;
break;
+ case 'f':
+ command->object = OBJECT_FACE;
+ break;
case 'l':
command->object = OBJECT_LISTENER;
- nargs = 5;
break;
case 'c':
command->object = OBJECT_CONNECTION;
- nargs = 6;
break;
case 'r':
command->object = OBJECT_ROUTE;
nargs = 0; // XXX
break;
+ case 'F':
+ command->action = ACTION_LIST;
+ command->object = OBJECT_FACE;
+ nargs = 0;
+ break;
case 'L':
command->action = ACTION_LIST;
command->object = OBJECT_LISTENER;
+ nargs = 0;
break;
case 'C':
command->action = ACTION_LIST;
command->object = OBJECT_CONNECTION;
+ nargs = 0;
break;
case 'R':
command->action = ACTION_LIST;
command->object = OBJECT_ROUTE;
+ nargs = 0;
break;
case 'S':
command->action = ACTION_LIST;
command->object = OBJECT_STRATEGY;
+ nargs = 0;
break;
default: /* "h" */
usage(argv[0]);
@@ -130,25 +200,126 @@ parse_options(int argc, char *argv[], hc_command_t * command)
}
}
- if (command->action == ACTION_DELETE)
- nargs = 1;
-
- /* Each option expects a different number of arguments */
- if ((command->object == OBJECT_UNDEFINED) || (optind != argc - nargs)) {
- //printf("Object requires %d arguments [optind=%d != args=%d - nargs=%d\n", nargs, optind, argc, nargs);
+ if (command->object == OBJECT_UNDEFINED) {
+ fprintf(stderr, "Missing object specification: connection | listener | route\n");
return -1;
}
+
if (nargs == 0)
- return 0;
+ return 0;
/* Parse and validate parameters for add/delete */
switch(command->object) {
+ case OBJECT_FACE:
+ switch(command->action) {
+ case ACTION_CREATE:
+ if ((argc - optind != 6) && (argc - optind != 7)) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "%s -f TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", argv[0]);
+ goto ERR_PARAM;
+ }
+ /* NAME will be autogenerated (and currently not used) */
+ //snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ command->face.face.type = face_type_from_str(argv[optind++]);
+ if (command->face.face.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->face.face.family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->face.face.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->face.face.local_addr) < 0)
+ goto ERR_PARAM;
+ command->face.face.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) || (command->face.face.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->face.face.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->face.face.remote_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ netdevice_set_name(&command->face.face.netdevice, argv[optind++]);
+ }
+
+ break;
+ case ACTION_DELETE:
+ if ((argc - optind != 1) && (argc - optind != 5) && (argc - optind != 6)) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "%s -ld ID\n", argv[0]);
+ //fprintf(stderr, "%s -ld NAME\n", argv[0]);
+ fprintf(stderr, "%s -ld TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", argv[0]);
+ goto ERR_PARAM;
+ }
+
+ if (argc - optind == 1) {
+ /* Id or name */
+ if (is_number(argv[optind])) {
+ command->face.id = atoi(argv[optind++]);
+ snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ //} else if (is_symbolic_name(argv[optind])) {
+ // snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ } else {
+ fprintf(stderr, "Invalid argument\n");
+ goto ERR_PARAM;
+ }
+ } else {
+ command->face.face.type = face_type_from_str(argv[optind++]);
+ if (command->face.face.type == FACE_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->face.face.family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->face.face.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->face.face.local_addr) < 0)
+ goto ERR_PARAM;
+ command->face.face.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) || (command->face.face.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->face.face.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->face.face.remote_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ netdevice_set_name(&command->face.face.netdevice, argv[optind++]);
+ }
+ }
+ break;
+ default:
+ goto ERR_COMMAND;
+ break;
+ }
+ break;
+
+ case OBJECT_ROUTE:
+ switch(command->action) {
+ case ACTION_CREATE:
+ goto ERR_COMMAND;
+ break;
+ case ACTION_DELETE:
+ goto ERR_COMMAND;
+ break;
+ default:
+ goto ERR_COMMAND;
+ break;
+ }
+ break;
+
+ case OBJECT_STRATEGY:
+ switch(command->action) {
+ case ACTION_LIST:
+ break;
+ default:
+ goto ERR_COMMAND;
+ break;
+ }
+ break;
+
case OBJECT_LISTENER:
switch(command->action) {
case ACTION_CREATE:
- /* NAME TYPE LOCAL_ADDRESS LOCAL_PORT */
- snprintf(command->listener.name, NAME_LEN, "%s", argv[optind++]);
- // conn type
+ if ((argc - optind != 4) && (argc - optind != 5)) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "%s -l NAME TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", argv[0]);
+ goto ERR_PARAM;
+ }
+ snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
command->listener.type = connection_type_from_str(argv[optind++]);
if (command->listener.type == CONNECTION_TYPE_UNDEFINED)
goto ERR_PARAM;
@@ -158,23 +329,63 @@ parse_options(int argc, char *argv[], hc_command_t * command)
if (ip_address_pton(argv[optind++], &command->listener.local_addr) < 0)
goto ERR_PARAM;
command->listener.local_port = atoi(argv[optind++]);
-#ifdef __linux__
- snprintf(command->listener.interface_name, INTERFACE_LEN, "%s", argv[optind++]);
-#endif
+ if (argc != optind) {
+ snprintf(command->listener.interface_name, INTERFACE_LEN, "%s", argv[optind++]);
+ }
break;
+
case ACTION_DELETE:
- goto ERR_COMMAND;
+ if ((argc - optind != 1) && (argc - optind != 3) && (argc - optind != 4)) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "%s -ld ID\n", argv[0]);
+ fprintf(stderr, "%s -ld NAME\n", argv[0]);
+ fprintf(stderr, "%s -ld TYPE LOCAL_ADDRESS LOCAL_PORT [INTERFACE_NAME]\n", argv[0]);
+ goto ERR_PARAM;
+ }
+
+ if (argc - optind == 1) {
+ /* Id or name */
+ if (is_number(argv[optind])) {
+ command->listener.id = atoi(argv[optind++]);
+ snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ } else if (is_symbolic_name(argv[optind])) {
+ snprintf(command->listener.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ } else {
+ fprintf(stderr, "Invalid argument\n");
+ goto ERR_PARAM;
+ }
+ } else {
+ command->listener.type = connection_type_from_str(argv[optind++]);
+ if (command->listener.type == CONNECTION_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->listener.family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->listener.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->listener.local_addr) < 0)
+ goto ERR_PARAM;
+ command->listener.local_port = atoi(argv[optind++]);
+ if (argc != optind) {
+ snprintf(command->listener.interface_name, INTERFACE_LEN, "%s", argv[optind++]);
+ }
+ }
break;
+
default:
goto ERR_COMMAND;
break;
}
break;
+
case OBJECT_CONNECTION:
switch(command->action) {
case ACTION_CREATE:
/* NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT */
- snprintf(command->connection.name, NAME_LEN, "%s", argv[optind++]);
+ if ((argc - optind != 6) && (argc - optind != 7)) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "%s -c NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", argv[0]);
+ goto ERR_PARAM;
+ }
+ snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
command->connection.type = connection_type_from_str(argv[optind++]);
if (command->connection.type == CONNECTION_TYPE_UNDEFINED)
goto ERR_PARAM;
@@ -191,45 +402,51 @@ parse_options(int argc, char *argv[], hc_command_t * command)
goto ERR_PARAM;
command->connection.remote_port = atoi(argv[optind++]);
- {
- char buf_connection[MAXSZ_HC_CONNECTION];
- if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION, &command->connection) >= MAXSZ_HC_CONNECTION)
- printf("PARSED !!\n");
- else
- printf("PARSED %s\n", buf_connection);
- }
-
- break;
- case ACTION_DELETE:
- goto ERR_COMMAND;
- break;
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
- case OBJECT_ROUTE:
- switch(command->action) {
- case ACTION_CREATE:
- goto ERR_COMMAND;
break;
case ACTION_DELETE:
- goto ERR_COMMAND;
- break;
- default:
- goto ERR_COMMAND;
- break;
- }
- break;
- case OBJECT_STRATEGY:
- switch(command->action) {
- case ACTION_LIST:
+ if ((argc - optind != 1) && (argc - optind != 5) && (argc - optind != 6)) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "%s -ld ID\n", argv[0]);
+ fprintf(stderr, "%s -ld NAME\n", argv[0]);
+ fprintf(stderr, "%s -ld TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT [INTERFACE_NAME]\n", argv[0]);
+ goto ERR_PARAM;
+ }
+
+ if (argc - optind == 1) {
+ /* Id or name */
+ if (is_number(argv[optind])) {
+ command->connection.id = atoi(argv[optind++]);
+ snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ } else if (is_symbolic_name(argv[optind])) {
+ snprintf(command->connection.name, SYMBOLIC_NAME_LEN, "%s", argv[optind++]);
+ } else {
+ fprintf(stderr, "Invalid argument\n");
+ goto ERR_PARAM;
+ }
+ } else {
+ command->connection.type = connection_type_from_str(argv[optind++]);
+ if (command->connection.type == CONNECTION_TYPE_UNDEFINED)
+ goto ERR_PARAM;
+ command->connection.family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(command->connection.family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->connection.local_addr) < 0)
+ goto ERR_PARAM;
+ command->connection.local_port = atoi(argv[optind++]);
+ family = ip_address_get_family(argv[optind]);
+ if (!IS_VALID_FAMILY(family) || (command->connection.family != family))
+ goto ERR_PARAM;
+ if (ip_address_pton(argv[optind++], &command->connection.remote_addr) < 0)
+ goto ERR_PARAM;
+ command->connection.remote_port = atoi(argv[optind++]);
+ }
break;
default:
goto ERR_COMMAND;
break;
}
break;
+
default:
goto ERR_COMMAND;
break;
@@ -246,7 +463,7 @@ int main(int argc, char *argv[])
{
hc_data_t * data;
int rc = 1;
- hc_command_t command;
+ hc_command_t command = {0};
char buf_listener[MAXSZ_HC_LISTENER];
char buf_connection[MAXSZ_HC_CONNECTION];
char buf_route[MAXSZ_HC_ROUTE];
@@ -263,51 +480,29 @@ int main(int argc, char *argv[])
die(CONNECT, "Error connecting to the forwarder.");
switch(command.object) {
- case OBJECT_LISTENER:
+ case OBJECT_FACE:
switch(command.action) {
case ACTION_CREATE:
- if (hc_listener_create(s, &command.listener) < 0)
- die(COMMAND, "Error creating listener");
+ if (hc_face_create(s, &command.face) < 0)
+ die(COMMAND, "Error creating face");
printf("OK\n");
break;
- case ACTION_DELETE:
- die(COMMAND, "Not implemented.");
- break;
- case ACTION_LIST:
- if (hc_listener_list(s, &data) < 0)
- die(COMMAND, "Error getting listeners.");
- printf("Listeners:\n");
- foreach_listener(l, data) {
- if (hc_listener_snprintf(buf_listener, MAXSZ_HC_LISTENER+17, l) >= MAXSZ_HC_LISTENER)
- die(COMMAND, "Display error");
- printf("[%d] %s\n", l->id, buf_listener);
- }
-
- hc_data_free(data);
- break;
- default:
- die(COMMAND, "Unsupported command for listener");
- break;
- }
- break;
- case OBJECT_CONNECTION:
- switch(command.action) {
- case ACTION_CREATE:
- die(COMMAND, "Not implemented.");
- break;
case ACTION_DELETE:
- die(COMMAND, "Not implemented.");
+ if (hc_face_delete(s, &command.face) < 0)
+ die(COMMAND, "Error creating face");
+ printf("OK\n");
break;
+
case ACTION_LIST:
- if (hc_connection_list(s, &data) < 0)
+ if (hc_face_list(s, &data) < 0)
die(COMMAND, "Error getting connections.");
- printf("Connections:\n");
- foreach_connection(c, data) {
- if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION, c) >= MAXSZ_HC_CONNECTION)
+ printf("Faces:\n");
+ foreach_face(f, data) {
+ if (hc_face_snprintf(buf_connection, MAXSZ_HC_FACE, f) >= MAXSZ_HC_FACE)
die(COMMAND, "Display error");
- printf("[%s] %s\n", c->name, buf_connection);
+ printf("[%s] %s\n", f->name, buf_connection);
}
hc_data_free(data);
@@ -317,6 +512,7 @@ int main(int argc, char *argv[])
break;
}
break;
+
case OBJECT_ROUTE:
switch(command.action) {
case ACTION_CREATE:
@@ -343,6 +539,7 @@ int main(int argc, char *argv[])
break;
}
break;
+
case OBJECT_STRATEGY:
switch(command.action) {
case ACTION_LIST:
@@ -363,6 +560,70 @@ int main(int argc, char *argv[])
break;
}
break;
+
+ case OBJECT_LISTENER:
+ switch(command.action) {
+ case ACTION_CREATE:
+ if (hc_listener_create(s, &command.listener) < 0)
+ die(COMMAND, "Error creating listener");
+ printf("OK\n");
+ break;
+ case ACTION_DELETE:
+ if (hc_listener_delete(s, &command.listener) < 0)
+ die(COMMAND, "Error deleting listener");
+ printf("OK\n");
+ break;
+ break;
+ case ACTION_LIST:
+ if (hc_listener_list(s, &data) < 0)
+ die(COMMAND, "Error getting listeners.");
+
+ printf("Listeners:\n");
+ foreach_listener(l, data) {
+ if (hc_listener_snprintf(buf_listener, MAXSZ_HC_LISTENER+17, l) >= MAXSZ_HC_LISTENER)
+ die(COMMAND, "Display error");
+ printf("[%d] %s\n", l->id, buf_listener);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for listener");
+ break;
+ }
+ break;
+
+ case OBJECT_CONNECTION:
+ switch(command.action) {
+ case ACTION_CREATE:
+ if (hc_connection_create(s, &command.connection) < 0)
+ die(COMMAND, "Error creating connection");
+ printf("OK\n");
+ break;
+ case ACTION_DELETE:
+ if (hc_connection_delete(s, &command.connection) < 0)
+ die(COMMAND, "Error creating connection");
+ printf("OK\n");
+ break;
+ case ACTION_LIST:
+ if (hc_connection_list(s, &data) < 0)
+ die(COMMAND, "Error getting connections.");
+
+ printf("Connections:\n");
+ foreach_connection(c, data) {
+ if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION, c) >= MAXSZ_HC_CONNECTION)
+ die(COMMAND, "Display error");
+ printf("[%s] %s\n", c->name, buf_connection);
+ }
+
+ hc_data_free(data);
+ break;
+ default:
+ die(COMMAND, "Unsupported command for connection");
+ break;
+ }
+ break;
+
default:
die(COMMAND, "Unsupported object");
break;
diff --git a/ctrl/libhicnctrl/src/util/map.h b/ctrl/libhicnctrl/src/util/map.h
new file mode 100644
index 000000000..334f12cc1
--- /dev/null
+++ b/ctrl/libhicnctrl/src/util/map.h
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ */
+
+#ifndef UTIL_MAP_H
+#define UTIL_MAP_H
+
+#include <stdlib.h>
+
+#include "set.h"
+
+#define ERR_MAP_EXISTS -2
+#define ERR_MAP_NOT_FOUND -3
+
+#define TYPEDEF_MAP_H(NAME, KEY_T, VAL_T) \
+ \
+typedef struct { \
+ KEY_T key; \
+ VAL_T value; \
+} NAME ## _pair_t; \
+ \
+NAME ## _pair_t * NAME ## _pair_create(KEY_T key, VAL_T value); \
+ \
+void NAME ## _pair_free(NAME ## _pair_t * pair); \
+ \
+int NAME ## _pair_cmp(const NAME ## _pair_t * p1, const NAME ## _pair_t * p2); \
+ \
+TYPEDEF_SET_H(NAME ## _pair_set, NAME ## _pair_t *) \
+ \
+typedef struct NAME ## _s { \
+ NAME ## _pair_set_t pair_set; \
+} NAME ## _t; \
+ \
+int NAME ## _initialize(NAME ## _t * map); \
+ \
+int NAME ## _finalize(NAME ## _t * map); \
+ \
+NAME ## _t * NAME ## _create(); \
+ \
+void NAME ## _free(NAME ## _t * map); \
+ \
+int NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value); \
+ \
+int NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value); \
+ \
+int NAME ## _get(NAME ## _t * map, KEY_T key, VAL_T * value); \
+ \
+void NAME ## _dump(NAME ## _t * map);
+
+
+
+
+#define TYPEDEF_MAP(NAME, KEY_T, VAL_T, CMP, KEY_SNPRINTF, VALUE_SNPRINTF) \
+ \
+NAME ## _pair_t * NAME ## _pair_create(KEY_T key, VAL_T value) \
+{ \
+ /* Create pair */ \
+ NAME ## _pair_t * pair = malloc(sizeof(NAME ## _pair_t)); \
+ if (!pair) \
+ return NULL; \
+ \
+ pair->key = key; \
+ pair->value = value; \
+ \
+ return pair; \
+} \
+ \
+void NAME ## _pair_free(NAME ## _pair_t * pair) \
+{ \
+ free(pair); \
+} \
+ \
+int \
+NAME ## _pair_cmp(const NAME ## _pair_t * p1, const NAME ## _pair_t * p2) \
+{ \
+ return (CMP(p1->key, p2->key)); \
+} \
+ \
+int \
+NAME ## _pair_snprintf(char * buf, size_t size, const NAME ## _pair_t * pair) { \
+ int rc; \
+ rc = KEY_SNPRINTF(buf, BUFSIZE/2, (KEY_T)pair->key); \
+ if (rc < 0) \
+ return rc; \
+ rc = VALUE_SNPRINTF(buf+rc, BUFSIZE/2, (VAL_T)pair->value); \
+ return rc; \
+} \
+ \
+TYPEDEF_SET(NAME ## _pair_set, NAME ## _pair_t *, NAME ## _pair_cmp, NAME ## _pair_snprintf); \
+ \
+int \
+NAME ## _initialize(NAME ## _t * map) \
+{ \
+ return NAME ## _pair_set_initialize(&map->pair_set); \
+} \
+ \
+int \
+NAME ## _finalize(NAME ## _t * map) \
+{ \
+ return NAME ## _pair_set_finalize(&map->pair_set); \
+} \
+ \
+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) \
+{ \
+ int rc; \
+ NAME ## _pair_t * found = NULL; \
+ \
+ NAME ## _pair_t * pair = NAME ## _pair_create(key, value); \
+ if (!pair) \
+ return -1; \
+ \
+ rc = NAME ## _pair_set_get(&map->pair_set, pair, &found); \
+ 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) { \
+ NAME ## _pair_free(pair); \
+ return -1; \
+ } \
+ return 0; \
+} \
+ \
+int \
+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) \
+ return ERR_MAP_NOT_FOUND; \
+ if (value) \
+ *value = found->value; \
+ NAME ## _pair_free(found); \
+ return 0; \
+} \
+ \
+int \
+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 (found) \
+ *value = found->value; \
+ return 0; \
+} \
+ \
+void \
+NAME ## _dump(NAME ## _t * map) { \
+ NAME ## _pair_set_dump(&map->pair_set); \
+} \
+ \
+int \
+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; \
+ /* Allocate result array */ \
+ *array = malloc(n * sizeof(KEY_T)); \
+ if (!array) { \
+ free(pair_array); \
+ return -1; \
+ } \
+ /* Copy keys */ \
+ for (int i = 0; i < n; i++) \
+ (*array)[i] = pair_array[i]->key; \
+ free(pair_array); \
+ return 0; \
+} \
+ \
+int \
+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; \
+ /* Allocate result array */ \
+ *array = malloc(n * sizeof(VAL_T)); \
+ if (!*array) { \
+ free(pair_array); \
+ return -1; \
+ } \
+ /* Copy values */ \
+ for (int i = 0; i < n; i++) \
+ (*array)[i] = pair_array[i]->value; \
+ free(pair_array); \
+ return 0; \
+}
+
+#endif /* UTIL_MAP_H */
diff --git a/ctrl/libhicnctrl/src/util/set.h b/ctrl/libhicnctrl/src/util/set.h
new file mode 100644
index 000000000..3706e36f4
--- /dev/null
+++ b/ctrl/libhicnctrl/src/util/set.h
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ */
+
+#ifndef UTIL_SET_H
+#define UTIL_SET_H
+
+#include <search.h>
+#include <string.h>
+//#if !defined(__ANDROID__) && !defined(__APPLE__)
+//#include <threads.h>
+//#else
+#define thread_local _Thread_local
+//#endif /* ! __ANDROID__ */
+#include "util/log.h"
+
+#define ERR_SET_EXISTS -2
+#define ERR_SET_NOT_FOUND -3
+
+/* FIXME: buffer overflow when this is too small... investigate */
+#define BUFSIZE 1024
+
+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);
+}
+
+static inline
+int
+string_snprintf(char * buf, size_t size, const char * s) {
+ return snprintf(buf, size, "%s", s);
+}
+
+static inline
+int
+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 { \
+ size_t size; \
+ void * root; \
+} NAME ## _t; \
+ \
+int NAME ## _initialize(NAME ## _t * set); \
+ \
+int NAME ## _finalize(NAME ## _t * set); \
+ \
+NAME ## _t * NAME ## _create(); \
+ \
+void NAME ## _free(NAME ## _t * set); \
+ \
+int NAME ## _add(NAME ## _t * set, const T element); \
+ \
+int NAME ## _remove(NAME ## _t * set, const T search, T * element); \
+ \
+int NAME ## _get(const NAME ## _t * set, const T search, T * element); \
+ \
+int NAME ## _get_array(const NAME ## _t * set, T ** element); \
+ \
+void NAME ## _dump(NAME ## _t * set);
+
+
+
+
+#define TYPEDEF_SET(NAME, T, CMP, SNPRINTF) \
+int \
+NAME ## _initialize(NAME ## _t * set) \
+{ \
+ set->root = NULL; \
+ set->size = 0; \
+ return 0; \
+} \
+ \
+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) \
+{ \
+ void * ptr = tsearch(element, &set->root, (cmp_t)CMP); \
+ if (!ptr) \
+ return -1; \
+ set->size++; \
+ return 0; \
+} \
+ \
+int \
+NAME ## _remove(NAME ## _t * set, const T search, T * element) \
+{ \
+ T * found = tfind(search, &set->root, (cmp_t)CMP); \
+ if (!found) \
+ return ERR_SET_NOT_FOUND; \
+ if (element) \
+ *element = *found; \
+ tdelete(search, &set->root, (cmp_t)CMP); \
+ set->size--; \
+ return 0; \
+} \
+ \
+int \
+NAME ## _get(const NAME ## _t * set, const T search, T * element) \
+{ \
+ T * found = tfind(search, &set->root, (cmp_t)CMP); \
+ if (element) \
+ *element = found ? *found : NULL; \
+ return 0; \
+} \
+ \
+static void \
+NAME ## _dump_node(const void *nodep, const VISIT which, \
+ const int depth) \
+{ \
+ char buf[BUFSIZE]; \
+ switch (which) { \
+ case preorder: \
+ case endorder: \
+ break; \
+ case postorder: \
+ case leaf: \
+ SNPRINTF(buf, BUFSIZE, *(T*)nodep); \
+ INFO("%s", buf); \
+ break; \
+ } \
+} \
+ \
+void \
+NAME ## _dump(NAME ## _t * set) { \
+ twalk(set->root, NAME ## _dump_node); \
+} \
+ \
+thread_local \
+T * NAME ## _array_pos = NULL; \
+ \
+static void \
+NAME ## _add_node_to_array(const void *nodep, const VISIT which, \
+ const int depth) \
+{ \
+ if (!NAME ## _array_pos) \
+ return; \
+ switch (which) { \
+ case preorder: \
+ case endorder: \
+ break; \
+ case postorder: \
+ case leaf: \
+ *NAME ## _array_pos = *(T*)nodep; \
+ NAME ## _array_pos++; \
+ break; \
+ } \
+} \
+ \
+int \
+NAME ## _get_array(const NAME ## _t * set, T ** element) \
+{ \
+ *element = malloc(set->size * sizeof(T)); \
+ if (!*element) \
+ return -1; \
+ NAME ## _array_pos = *element; \
+ twalk(set->root, NAME ## _add_node_to_array); \
+ NAME ## _array_pos = NULL; \
+ return set->size; \
+}
+
+#endif /* UTIL_SET_H */
diff --git a/hicn-light/cmake/Modules/Packaging.cmake b/hicn-light/cmake/Modules/Packaging.cmake
index 006261b03..2b9f4a7b9 100644
--- a/hicn-light/cmake/Modules/Packaging.cmake
+++ b/hicn-light/cmake/Modules/Packaging.cmake
@@ -25,7 +25,22 @@ set(${HICN_LIGHT}_DEB_DEPENDENCIES
CACHE STRING "Dependencies for deb/rpm package."
)
+set(${HICN_LIGHT}_DEB_PACKAGE_CONTROL_EXTRA
+ "${CMAKE_CURRENT_SOURCE_DIR}/config/postinst;${CMAKE_CURRENT_SOURCE_DIR}/config/prerm"
+ CACHE STRING "Control scripts conffiles, postinst, postrm, prerm."
+)
+
set(${HICN_LIGHT}_RPM_DEPENDENCIES
"lib${LIBHICN} >= stable_version, libparc >= 1.0"
CACHE STRING "Dependencies for deb/rpm package."
-) \ No newline at end of file
+)
+
+set(${HICN_LIGHT}_RPM_POST_INSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_SOURCE_DIR}/config/post"
+ CACHE STRING "Install script that will be copied in the %post section"
+)
+
+set(${HICN_LIGHT}_RPM_PRE_UNINSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_SOURCE_DIR}/config/preun"
+ CACHE STRING "Install script that will be copied in the %post section"
+)
diff --git a/hicn-light/config/hicn-light.service b/hicn-light/config/hicn-light.service
index 0f976fc6c..f269b2f26 100644
--- a/hicn-light/config/hicn-light.service
+++ b/hicn-light/config/hicn-light.service
@@ -21,8 +21,8 @@ Environment=LOG_FILE=/tmp/hicn_light.log
Environment=CS_SIZE=1000
Environment=CONFIG=/etc/hicn/hicn_light.conf
# This will overrride the default environment
-EnvironmentFile=-/etc/default/source
-ExecStart=/usr/bin/hicnLightDaemon --port ${PORT} --log-file ${LOG_FILE} --capacity ${CS_SIZE} --config ${CONFIG}
+EnvironmentFile=-/etc/default/hicn-light
+ExecStart=/usr/bin/hicn-light-daemon --port ${PORT} --log-file ${LOG_FILE} --capacity ${CS_SIZE} --config ${CONFIG}
Restart=on-failure
[Install]
diff --git a/hicn-light/config/post b/hicn-light/config/post
new file mode 100755
index 000000000..dced2a093
--- /dev/null
+++ b/hicn-light/config/post
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+systemctl enable hicn-light \ No newline at end of file
diff --git a/hicn-light/config/postinst b/hicn-light/config/postinst
new file mode 100755
index 000000000..dced2a093
--- /dev/null
+++ b/hicn-light/config/postinst
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+systemctl enable hicn-light \ No newline at end of file
diff --git a/hicn-light/config/prerm b/hicn-light/config/prerm
new file mode 100755
index 000000000..4584c7057
--- /dev/null
+++ b/hicn-light/config/prerm
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+systemctl disable hicn-light \ No newline at end of file
diff --git a/hicn-light/config/preun b/hicn-light/config/preun
new file mode 100755
index 000000000..4584c7057
--- /dev/null
+++ b/hicn-light/config/preun
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+systemctl disable hicn-light \ No newline at end of file
diff --git a/hicn-light/src/hicn/config/configuration.c b/hicn-light/src/hicn/config/configuration.c
index 2b63a32a0..4771c4073 100644
--- a/hicn-light/src/hicn/config/configuration.c
+++ b/hicn-light/src/hicn/config/configuration.c
@@ -688,10 +688,10 @@ struct iovec *configuration_ProcessConnectionList(Configuration *config,
listConnectionsCommand->connid = connection_GetConnectionId(original);
const char *connectionName = symbolicNameTable_GetNameByIndex(config->symbolicNameTable, connection_GetConnectionId(original));
- snprintf(listConnectionsCommand->connectionName, 16, "%s", connectionName);
+ snprintf(listConnectionsCommand->connectionName, SYMBOLIC_NAME_LEN, "%s", connectionName);
_strlwr(listConnectionsCommand->connectionName);
- snprintf(listConnectionsCommand->interfaceName, 16, "%s", ioOperations_GetInterfaceName(connection_GetIoOperations(original)));
+ snprintf(listConnectionsCommand->interfaceName, SYMBOLIC_NAME_LEN, "%s", ioOperations_GetInterfaceName(connection_GetIoOperations(original)));
listConnectionsCommand->state =
connection_IsUp(original) ? IFACE_UP : IFACE_DOWN;
@@ -801,11 +801,11 @@ struct iovec *configuration_ProcessListenersList(Configuration *config,
}
const char * listenerName = listenerEntry->getListenerName(listenerEntry);
- snprintf(listListenersCommand->listenerName, 16, "%s", listenerName);
+ snprintf(listListenersCommand->listenerName, SYMBOLIC_NAME_LEN, "%s", listenerName);
if (listenerEntry->getEncapType(listenerEntry) == ENCAP_TCP ||
listenerEntry->getEncapType(listenerEntry) == ENCAP_UDP) {
const char * interfaceName = listenerEntry->getInterfaceName(listenerEntry);
- snprintf(listListenersCommand->interfaceName, 16, "%s", interfaceName);
+ snprintf(listListenersCommand->interfaceName, SYMBOLIC_NAME_LEN, "%s", interfaceName);
}
}
diff --git a/hicn-light/src/hicn/config/configurationListeners.c b/hicn-light/src/hicn/config/configurationListeners.c
index c321007e2..8abbeb781 100644
--- a/hicn-light/src/hicn/config/configurationListeners.c
+++ b/hicn-light/src/hicn/config/configurationListeners.c
@@ -595,11 +595,11 @@ void configurationListeners_SetupAll(const Configuration *config, uint16_t port,
const Address *address = addressListGetItem(addresses, j);
// Do not start on link address
- char listenerName[16];
+ char listenerName[SYMBOLIC_NAME_LEN];
#ifdef __ANDROID__
- snprintf(listenerName, 16, "local_%zu", i);
+ snprintf(listenerName, SYMBOLIC_NAME_LEN, "local_%zu", i);
#else
- snprintf(listenerName, 16, "local_%ld", i);
+ snprintf(listenerName, SYMBOLIC_NAME_LEN, "local_%ld", i);
#endif
if (addressGetType(address) != ADDR_LINK) {
_setupListenersOnAddress(forwarder, listenerName, address, port,
@@ -617,8 +617,8 @@ void configurationListeners_SetutpLocalIPv4(const Configuration *config,
in_addr_t addr = inet_addr("127.0.0.1");
uint16_t network_byte_order_port = htons(port);
- char listenerNameUdp[16] = "lo_udp";
- char listenerNameTcp[16] = "lo_tcp";
+ char listenerNameUdp[SYMBOLIC_NAME_LEN] = "lo_udp";
+ char listenerNameTcp[SYMBOLIC_NAME_LEN] = "lo_tcp";
char *loopback_interface = "lo";
_setupUdpListenerOnInet(forwarder, listenerNameUdp,(ipv4_addr_t *)&(addr),
&network_byte_order_port, loopback_interface);
diff --git a/hicn-light/src/hicn/config/controlAddListener.c b/hicn-light/src/hicn/config/controlAddListener.c
index cfd061131..1a94ff252 100644
--- a/hicn-light/src/hicn/config/controlAddListener.c
+++ b/hicn-light/src/hicn/config/controlAddListener.c
@@ -120,7 +120,7 @@ static CommandReturn _CreateListener(CommandParser *parser, CommandOps *ops,
}
// Fill remaining payload fields
- memcpy(addListenerCommand->interfaceName, interfaceName, 16);
+ memcpy(addListenerCommand->interfaceName, interfaceName, SYMBOLIC_NAME_LEN);
addListenerCommand->listenerMode = mode;
addListenerCommand->connectionType = type;
addListenerCommand->port = htons((uint16_t)atoi(port));
diff --git a/hicn-light/src/hicn/config/controlListListeners.c b/hicn-light/src/hicn/config/controlListListeners.c
index 5be7b0a9b..1489470a8 100644
--- a/hicn-light/src/hicn/config/controlListListeners.c
+++ b/hicn-light/src/hicn/config/controlListListeners.c
@@ -95,7 +95,7 @@ static CommandReturn _controlListListeners_Execute(CommandParser *parser,
char *addrString = NULL;
if (receivedHeader->length > 0) {
- printf("%6.6s %16s %50.70s %6s %10s\n", "iface", "name", "address", "type", "interface");
+ printf("%6.6s %.*s %50.70s %6s %10s\n", "iface", SYMBOLIC_NAME_LEN, "name", "address", "type", "interface");
} else {
printf(" --- No entry in the list \n");
@@ -114,15 +114,17 @@ static CommandReturn _controlListListeners_Execute(CommandParser *parser,
if (strcmp(listenerType[listListenersCommand->encapType], "UDP") == 0 ||
strcmp(listenerType[listListenersCommand->encapType], "TCP") == 0) {
- parcBufferComposer_Format(composer, "%6u %16s %50.70s %6s %10s",
+ parcBufferComposer_Format(composer, "%6u %.*s %50.70s %6s %10s",
listListenersCommand->connid,
- listListenersCommand->listenerName,addrString,
+ SYMBOLIC_NAME_LEN, listListenersCommand->listenerName,
+ addrString,
listenerType[listListenersCommand->encapType],
listListenersCommand->interfaceName);
} else {
- parcBufferComposer_Format(composer, "%6u %16s %50.70s %6s",
+ parcBufferComposer_Format(composer, "%6u %.*s %50.70s %6s",
listListenersCommand->connid,
- listListenersCommand->listenerName,addrString,
+ SYMBOLIC_NAME_LEN, listListenersCommand->listenerName,
+ addrString,
listenerType[listListenersCommand->encapType]);
}
diff --git a/hicn-light/src/hicn/config/controlRemoveListener.c b/hicn-light/src/hicn/config/controlRemoveListener.c
index 50581a8d9..545e189c0 100644
--- a/hicn-light/src/hicn/config/controlRemoveListener.c
+++ b/hicn-light/src/hicn/config/controlRemoveListener.c
@@ -99,7 +99,7 @@ if (!utils_ValidateSymbolicName(listenerId) &&
parcMemory_AllocateAndClear(sizeof(remove_listener_command));
// fill payload
//removeListenerCommand->listenerId = atoi(listenerId);
- strncpy(removeListenerCommand->symbolicOrListenerid, listenerId, strlen(listenerId));
+ snprintf(removeListenerCommand->symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%s", listenerId);
// send message and receive response
struct iovec *response =
diff --git a/hicn-light/src/hicn/utils/commands.h b/hicn-light/src/hicn/utils/commands.h
index 1a313de6a..60d4cd5fa 100644
--- a/hicn-light/src/hicn/utils/commands.h
+++ b/hicn-light/src/hicn/utils/commands.h
@@ -35,6 +35,8 @@
#include <hicn/policy.h>
#endif /* WITH_POLICY */
+#define SYMBOLIC_NAME_LEN 16
+
typedef struct in6_addr ipv6_addr_t;
typedef uint32_t ipv4_addr_t;
@@ -115,8 +117,8 @@ typedef struct {
typedef enum { ETHER_MODE, IP_MODE, HICN_MODE } listener_mode;
typedef struct {
- char symbolic[16];
- char interfaceName[16];
+ char symbolic[SYMBOLIC_NAME_LEN];
+ char interfaceName[SYMBOLIC_NAME_LEN];
union commandAddr address;
uint16_t port;
// uint16_t etherType;
@@ -130,8 +132,8 @@ typedef struct {
//========== [01] ADD CONNECTION ==========
typedef struct {
- char symbolic[16];
- //char interfaceName[16];
+ char symbolic[SYMBOLIC_NAME_LEN];
+ //char interfaceName[SYMBOLIC_NAME_LEN];
union commandAddr remoteIp;
union commandAddr localIp;
uint16_t remotePort;
@@ -168,8 +170,8 @@ typedef struct {
uint32_t connid;
uint8_t state;
uint8_t admin_state;
- char interfaceName[16];
- char connectionName[16];
+ char interfaceName[SYMBOLIC_NAME_LEN];
+ char connectionName[SYMBOLIC_NAME_LEN];
} list_connections_command;
// SIZE=80
@@ -177,7 +179,7 @@ typedef struct {
//========== [03] ADD ROUTE ==========
typedef struct {
- char symbolicOrConnid[16];
+ char symbolicOrConnid[SYMBOLIC_NAME_LEN];
union commandAddr address;
uint16_t cost;
uint8_t addressType;
@@ -200,12 +202,12 @@ typedef struct {
//========== [05] REMOVE CONNECTION ==========
typedef struct {
- char symbolicOrConnid[16];
+ char symbolicOrConnid[SYMBOLIC_NAME_LEN];
} remove_connection_command;
//========== [06] REMOVE LISTENER ==========
typedef struct {
- char symbolicOrListenerid[16];
+ char symbolicOrListenerid[SYMBOLIC_NAME_LEN];
} remove_listener_command;
// SIZE=16
@@ -213,7 +215,7 @@ typedef struct {
//========== [07] REMOVE ROUTE ==========
typedef struct {
- char symbolicOrConnid[16];
+ char symbolicOrConnid[SYMBOLIC_NAME_LEN];
union commandAddr address;
uint8_t addressType;
uint8_t len;
@@ -259,7 +261,7 @@ typedef struct {
//========== [11] SET WLDR ==========
typedef struct {
- char symbolicOrConnid[16];
+ char symbolicOrConnid[SYMBOLIC_NAME_LEN];
uint8_t activate;
} set_wldr_command;
@@ -268,7 +270,7 @@ typedef struct {
//========== [12] ADD PUNTING ==========
typedef struct {
- char symbolicOrConnid[16];
+ char symbolicOrConnid[SYMBOLIC_NAME_LEN];
union commandAddr address;
uint8_t addressType;
uint8_t len;
@@ -280,8 +282,8 @@ typedef struct {
typedef struct {
union commandAddr address;
- char listenerName[16];
- char interfaceName[16];
+ char listenerName[SYMBOLIC_NAME_LEN];
+ char interfaceName[SYMBOLIC_NAME_LEN];
uint32_t connid;
uint16_t port;
uint8_t addressType;
@@ -307,7 +309,7 @@ typedef struct {
// SIZE=1
typedef struct {
- char symbolicOrConnid[16];
+ char symbolicOrConnid[SYMBOLIC_NAME_LEN];
uint8_t admin_state;
uint16_t pad16;
} connection_set_admin_state_command;
@@ -335,7 +337,7 @@ typedef struct {
} remove_policy_command;
typedef struct {
- char symbolicOrConnid[16];
+ char symbolicOrConnid[SYMBOLIC_NAME_LEN];
uint8_t admin_state;
policy_tags_t tags;
} update_connection_command;
diff --git a/hicn-plugin/README.md b/hicn-plugin/README.md
index 664b9a446..3d332851b 100644
--- a/hicn-plugin/README.md
+++ b/hicn-plugin/README.md
@@ -66,10 +66,11 @@ Build dependencies:
- VPP 19.08
- DEB packages (can be found https://packagecloud.io/fdio/release/install):
+ - vpp
- libvppinfra-dev
- vpp-dev
-Running dependencies:
+Runtime dependencies:
- VPP 19.08
- DEB packages (can be found https://packagecloud.io/fdio/release/install):
diff --git a/lib/src/util/ip_address.c b/lib/src/util/ip_address.c
index 7afd3e2a4..c54b1fae6 100644
--- a/lib/src/util/ip_address.c
+++ b/lib/src/util/ip_address.c
@@ -98,19 +98,18 @@ int
ip_address_pton (const char *ip_address_str, ip_address_t * ip_address)
{
int pton_fd;
- char *addr = strdup (ip_address_str);
int family;
- family = ip_address_get_family (addr);
+ family = ip_address_get_family (ip_address_str);
switch (family)
{
case AF_INET6:
- pton_fd = inet_pton (AF_INET6, addr, &ip_address->buffer);
+ pton_fd = inet_pton (AF_INET6, ip_address_str, &ip_address->buffer);
break;
case AF_INET:
- pton_fd = inet_pton (AF_INET, addr, &ip_address->buffer);
+ pton_fd = inet_pton (AF_INET, ip_address_str, &ip_address->buffer);
break;
default:
goto ERR;
@@ -125,7 +124,6 @@ ip_address_pton (const char *ip_address_str, ip_address_t * ip_address)
return 1;
ERR:
- free (addr);
return -1;
}