aboutsummaryrefslogtreecommitdiffstats
path: root/ctrl
diff options
context:
space:
mode:
authorJordan Augé <jordan.auge@cisco.com>2019-10-30 17:56:08 +0100
committerJordan Augé <jordan.auge@cisco.com>2019-10-31 13:41:47 +0100
commit95170bf3a69597b49238bb7ff396d41f6dc94f30 (patch)
tree2f9b565e84514d7ee25cfd874235dd25e9300a0f /ctrl
parentfc6dfe9f7ee02834ae1e6f56e0aaee36ac3e88dd (diff)
[HICN-369] Implement reconciliation state machine in face manager incl. reattempts in case of errors
Change-Id: Ia4ecf621fbd513d9e29313d2aaa487aa65811183 Signed-off-by: Jordan Augé <jordan.auge@cisco.com>
Diffstat (limited to 'ctrl')
-rw-r--r--ctrl/facemgr/includes/CMakeLists.txt3
-rw-r--r--ctrl/facemgr/includes/facemgr.h3
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/api.h6
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/facelet.h (renamed from ctrl/facemgr/src/facelet.h)20
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/loop.h5
-rw-r--r--ctrl/facemgr/src/CMakeLists.txt1
-rw-r--r--ctrl/facemgr/src/api.c815
-rw-r--r--ctrl/facemgr/src/cfg.c20
-rw-r--r--ctrl/facemgr/src/facelet.c331
-rw-r--r--ctrl/facemgr/src/interface.c16
-rw-r--r--ctrl/facemgr/src/interface.h5
-rw-r--r--ctrl/facemgr/src/interfaces/android_utility/android_utility.c13
-rw-r--r--ctrl/facemgr/src/interfaces/bonjour/bonjour.c8
-rw-r--r--ctrl/facemgr/src/interfaces/dummy/dummy.c10
-rw-r--r--ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c37
-rw-r--r--ctrl/facemgr/src/interfaces/netlink/netlink.c11
-rw-r--r--ctrl/facemgr/src/interfaces/network_framework/network_framework.c1
-rw-r--r--ctrl/facemgr/src/interfaces/updown/updown.c8
-rw-r--r--ctrl/facemgr/src/loop_dispatcher.c6
-rw-r--r--ctrl/facemgr/src/loop_libevent.c42
-rw-r--r--ctrl/facemgr/src/main.c53
-rw-r--r--ctrl/facemgr/src/util/map.h10
-rw-r--r--ctrl/facemgr/src/util/set.h14
-rw-r--r--ctrl/libhicnctrl/src/api.c39
24 files changed, 1014 insertions, 463 deletions
diff --git a/ctrl/facemgr/includes/CMakeLists.txt b/ctrl/facemgr/includes/CMakeLists.txt
index e7265eebb..eaf8b88a0 100644
--- a/ctrl/facemgr/includes/CMakeLists.txt
+++ b/ctrl/facemgr/includes/CMakeLists.txt
@@ -25,6 +25,7 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/api.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/cfg.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/facelet.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
@@ -37,6 +38,8 @@ else ()
${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/facelet.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/facemgr/loop.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/log.h
PARENT_SCOPE
)
diff --git a/ctrl/facemgr/includes/facemgr.h b/ctrl/facemgr/includes/facemgr.h
index b322e7b1f..b3b482ccc 100644
--- a/ctrl/facemgr/includes/facemgr.h
+++ b/ctrl/facemgr/includes/facemgr.h
@@ -20,9 +20,10 @@
#ifndef HICN_FACEMGR_H
#define HICN_FACEMGR_H
-#include <hicn/policy.h>
#include <hicn/facemgr/api.h>
#include <hicn/facemgr/cfg.h>
+#include <hicn/facemgr/facelet.h>
+#include <hicn/facemgr/loop.h>
#endif /* HICN_FACEMGR_H */
diff --git a/ctrl/facemgr/includes/hicn/facemgr/api.h b/ctrl/facemgr/includes/hicn/facemgr/api.h
index e6151da11..fcc31eb37 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/api.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/api.h
@@ -21,6 +21,7 @@
#define FACEMGR_H
#include <hicn/facemgr/cfg.h>
+#include <hicn/facemgr/facelet.h>
#include <hicn/util/ip_address.h>
#ifdef __ANDROID__
#include <hicn/android_utility/android_utility.h>
@@ -86,8 +87,9 @@ int facemgr_bootstrap(facemgr_t * facemgr);
void facemgr_set_jvm(facemgr_t * facemgr, JavaVM *jvm);
#endif /* __ANDROID__ */
-typedef int (*facemgr_list_faces_cb_t)(face_t * face, void * user_data);
+typedef int (*facemgr_list_facelets_cb_t)(const facemgr_t * facemgr, const facelet_t * facelet, void * user_data);
-void facemgr_list_faces(facemgr_t * facemgr, facemgr_list_faces_cb_t cb, void * user_data);
+void facemgr_list_facelets(const facemgr_t * facemgr, facemgr_list_facelets_cb_t cb, void * user_data);
+int facemgr_list_facelets_json(const facemgr_t * facemgr, char ** buffer);
#endif /* FACEMGR_H */
diff --git a/ctrl/facemgr/src/facelet.h b/ctrl/facemgr/includes/hicn/facemgr/facelet.h
index 16c23b12e..7fc2745f1 100644
--- a/ctrl/facemgr/src/facelet.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/facelet.h
@@ -29,7 +29,7 @@
#include <stdbool.h>
#include <hicn/ctrl/face.h>
-#include <hicn/facemgr.h>
+#include <hicn/facemgr/cfg.h>
#define MAXSZ_FACELET 1024
@@ -41,13 +41,14 @@ typedef struct facelet_s facelet_t;
/* Facelet status */
#define foreach_facelet_status \
_(UNDEFINED) \
- _(NEW) \
+ _(UNCERTAIN) \
+ _(INCOMPLETE) \
+ _(CREATE) \
_(CLEAN) \
- _(DIRTY) \
- _(CONFLICT) \
- _(DELETED) \
_(IGNORED) \
- _(ERROR) \
+ _(UPDATE) \
+ _(DELETE) \
+ _(DELETED) \
_(N)
typedef enum {
@@ -172,6 +173,9 @@ 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);
+void facelet_set_status_error(facelet_t * facelet, bool value);
+bool facelet_get_status_error(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);
@@ -181,7 +185,7 @@ 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);
-int facelet_snprintf(char * buf, size_t size, facelet_t * facelet);
+int facelet_snprintf(char * buf, size_t size, const facelet_t * facelet);
#define DUMP_FACELET(msg, facelet) do { \
char buf[MAXSZ_FACELET]; \
@@ -189,4 +193,6 @@ int facelet_snprintf(char * buf, size_t size, facelet_t * facelet);
DEBUG("%s : %s", msg, buf); \
} while(0)
+int facelet_snprintf_json(char * buf, size_t size, const facelet_t * facelet, int indent);
+
#endif /* FACEMGR_FACELET_H */
diff --git a/ctrl/facemgr/includes/hicn/facemgr/loop.h b/ctrl/facemgr/includes/hicn/facemgr/loop.h
index 77cbedb21..752a3b365 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/loop.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/loop.h
@@ -63,14 +63,15 @@ void loop_free(loop_t * loop);
/**
* \brief Runs the loop instance to process events
* \param [in] loop - Pointer to the loop instance
+ * \return 0 if successful, -1 otherwise
*/
-void loop_dispatch(loop_t * loop);
+int 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);
+int loop_undispatch(loop_t * loop);
/**
* \brief Breaks out of the loop
diff --git a/ctrl/facemgr/src/CMakeLists.txt b/ctrl/facemgr/src/CMakeLists.txt
index 88f554c40..a473d6f72 100644
--- a/ctrl/facemgr/src/CMakeLists.txt
+++ b/ctrl/facemgr/src/CMakeLists.txt
@@ -22,7 +22,6 @@ set(COMPILER_DEFINITIONS
set(HEADER_FILES
common.h
error.h
- facelet.h
interface.h
loop.h
util/hash.h
diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c
index a1507bd70..19f211dbf 100644
--- a/ctrl/facemgr/src/api.c
+++ b/ctrl/facemgr/src/api.c
@@ -39,8 +39,8 @@
#endif /* __ANDROID__ */
#include <hicn/ctrl/face.h>
+#include <hicn/facemgr/facelet.h>
#include "common.h"
-#include "facelet.h"
#include "interface.h"
#include "util/map.h"
#include "util/set.h"
@@ -49,6 +49,7 @@
#define DEFAULT_PORT 9695
+#define DEFAULT_REATTEMPT_DELAY_MS 250
#define MAX_FDS 10
typedef struct {
@@ -149,6 +150,7 @@ struct facemgr_s {
#ifdef WITH_EXAMPLE_UPDOWN
interface_t * updown;
#endif
+ int timer_fd; /* Timer used for reattempts */
};
int
@@ -174,6 +176,8 @@ facemgr_initialize(facemgr_t * facemgr)
if (!facemgr->cfg)
goto ERR_CFG;
+ facemgr->timer_fd = 0;
+
return 0;
ERR_CFG:
@@ -194,6 +198,16 @@ facemgr_finalize(facemgr_t * facemgr)
int ret = 0;
int rc;
+ if (facemgr->timer_fd) {
+ rc = facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_UNREGISTER_TIMER, &facemgr->timer_fd);
+ if (rc < 0) {
+ ERROR("[facemgr_finalize] Error unregistering timer");
+ ret = -1;
+ }
+ facemgr->timer_fd = 0;
+ }
+
rc = interface_map_finalize(&facemgr->interface_map);
if (rc < 0) {
ERROR("[facemgr_finalize] Could not finalize interface_map");
@@ -226,6 +240,8 @@ facemgr_finalize(facemgr_t * facemgr)
ret = -1;
#endif /* __linux__ */
+ interface_unregister_all();
+
return ret;
}
@@ -265,12 +281,49 @@ facemgr_create_with_config(facemgr_cfg_t * cfg)
return facemgr;
}
+/*
+ * \brief Heuristics to determine face type based on name, until a better
+ * solution is found
+ */
+netdevice_type_t
+facemgr_get_netdevice_type(const facemgr_t * facemgr, const char * interface_name)
+{
+ if (strncmp(interface_name, "lo", 2) == 0) {
+ return NETDEVICE_TYPE_LOOPBACK;
+ }
+ if ((strncmp(interface_name, "eth", 3) == 0) ||
+ (strncmp(interface_name, "en", 2) == 0)) {
+ /* eth* en* enx* */
+ return NETDEVICE_TYPE_WIRED;
+ }
+ if (strncmp(interface_name, "wl", 2) == 0) {
+ /* wlan* wlp* wlx* */
+ return NETDEVICE_TYPE_WIFI;
+ }
+ if (strncmp(interface_name, "rmnet_ipa", 9) == 0) {
+ /* Qualcomm IPA driver */
+ return NETDEVICE_TYPE_UNDEFINED;
+ }
+ if ((strncmp(interface_name, "rmnet", 5) == 0) ||
+ (strncmp(interface_name, "rev_rmnet", 9) == 0) ||
+ (strncmp(interface_name, "ccmni", 5) == 0)) {
+ /*
+ * rmnet* (Qualcomm) ccmni* (MediaTek)
+ */
+ return NETDEVICE_TYPE_CELLULAR;
+ }
+ /* usb0 might be cellular (eg Zenfone2) */
+ /* what about tethering */
+ /* tun* dummy* ... */
+ /* bnet* pan* hci* for bluetooth */
+ return NETDEVICE_TYPE_UNDEFINED;
+}
+
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;
char rand_name[RAND_NAME_LEN+1];
interface_t * interface;
@@ -291,10 +344,6 @@ facemgr_create_interface(facemgr_t * facemgr, const char * name, const char * ty
}
interface_set_callback(interface, facemgr, facemgr_callback);
- fd = interface_initialize(interface, cfg);
- if (fd < 0)
- goto ERR_INIT;
-
interface_map_data_t * interface_map_data = malloc(sizeof(interface_map_data_t));
if (!interface_map_data)
goto ERR_MAP_DATA;
@@ -308,6 +357,15 @@ facemgr_create_interface(facemgr_t * facemgr, const char * name, const char * ty
if (interface_map_add(&facemgr->interface_map, interface->name, interface_map_data) < 0)
goto ERR_MAP_ADD;
+ /*
+ * This should be called _after_ the interface_map is initialized otherwise
+ * it will be impossible to register fds from *_initialize
+ */
+ if (interface_initialize(interface, cfg) < 0) {
+ ERROR("[facemgr_create_interface] Error initializing interface");
+ goto ERR_INIT;
+ }
+
DEBUG("Interface %s created successfully.", name);
if (pinterface)
*pinterface = interface;
@@ -342,7 +400,13 @@ facemgr_delete_interface(facemgr_t * facemgr, interface_t * interface)
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);
+ fd_callback_data_t fd_callback_data = {
+ .fd = fd,
+ .owner = facemgr,
+ .callback = NULL,
+ .data = NULL,
+ };
+ facemgr->callback(facemgr->callback_owner, FACEMGR_CB_TYPE_UNREGISTER_FD, &fd_callback_data);
if (rc < 0)
WARN("[facemgr_delete_interface] Error unregistering fd %d for interface", fd);
}
@@ -494,7 +558,7 @@ facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet)
}
netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifdef __ANDROID__
+//#ifdef __ANDROID__
/*
* In addition to netdevice, netdevice_type should be present to correctly
* apply rules
@@ -504,7 +568,7 @@ facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet)
ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice_type from facelet");
return -2;
}
-#endif /* __ANDROID__ */
+//#endif /* __ANDROID__ */
/* Ignore */
bool ignore;
@@ -578,11 +642,13 @@ facemgr_complement_facelet_au(facemgr_t * facemgr, facelet_t * facelet)
}
DEBUG("Querying android utility...");
- facelet_set_au_done(facelet);
/* /!\ Synchronous code here /!\ */
- if (facemgr_query_android_utility(facemgr, netdevice) < 0)
+ if (facemgr_query_android_utility(facemgr, netdevice) < 0) {
return -1;
+ }
+
+ facelet_set_au_done(facelet);
return 0;
}
#endif /* __ANDROID__ */
@@ -607,7 +673,7 @@ facemgr_complement_facelet_bj(facemgr_t * facemgr, facelet_t * facelet)
}
netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifdef __ANDROID__
+//#ifdef __ANDROID__
/*
* In addition to netdevice, netdevice_type should be present to correctly
* apply rules
@@ -617,7 +683,7 @@ facemgr_complement_facelet_bj(facemgr_t * facemgr, facelet_t * facelet)
ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice_type from facelet");
return -2;
}
-#endif /* __ANDROID__ */
+//#endif /* __ANDROID__ */
bool discovery;
if (facemgr_cfg_get_discovery(facemgr->cfg, &netdevice, netdevice_type,
@@ -679,7 +745,7 @@ facemgr_complement_facelet_manual(facemgr_t * facemgr, facelet_t * facelet)
}
netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifdef __ANDROID__
+//#ifdef __ANDROID__
/*
* In addition to netdevice, netdevice_type should be present to correctly
* apply rules
@@ -689,7 +755,7 @@ facemgr_complement_facelet_manual(facemgr_t * facemgr, facelet_t * facelet)
ERROR("[facemgr_complement_facelet_manual] Error retrieving netdevice_type from facelet");
return -2;
}
-#endif /* __ANDROID__ */
+//#endif /* __ANDROID__ */
int family = AF_UNSPEC;
if (facelet_has_family(facelet)) {
@@ -798,11 +864,22 @@ facemgr_complement_facelet(facemgr_t * facemgr, facelet_t * facelet)
if (!facelet_has_key(facelet))
return -2;
+#if 0
#ifdef __ANDROID__
rc = facemgr_complement_facelet_au(facemgr, facelet);
if (rc != -2)
return rc;
#endif /* __ANDROID__ */
+#endif
+ if (!facelet_has_netdevice_type(facelet)) {
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+ rc = facelet_get_netdevice(facelet, &netdevice);
+ if (rc < 0) {
+ ERROR("[facemgr_complement_facelet] Error retrieving netdevice from facelet");
+ return -1;
+ }
+ facelet_set_netdevice_type(facelet, facemgr_get_netdevice_type(facemgr, netdevice.name));
+ }
/* We continue only if the current call was not applicable. In the current
* setting we have no interface that can be requested in parallel, and no
@@ -825,105 +902,279 @@ facemgr_complement_facelet(facemgr_t * facemgr, facelet_t * facelet)
return 0;
}
-/**
- * \brief Process facelet CREATE event
- * \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.
- */
-int
-facemgr_process_create(facemgr_t * facemgr, facelet_t * facelet)
+int facemgr_assign_face_type(facemgr_t * facemgr, facelet_t * facelet)
{
- /*
- * We create an interface locally, which does not means it should not exist
- * remotely. Once such codepath is enabled, the two facelets will have been
- * merged and we need to handle an eventual update on our side.
- *
- * In the same way, we need to check for the equivalence of face types etc.
- */
- int rc;
+ /* As key, netdevice and family should always be present */
+ netdevice_t netdevice = NETDEVICE_EMPTY;
+ int rc = facelet_get_netdevice(facelet, &netdevice);
+ if (rc < 0) {
+ ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice from facelet");
+ return -1;
+ }
+ netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
+//#ifdef __ANDROID__
/*
- * If the facelet does not satisfy filters, we do not lose any information
- * but do not take any action to complement the face
+ * In addition to netdevice, netdevice_type should be present to correctly
+ * apply rules
*/
- rc = facemgr_facelet_satisfy_rules(facemgr, facelet);
- if (rc == -3) {
- facelet_set_status(facelet, FACELET_STATUS_IGNORED);
- /* Does not satisfy rules */
- return 0;
+ rc = facelet_get_netdevice_type(facelet, &netdevice_type);
+ if (rc < 0) {
+ ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice_type from facelet");
+ return -2;
}
+//#endif /* __ANDROID__ */
- // FIXME: we should complement a part of the facelet, so that we don't
- // necessarily keep this information if we get more locally. Or at least we
- // should remember that.
- if (rc == -2) {
- /*
- * We don't have equivalent for linux right now, heuristic is only used
- * at the end... might change.
- */
-#ifdef __ANDROID__
- /* Priority is given to information that complements a face */
- if (facemgr_complement_facelet_au(facemgr, facelet) < 0) {
- ERROR("[facemgr_process_create] Error while attempting to complement face for fields required by rule application");
- return -1;
- }
- return 0;
-#endif /* __ANDROID__ */
+ facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED;
+ if (facemgr_cfg_get_face_type(facemgr->cfg, &netdevice, netdevice_type, &face_type) < 0)
+ return rc;
+ facelet_set_face_type(facelet, face_type);
+ return 0;
+}
+
+/*
+ * This function performs one step of the state machine associated to the
+ * facelet, from initial creation, to synchronization with the forwarder.
+ *
+ * We assume the facelet is already present in the cache
+ */
+int
+facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet)
+{
+ int rc;
+
+ switch(facelet_get_status(facelet)) {
+ case FACELET_STATUS_UNCERTAIN:
+ /*
+ * All new faces are marked UNCERTAIN. We need to check whether we
+ * have sufficient information to check rules, if not proceed,
+ * otherwise possibly mark the face as IGNORED. Otherwise, we verify
+ * the completeness of the information we have, and continue towards
+ * being able to mark the face as CREATE.
+ */
+ rc = facemgr_facelet_satisfy_rules(facemgr, facelet);
+ switch(rc) {
+ case -3:
+ /* Does not satisfy rules */
+ facelet_set_status(facelet, FACELET_STATUS_IGNORED);
+ return 0;
+
+ case -2:
+ /* Not enough information: AU in fact */
+ if (facemgr_complement_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_facelet] Error while attempting to complement face for fields required by face creation");
+ goto ERR;
+ }
+ return 0;
+
+ case 0:
+ /* Ok pass rules */
+ break;
+
+ default:
+ /* -1 - Error */
+ goto ERR;
+ }
+
+ if (facemgr_assign_face_type(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_facelet] Could not assign face type");
+ goto ERR;
+ }
+ facelet_set_status(facelet, FACELET_STATUS_INCOMPLETE);
+ /* Continue in case facelet satisfies rules */
+
+ case FACELET_STATUS_INCOMPLETE:
+ if (!facelet_validate_face(facelet)) {
+ /* We need additional information */
+ if (facemgr_complement_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_facelet] Error while attempting to complement face for fields required by face creation");
+ goto ERR;
+ }
+ }
+ if (!facelet_validate_face(facelet))
+ return 0;
+
+ facelet_set_status(facelet, FACELET_STATUS_CREATE);
+ /* Continue in case we need to proceed to creation */
+
+ case FACELET_STATUS_CREATE:
+ facelet_set_event(facelet, FACELET_EVENT_CREATE);
+ if (interface_on_event(facemgr->hl, facelet) < 0) {
+ ERROR("[facemgr_process_facelet] Failed to create face");
+ goto ERR;
+ }
+
+ /* This works assuming the call to hicn-light is blocking */
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ break;
+
+
+ case FACELET_STATUS_UPDATE:
+ facelet_set_event(facelet, FACELET_EVENT_UPDATE);
+ if (interface_on_event(facemgr->hl, facelet) < 0) {
+ ERROR("[facemgr_process_facelet] Failed to update face");
+ goto ERR;
+ }
+
+ /* This works assuming the call to hicn-light is blocking */
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ break;
+
+ case FACELET_STATUS_DELETE:
+ facelet_set_event(facelet, FACELET_EVENT_DELETE);
+ if (interface_on_event(facemgr->hl, facelet) < 0) {
+ ERROR("[facemgr_process_facelet] Failed to delete face");
+ goto ERR;
+ }
+
+ /* This works assuming the call to hicn-light is blocking */
+ DEBUG("[facemgr_process_facelet] Cleaning cached data");
+ facelet_unset_local_addr(facelet);
+ facelet_unset_local_port(facelet);
+ facelet_unset_remote_addr(facelet);
+ facelet_unset_remote_port(facelet);
+ facelet_unset_bj_done(facelet);
+ //facelet_unset_au_done(facelet);
+
+ facelet_set_status(facelet, FACELET_STATUS_DELETED);
+ break;
+
+ case FACELET_STATUS_CLEAN:
+ case FACELET_STATUS_IGNORED:
+ case FACELET_STATUS_DELETED:
+ /* Nothing to do */
+ break;
+
+ case FACELET_STATUS_UNDEFINED:
+ case FACELET_STATUS_N:
+ ERROR("[facemgr_process_facelet] Unexpected facelet status");
+ goto ERR;
}
- if (rc < 0)
- return -1;
-// netdevice_t netdevice = NETDEVICE_EMPTY;
-// if (facelet_get_netdevice(facelet, &netdevice) < 0) {
-// ERROR("[facemgr_process_create] Error retrieving netdevice from facelet");
-// return -1;
-// }
-//
-// netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-//#ifdef __ANDROID__
-// /*
-// * In addition to netdevice, netdevice_type should be present to correctly
-// * apply rules
-// */
-// if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) {
-// ERROR("[facemgr_process_create] Error retrieving netdevice_type from facelet");
-// return -2;
-// }
-//#endif /* __ANDROID__ */
+ facelet_set_status_error(facelet, false);
+ return 0;
+ERR:
+ facelet_set_status_error(facelet, true);
+ return -1;
+}
- char facelet_s[MAXSZ_FACELET];
- facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
- //DEBUG("---[ FACELET CREATE : %s ] ---", facelet_s);
+int
+facemgr_reattempt_timeout(facemgr_t * facemgr, int fd, void * data)
+{
+ bool has_error = false;
- /* Do we have enough information about the facelet ? */
- if (!facelet_validate_face(facelet)) {
- if (facemgr_complement_facelet(facemgr, facelet) < 0) {
- ERROR("[facemgr_process_create] Error while attempting to complement face for fields required by face creation");
- return -1;
+ assert(data == NULL);
+
+ /* 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_reattempt_timeout] Could not retrieve facelets in cache");
+ } else {
+ for (unsigned i = 0; i < n; i++) {
+ facelet_t * facelet = facelet_array[i];
+
+ if (!facelet_get_status_error(facelet))
+ continue;
+
+ char buf[MAXSZ_FACELET];
+ facelet_snprintf(buf, MAXSZ_FACELET, facelet);
+ DEBUG("Reattempt to process failed facelet %s", buf);
+ if (facemgr_process_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_reattempt_timeout] Error processing facelet");
+ has_error = true;
+ continue;
+ }
+ facelet_set_status_error(facelet, false);
}
- // we should not stop after complement_manual but create a face if
- // possible... so we add a second validation
+ free(facelet_array);
}
- if (!facelet_validate_face(facelet))
+ if (has_error)
return 0;
- /*
- * Is the forwarder connected, and has the facelet cache already sync'ed the
- * remote faces ?
- */
- // TODO
+ DEBUG("Cancelling timer");
+ if (facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_UNREGISTER_TIMER, &facemgr->timer_fd) < 0) {
+ ERROR("[facemgr_reattempt_timeout] Error unregistering reattempt timer");
+ return -1;
+ }
+ facemgr->timer_fd = 0;
+ return 0;
+}
- /*
- * Actually create the face on the forwarder
- *
- * FIXME Currently hicn-light is hardcoded
- */
- if (interface_on_event(facemgr->hl, facelet) < 0)
+int
+facemgr_start_reattempts(facemgr_t * facemgr)
+{
+ if (facemgr->timer_fd > 0)
+ return 0;
+
+ timer_callback_data_t timer_callback = {
+ .delay_ms = DEFAULT_REATTEMPT_DELAY_MS,
+ .owner = facemgr,
+ .callback = (fd_callback_t)facemgr_reattempt_timeout,
+ .data = NULL,
+ };
+ facemgr->timer_fd = facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_REGISTER_TIMER, &timer_callback);
+ return (facemgr->timer_fd > 0);
+}
+
+/**
+ * \brief Process facelet CREATE event
+ * \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_facelet_create(facemgr_t * facemgr, facelet_t * facelet)
+{
+ switch(facelet_get_status(facelet)) {
+ case FACELET_STATUS_UNCERTAIN:
+ case FACELET_STATUS_INCOMPLETE:
+ case FACELET_STATUS_CREATE:
+ /* No change */
+ break;
+ case FACELET_STATUS_UPDATE:
+ case FACELET_STATUS_DELETE:
+ /*
+ * Unlikely. The face had been created and is planned to
+ * be deleted. Schedule for creation (we should have all
+ * needed information), but make sure to handle errors
+ * correctly if the face is still present.
+ * TODO What if some fields have been updated ?
+ */
+ facelet_set_status(facelet, FACELET_STATUS_CREATE);
+ break;
+ case FACELET_STATUS_CLEAN:
+ case FACELET_STATUS_IGNORED:
+ /*
+ * We should have nothing to do unless some fields have
+ * been updated.
+ */
+ break;
+
+ case FACELET_STATUS_DELETED:
+ /*
+ * Unless rules have changed, we only need to recover
+ * missing information, and proceed to face creation.
+ * Rule changes should be handled separately.
+ */
+ facelet_set_status(facelet, FACELET_STATUS_INCOMPLETE);
+ break;
+ case FACELET_STATUS_UNDEFINED:
+ case FACELET_STATUS_N:
+ ERROR("[facemgr_process_facelet_create] Unexpected facelet status");
+ return -1;
+ }
+
+ if (facemgr_process_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_facelet_create] Error processing facelet");
return -1;
- facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ }
+
return 0;
}
@@ -935,15 +1186,15 @@ facemgr_process_create(facemgr_t * facemgr, facelet_t * facelet)
* -2 means we ignored the face purposedly
*/
int
-facemgr_process_get(facemgr_t * facemgr, facelet_t * facelet)
+facemgr_process_facelet_get(facemgr_t * facemgr, facelet_t * facelet)
{
- facelet_set_status(facelet, FACELET_STATUS_CLEAN);
if (facelet_has_netdevice(facelet)) {
netdevice_t netdevice;
if (facelet_get_netdevice(facelet, &netdevice) < 0)
return -1;
if (!IS_VALID_NETDEVICE(netdevice))
return -2;
+ facelet_set_status(facelet, FACELET_STATUS_CLEAN);
return facelet_cache_add(&facemgr->facelet_cache, facelet);
}
return -2;
@@ -954,146 +1205,38 @@ facemgr_process_get(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_update(facemgr_t * facemgr, facelet_t * facelet)
+facemgr_process_facelet_update(facemgr_t * facemgr, facelet_t * facelet)
{
- /* This is the most complex operation since we have the same problems as in
- * CREATE + the need to manage changes...
- *
- * This might eventually trigger a face deletion...
- */
-
- /*
- * Update in local does not mean the face should not be created remotely as
- * it might be the first time we have enough information to create it
- */
-
- char facelet_s[MAXSZ_FACELET];
- facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
- //DEBUG("---[ FACELET UPDATE : %s ] ---", facelet_s);
-
- /* Sets face type */
- if (!facelet_has_face_type(facelet)) {
-
- /* As key, netdevice and family should always be present */
- netdevice_t netdevice = NETDEVICE_EMPTY;
- int rc = facelet_get_netdevice(facelet, &netdevice);
- if (rc < 0) {
- ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice from facelet");
- return -1;
- }
-
- netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifdef __ANDROID__
- /*
- * In addition to netdevice, netdevice_type should be present to correctly
- * apply rules
- */
- rc = facelet_get_netdevice_type(facelet, &netdevice_type);
- if (rc < 0) {
- ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice_type from facelet");
- return -2;
- }
-#endif /* __ANDROID__ */
-
- facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED;
- if (facemgr_cfg_get_face_type(facemgr->cfg, &netdevice, netdevice_type, &face_type) < 0)
- return rc;
- facelet_set_face_type(facelet, face_type);
- }
-
- /* Process GET/UDPATE... */
- int rc;
switch(facelet_get_status(facelet)) {
- case FACELET_STATUS_UNDEFINED:
- ERROR("[facemgr_process_update] Unexpected facelet status");
- return -1;
-
- case FACELET_STATUS_DELETED:
- case FACELET_STATUS_NEW:
- /*
- * If the remote action should be a CREATE, then we need to check
- * whether we have enough information about the face...
- */
- if (!facelet_validate_face(facelet)) {
- if (facemgr_complement_facelet(facemgr, facelet) < 0) {
- ERROR("[facemgr_process_update] Error while attempting to complement face for fields required by face creation");
- 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;
-
- facelet_set_event(facelet, FACELET_EVENT_CREATE);
- interface_on_event(facemgr->hl, facelet);
-
- /* This works assuming the call to hicn-light is blocking */
- facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ case FACELET_STATUS_UNCERTAIN:
+ case FACELET_STATUS_INCOMPLETE:
+ case FACELET_STATUS_CREATE:
+ case FACELET_STATUS_UPDATE:
+ /* No change */
break;
-
case FACELET_STATUS_CLEAN:
- /* Nothing to do */
- break;
-
- case FACELET_STATUS_DIRTY:
- /*
- * For now we assume only local changes, and proceed to try and
- * update the hICN forwarder.
- *
- * In case of update, the face exists which means we should already
- * have enough information
- */
- if (!facelet_validate_face(facelet)) {
- if (facemgr_complement_facelet(facemgr, facelet) < 0) {
- ERROR("[facemgr_process_create] Error while attempting to complement face for fields required by face creation");
- 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;
-
- facelet_set_event(facelet, FACELET_EVENT_UPDATE);
- if (interface_on_event(facemgr->hl, facelet) < 0)
- return -1;
-
- /* This works assuming the call to hicn-light is blocking and we
- * have proceeded to all udpates */
- facelet_set_status(facelet, FACELET_STATUS_CLEAN);
+ facelet_set_status(facelet, FACELET_STATUS_UPDATE);
break;
-
- 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_DELETE:
+ case FACELET_STATUS_DELETED:
case FACELET_STATUS_IGNORED:
- ERROR("[facemgr_process_update] Case IGNORED (not) yet implemented");
+ /* Reconsider face creation in light of new information */
+ facelet_set_status(facelet, FACELET_STATUS_UNCERTAIN);
break;
-
+ case FACELET_STATUS_UNDEFINED:
case FACELET_STATUS_N:
- ERROR("[facemgr_process_update] Facelet in error");
+ ERROR("[facemgr_process_facelet_update] Unexpected facelet status");
return -1;
}
+
+ if (facemgr_process_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_facelet_update] Error processing facelet");
+ return -1;
+ }
+
return 0;
}
@@ -1102,34 +1245,47 @@ facemgr_process_update(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_delete(facemgr_t * facemgr, facelet_t * facelet)
+facemgr_process_facelet_delete(facemgr_t * facemgr, facelet_t * facelet)
{
+ switch(facelet_get_status(facelet)) {
+ case FACELET_STATUS_UNCERTAIN:
+ case FACELET_STATUS_INCOMPLETE:
+ case FACELET_STATUS_CREATE:
+ facelet_unset_local_addr(facelet);
+ facelet_unset_local_port(facelet);
+ facelet_unset_remote_addr(facelet);
+ facelet_unset_remote_port(facelet);
+ facelet_unset_bj_done(facelet);
+ //facelet_unset_au_done(facelet);
+ facelet_set_status(facelet, FACELET_STATUS_DELETED);
+ break;
+ case FACELET_STATUS_UPDATE:
+ case FACELET_STATUS_CLEAN:
+ facelet_set_status(facelet, FACELET_STATUS_DELETE);
+ break;
+ case FACELET_STATUS_DELETE:
+ case FACELET_STATUS_IGNORED:
+ case FACELET_STATUS_DELETED:
+ /* Nothing to do */
+ DEBUG("%s\n", facelet_status_str[facelet_get_status(facelet)]);
+ break;
+ case FACELET_STATUS_UNDEFINED:
+ case FACELET_STATUS_N:
+ ERROR("[facemgr_process_facelet_delete] Unexpected facelet status");
+ return -1;
+ }
- DEBUG("[facemgr_process_delete] Deleting facelet on hicn-light");
- if (interface_on_event(facemgr->hl, facelet) < 0)
+ if (facemgr_process_facelet(facemgr, facelet) < 0) {
+ ERROR("[facemgr_process_facelet_delete] Error processing facelet");
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_unset_bj_done(facelet);
+ }
return 0;
}
-
/**
* \brief Process incoming events from interfaces
*
@@ -1147,37 +1303,41 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
char facelet_s[MAXSZ_FACELET];
facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet_in);
- //DEBUG("----------------------------------");
DEBUG("EVENT %s", facelet_s);
facelet_t ** cached_facelets = NULL;
int n = facelet_cache_lookup(&facemgr->facelet_cache, facelet_in, &cached_facelets);
if (n < 0) {
ERROR("[facemgr_on_event] Error during cache lookup");
- goto ERR;
+ free(facelet_in);
+ return -1;
}
if (n == 0) {
/* This is a new facelet... we expect a CREATE event. */
switch(facelet_get_event(facelet_in)) {
case FACELET_EVENT_CREATE:
+ facelet_set_status(facelet_in, FACELET_STATUS_UNCERTAIN);
if (facelet_cache_add(&facemgr->facelet_cache, facelet_in) < 0) {
ERROR("[facemgr_on_event] Error adding facelet to cache");
+ free(facelet_in);
+ free(cached_facelets);
return -1;
}
- //DEBUG("Facelet added to cache");
remove_facelet = false;
- if (facemgr_process_create(facemgr, facelet_in) < 0) {
- ERROR("[facemgr_on_event] Error processing CREATE event");
+ if (facemgr_process_facelet_create(facemgr, facelet_in) < 0) {
+ ERROR("[facemgr_on_event] Error processing facelet CREATE event");
+ ret = -1;
goto ERR;
}
+
break;
case FACELET_EVENT_GET:
/* Insert new facelet in cached */
- rc = facemgr_process_get(facemgr, facelet_in);
+ rc = facemgr_process_facelet_get(facemgr, facelet_in);
if (rc == 0)
remove_facelet = false;
if (rc == -1) {
@@ -1227,10 +1387,12 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
ERROR("[facemgr_on_event] Error merging facelets");
continue;
}
- if (facemgr_process_create(facemgr, facelet) < 0) {
- ERROR("[facemgr_on_event] Error processing CREATE event");
+
+ if (facemgr_process_facelet_create(facemgr, facelet_in) < 0) {
+ ERROR("[facemgr_on_event] Error processing facelet CREATE event");
ret = -1;
}
+
continue;
case FACELET_EVENT_GET: /* should be an INFORM message */
@@ -1245,8 +1407,8 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
ERROR("[facemgr_on_event] Error merging facelets");
continue;
}
- if (facemgr_process_update(facemgr, facelet) < 0) {
- ERROR("[facemgr_on_event] Error processing UPDATE event");
+ if (facemgr_process_facelet_update(facemgr, facelet) < 0) {
+ ERROR("[facemgr_on_event] Error processing facelet UPDATE event");
ret = -1;
}
continue;
@@ -1256,8 +1418,8 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
ERROR("[facemgr_on_event] Error merging facelets");
continue;
}
- if (facemgr_process_delete(facemgr, facelet) < 0) {
- ERROR("[facemgr_on_event] Error processing DELETE event");
+ if (facemgr_process_facelet_delete(facemgr, facelet) < 0) {
+ ERROR("[facemgr_on_event] Error processing facelet DELETE event");
ret = -1;
}
continue;
@@ -1268,7 +1430,6 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
}
}
- free(cached_facelets);
goto DUMP_CACHE;
ERR:
@@ -1283,9 +1444,14 @@ DUMP_CACHE:
DEBUG("----------------------------------");
#endif
+ free(cached_facelets);
+
if (remove_facelet)
facelet_free(facelet_in);
+ if (ret == -1)
+ facemgr_start_reattempts(facemgr);
+
return ret;
}
@@ -1294,18 +1460,62 @@ 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:
+ {
+ /* Remember fd for further release */
+ fd_callback_data_t * fd_callback_data = data;
+ interface_t * interface = (interface_t*)(fd_callback_data->owner);
+
+ interface_map_data_t * interface_map_data = NULL;
+ if (interface_map_get(&facemgr->interface_map, interface->name, &interface_map_data) < 0) {
+ ERROR("[facemgr_callback] Error getting interface map data");
+ return -1;
+ }
+ if (!interface_map_data) {
+ ERROR("[facemgr_callback] No entry in interface map data");
+ return -1;
+ }
+ interface_map_data->fds[interface_map_data->num_fds++] = fd_callback_data->fd;
+
return facemgr->callback(facemgr->callback_owner,
FACEMGR_CB_TYPE_REGISTER_FD, data);
+ }
+
+ case INTERFACE_CB_TYPE_UNREGISTER_FD:
+ {
+ fd_callback_data_t * fd_callback_data = data;
+ interface_t * interface = (interface_t*)(fd_callback_data->owner);
+
+ interface_map_data_t * interface_map_data = NULL;
+ if (interface_map_get(&facemgr->interface_map, interface->name, &interface_map_data) < 0) {
+ ERROR("[facemgr_callback] Error getting interface map data");
+ return -1;
+ }
+ if (!interface_map_data) {
+ ERROR("[facemgr_callback] No entry in interface map data");
+ return -1;
+ }
+
+ for (unsigned i = 0; i < interface_map_data->num_fds; i++) {
+ if (interface_map_data->fds[i] == fd_callback_data->fd) {
+ interface_map_data->fds[i] = interface_map_data->fds[--interface_map_data->num_fds];
+ break;
+ }
+ }
+
+ return facemgr->callback(facemgr->callback_owner,
+ FACEMGR_CB_TYPE_UNREGISTER_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;
}
@@ -1497,8 +1707,85 @@ facemgr_set_callback(facemgr_t * facemgr, void * callback_owner, facemgr_cb_t ca
facemgr->callback_owner = callback_owner;
}
-void facemgr_list_faces(facemgr_t * facemgr, facemgr_list_faces_cb_t cb, void * user_data)
+void facemgr_list_facelets(const facemgr_t * facemgr, facemgr_list_facelets_cb_t cb, void * user_data)
{
- //face_cache_iter(&facemgr->face_cache, cb, user_data);
- facelet_cache_dump(&facemgr->facelet_cache);
+ facelet_t ** facelet_array;
+ if (!cb)
+ return;
+ int n = facelet_cache_get_array(&facemgr->facelet_cache, &facelet_array);
+ if (n < 0) {
+ ERROR("[facemgr_list_facelets] Could not retrieve facelets in cache");
+ return;
+ }
+ for (unsigned i = 0; i < n; i++) {
+ facelet_t * facelet = facelet_array[i];
+ cb(facemgr, facelet, user_data);
+ }
+ free(facelet_array);
+}
+
+int
+facemgr_list_facelets_json(const facemgr_t * facemgr, char ** buffer)
+{
+ char * cur;
+ char * s;
+ int rc;
+
+ facelet_t ** facelet_array;
+ int n = facelet_cache_get_array(&facemgr->facelet_cache, &facelet_array);
+ if (n < 0) {
+ ERROR("[facemgr_list_facelets_json] Could not retrieve facelets in cache");
+ return -1;
+ }
+ /* This should be enough for JSON overhead, refine later */
+ size_t size = 2 * n * MAXSZ_FACELET;
+ *buffer = malloc(size);
+ if (!buffer) {
+ ERROR("[facemgr_list_facelets_json] Could not allocate JSON s");
+ free(facelet_array);
+ return -1;
+ }
+ s = *buffer;
+ cur = s;
+
+ rc = snprintf(cur, s + size - cur, "{\"facelets\": [\n");
+ if (rc < 0)
+ goto ERR;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ goto END;
+
+ for (unsigned i = 0; i < n; i++) {
+ facelet_t * facelet = facelet_array[i];
+
+ rc = facelet_snprintf_json(cur, s + size - cur, facelet, /* indent */ 1);
+ if (rc < 0)
+ goto ERR;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ goto END;
+
+ rc = snprintf(cur, s + size - cur, (i == n-1) ? "\n" : ",\n");
+ if (rc < 0)
+ goto ERR;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ goto END;
+ }
+ free(facelet_array);
+
+ rc = snprintf(cur, s + size - cur, "]}\n");
+ if (rc < 0)
+ goto ERR;
+ cur += rc;
+ if (size != 0 && cur >= s + size)
+ goto END;
+
+END:
+ free(facelet_array);
+ return cur - s;
+
+ERR:
+ free(facelet_array);
+ return rc;
}
diff --git a/ctrl/facemgr/src/cfg.c b/ctrl/facemgr/src/cfg.c
index 527da54e7..bf47e5570 100644
--- a/ctrl/facemgr/src/cfg.c
+++ b/ctrl/facemgr/src/cfg.c
@@ -726,13 +726,13 @@ facemgr_cfg_get_override(const facemgr_cfg_t * cfg,
continue;
/* Check match for interface type */
if (rule_array[i]->match.interface_type != NETDEVICE_TYPE_UNDEFINED) {
-#ifdef __ANDROID__
+//#ifdef __ANDROID__
if (netdevice_type != rule_array[i]->match.interface_type)
continue;
-#else
- ERROR("Match on interface type is currently not implemented");
- goto ERR_ARRAY;
-#endif /* __ANDROID__ */
+//#else
+// ERROR("Match on interface type is currently not implemented");
+// goto ERR_ARRAY;
+//#endif /* __ANDROID__ */
}
/* Found match... do we have an override for face_type */
*override = &rule_array[i]->override;
@@ -745,11 +745,11 @@ FOUND:
free(rule_array);
return 0;
-#ifndef __ANDROID__
-ERR_ARRAY:
- free(rule_array);
- return -1;
-#endif /* __ANDROID__ */
+//#ifndef __ANDROID__
+//ERR_ARRAY:
+// free(rule_array);
+// return -1;
+//#endif /* __ANDROID__ */
}
int
diff --git a/ctrl/facemgr/src/facelet.c b/ctrl/facemgr/src/facelet.c
index 6d6d74c2b..01f4b8076 100644
--- a/ctrl/facemgr/src/facelet.c
+++ b/ctrl/facemgr/src/facelet.c
@@ -22,10 +22,9 @@
#include <stdbool.h>
#include <hicn/ctrl/face.h>
#include <hicn/facemgr/cfg.h>
+#include <hicn/facemgr/facelet.h>
#include <hicn/util/log.h>
-#include "facelet.h"
-
const char * face_type_layer_str[] = {
#define _(x) [FACE_TYPE_LAYER_ ## x] = STRINGIZE(x),
foreach_face_type_layer
@@ -75,6 +74,8 @@ struct facelet_s {
#undef _
facelet_status_t status;
+ bool status_error;
+
facelet_event_t event;
/* Joins */
@@ -106,7 +107,8 @@ facelet_create()
facelet->state_status = FACELET_ATTR_STATUS_UNSET;
facelet->face_type_status = FACELET_ATTR_STATUS_UNSET;
- facelet->status = FACELET_STATUS_NEW;
+ facelet->status = FACELET_STATUS_UNDEFINED;
+ facelet->status_error = false;
facelet->bj_done = false;
facelet->au_done = false;
@@ -296,6 +298,7 @@ facelet_create_from_face(face_t * face)
/* Status */
facelet->status = FACELET_STATUS_CLEAN;
+ facelet->status_error = false;
/* TODO Consistency check between face type and found attributes */
if (facelet_validate_face(facelet) < 0)
@@ -465,7 +468,7 @@ facelet_set_local_ ## NAME(facelet_t * facelet, TYPE NAME)
facelet-> NAME = NAME; \
facelet->NAME ## _status = FACELET_ATTR_STATUS_DIRTY; \
if (facelet->status == FACELET_STATUS_CLEAN) \
- facelet->status = FACELET_STATUS_DIRTY; \
+ facelet->status = FACELET_STATUS_UPDATE; \
break; \
case FACELET_ATTR_STATUS_CONFLICT: \
break; \
@@ -495,8 +498,9 @@ facelet_set_remote_ ## NAME(facelet_t * facelet, TYPE NAME)
case FACELET_ATTR_STATUS_PENDING: \
ERROR("Received remote value on pending attribute"); \
facelet->NAME ## _status = FACELET_ATTR_STATUS_CONFLICT; \
- if (facelet->status != FACELET_STATUS_CONFLICT) \
- facelet->status = FACELET_STATUS_CONFLICT; \
+ /* We need to proceed to an update of the face */ \
+ if (facelet->status != FACELET_STATUS_UPDATE) \
+ facelet->status = FACELET_STATUS_UPDATE; \
break; \
case FACELET_ATTR_STATUS_CONFLICT: \
return -1; \
@@ -686,32 +690,6 @@ facelet_get_face(const facelet_t * facelet, face_t ** pface)
goto ERR;
}
}
-#ifdef __linux__
-#ifndef __ANDROID__
- else {
- /*
- * Heuristics to determine face type based on name, until a better
- * solution is found
- */
- if (strncmp(facelet->netdevice.name, "eth", 3) == 0) {
- policy_tags_add(&tags, POLICY_TAG_WIRED);
- goto DONE;
- }
- if (strncmp(facelet->netdevice.name, "en", 2) == 0) {
- policy_tags_add(&tags, POLICY_TAG_WIRED);
- goto DONE;
- }
- if (strncmp(facelet->netdevice.name, "wl", 2) == 0) {
- /* wlan* wlp* wlx* */
- policy_tags_add(&tags, POLICY_TAG_WIFI);
- goto DONE;
- }
-
-DONE:
- ;
- }
-#endif /* ! __ANDROID__ */
-#endif /* __linux__ */
face->tags = tags;
*pface = face;
@@ -731,10 +709,10 @@ facelet_get_status(const facelet_t * facelet)
return facelet->status;
}
-#define SET_ATTR_STATUS_CLEAN(TYPE, NAME) \
-do { \
- if (facelet->NAME ## _status == FACELET_ATTR_STATUS_DIRTY) \
- facelet->NAME ## _status = FACELET_ATTR_STATUS_CLEAN; \
+#define SET_ATTR_STATUS_CLEAN(TYPE, NAME) \
+do { \
+ if (facelet->NAME ## _status == FACELET_ATTR_STATUS_DIRTY) \
+ facelet->NAME ## _status = FACELET_ATTR_STATUS_CLEAN; \
} while (0)
void
@@ -749,6 +727,18 @@ facelet_set_status(facelet_t * facelet, facelet_status_t status)
}
void
+facelet_set_status_error(facelet_t * facelet, bool value)
+{
+ facelet->status_error = value;
+}
+
+bool
+facelet_get_status_error(const facelet_t * facelet)
+{
+ return facelet->status_error;
+}
+
+void
facelet_set_bj_done(facelet_t * facelet)
{
facelet->bj_done = true;
@@ -791,7 +781,7 @@ facelet_set_event(facelet_t * facelet, facelet_event_t event)
}
int
-facelet_snprintf(char * s, size_t size, facelet_t * facelet)
+facelet_snprintf(char * s, size_t size, const facelet_t * facelet)
{
char * cur = s;
int rc;
@@ -799,9 +789,9 @@ 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)",
- // FIXME, better than the event would be the action to be performed next
- facelet_event_str[facelet->event],
+ rc = snprintf(cur, s + size - cur, "<Facelet %s %s (%s)",
+ facelet_status_str[facelet->status],
+ facelet_get_status_error(facelet) ? "/!\\" : "",
(facelet->family == AF_INET) ? "AF_INET" :
(facelet->family == AF_INET6) ? "AF_INET6" :
(facelet->family == AF_UNSPEC) ? "AF_UNSPEC" :
@@ -809,7 +799,7 @@ facelet_snprintf(char * s, size_t size, facelet_t * facelet)
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
/* Netdevice */
@@ -819,14 +809,14 @@ facelet_snprintf(char * s, size_t size, facelet_t * facelet)
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
rc = snprintf(cur, s + size - cur, "/%d", facelet->netdevice.index);
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
} else {
@@ -834,7 +824,7 @@ facelet_snprintf(char * s, size_t size, facelet_t * facelet)
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
}
@@ -845,39 +835,9 @@ facelet_snprintf(char * s, size_t size, facelet_t * facelet)
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
- return cur - s;
- }
-#ifdef __linux__
-#ifndef __ANDROID__
- else {
- /*
- * Heuristics to determine face type based on name, until a better
- * solution is found
- */
- if ((strncmp(facelet->netdevice.name, "eth", 3) == 0) ||
- (strncmp(facelet->netdevice.name, "en", 2) == 0)) {
- rc = snprintf(cur, s + size - cur, " [type=WIRED]");
- goto HEURISTIC_DONE;
- }
- if (strncmp(facelet->netdevice.name, "wl", 2) == 0) {
- /* wlan* wlp* wlx* */
- rc = snprintf(cur, s + size - cur, " [type=WIFI]");
- goto HEURISTIC_DONE;
- }
- goto HEURISTIC_END;
-
-HEURISTIC_DONE:
- if (rc < 0)
- return rc;
- cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
-HEURISTIC_END:
- ;
}
-#endif /* ! __ANDROID__ */
-#endif /* __linux__ */
/* Local ip address */
if (facelet_has_local_addr(facelet)) {
@@ -885,7 +845,7 @@ HEURISTIC_END:
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
rc = ip_address_snprintf(cur, s + size - cur, &facelet->local_addr,
@@ -893,7 +853,7 @@ HEURISTIC_END:
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
}
@@ -904,7 +864,7 @@ HEURISTIC_END:
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
}
@@ -914,7 +874,7 @@ HEURISTIC_END:
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
rc = ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr,
@@ -922,7 +882,7 @@ HEURISTIC_END:
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
}
@@ -933,7 +893,7 @@ HEURISTIC_END:
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
}
@@ -944,7 +904,7 @@ HEURISTIC_END:
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
}
@@ -955,7 +915,7 @@ HEURISTIC_END:
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
}
@@ -965,7 +925,7 @@ HEURISTIC_END:
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
return cur - s;
}
@@ -973,7 +933,208 @@ HEURISTIC_END:
if (rc < 0)
return rc;
cur += rc;
- if (size != 0 && cur >= s + size)
+ if (cur >= s + size)
+ return cur - s;
+
+ return cur - s;
+}
+
+int facelet_snprintf_json(char * s, size_t size, const facelet_t * facelet, int indent)
+{
+ char * cur = s;
+ int rc;
+
+ assert(facelet);
+
+ /* Header + key attributes (netdevice + family) */
+ rc = snprintf(cur, s + size - cur, "%*s%s", 4 * indent, "", "{\n");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+
+ /* Status */
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "", "\"status\"",
+ facelet_status_str[facelet->status]);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+
+ /* Family */
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "", "\"family\"",
+ (facelet->family == AF_INET) ? "AF_INET" :
+ (facelet->family == AF_INET6) ? "AF_INET6" :
+ (facelet->family == AF_UNSPEC) ? "AF_UNSPEC" :
+ "unknown");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+
+ /* Netdevice */
+ if (facelet_has_netdevice(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "",
+ "\"netdevice\"",
+ facelet->netdevice.name[0] ? facelet->netdevice.name : "*");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+
+ } else {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "",
+ "\"netdevice\"", "*");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+ }
+
+ /* Netdevice type */
+ if (facelet_has_netdevice_type(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "",
+ "\"netdevice_type\"",
+ netdevice_type_str[facelet->netdevice_type]);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+ }
+
+ /* Local ip address */
+ if (facelet_has_local_addr(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"", 4 * (indent+1), "",
+ "\"local_addr\"");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+
+ rc = ip_address_snprintf(cur, s + size - cur, &facelet->local_addr,
+ facelet->family);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+
+ rc = snprintf(cur, s + size - cur, "\",\n");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+ }
+
+ /* Local port */
+ if (facelet_has_local_port(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent+1), "",
+ "\"local_port\"",
+ facelet->local_port);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+ }
+
+ /* Remote ip address */
+ if (facelet_has_remote_addr(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"", 4 * (indent+1), "",
+ "\"remote_addr\"");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+
+ rc = ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr,
+ facelet->family);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+
+ rc = snprintf(cur, s + size - cur, "\",\n");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+ }
+
+ /* Remote port */
+ if (facelet_has_remote_port(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent+1), "",
+ "\"remote_port\"",
+ facelet->remote_port);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+ }
+
+ /* Admin state */
+ if (facelet_has_admin_state(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "",
+ "\"admin_state\"",
+ face_state_str[facelet->admin_state]);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+ }
+
+ /* State */
+ if (facelet_has_state(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\",\n", 4 * (indent+1), "",
+ "\"state\"",
+ face_state_str[facelet->state]);
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+ }
+
+ if (facelet_has_face_type(facelet)) {
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"LAYER%s/%s\",\n", 4 * (indent+1), "",
+ "\"face_type\"",
+ FACEMGR_FACE_TYPE_STR(facelet->face_type));
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+ }
+
+ /* Status error */
+ rc = snprintf(cur, s + size - cur, "%*s%s: \"%s\"\n", 4 * (indent+1), "",
+ "\"error\"",
+ facelet_get_status_error(facelet) ? "true" : "false");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
+ return cur - s;
+
+
+ rc = snprintf(cur, s + size - cur, "%*s%s", 4 * indent, "", "}");
+ if (rc < 0)
+ return rc;
+ cur += rc;
+ if (cur >= s + size)
return cur - s;
return cur - s;
diff --git a/ctrl/facemgr/src/interface.c b/ctrl/facemgr/src/interface.c
index 5cefcb98c..72a78ef56 100644
--- a/ctrl/facemgr/src/interface.c
+++ b/ctrl/facemgr/src/interface.c
@@ -21,9 +21,11 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
-#include "facelet.h"
-#include "interface.h"
+
+#include <hicn/facemgr/facelet.h>
#include <hicn/facemgr/loop.h> /* *_callback_data_t */
+
+#include "interface.h"
#include "util/map.h"
TYPEDEF_MAP_H(interface_ops_map, const char *, const interface_ops_t *);
@@ -62,6 +64,8 @@ interface_unregister_all()
}
free(ops_name_array);
}
+ interface_ops_map_free(interface_ops_map);
+ interface_ops_map = NULL;
return ret;
}
@@ -155,8 +159,14 @@ int
interface_unregister_fd(interface_t * interface, int fd)
{
assert(interface->callback);
+ fd_callback_data_t fd_callback = {
+ .fd = fd,
+ .owner = interface,
+ .callback = NULL,
+ .data = NULL,
+ };
return interface->callback(interface->callback_owner,
- INTERFACE_CB_TYPE_UNREGISTER_FD, &fd);
+ INTERFACE_CB_TYPE_UNREGISTER_FD, &fd_callback);
}
typedef int (*interface_fd_callback_t)(interface_t * interface, int fd, void * unused);
diff --git a/ctrl/facemgr/src/interface.h b/ctrl/facemgr/src/interface.h
index d99f4fc8e..0ebe8c7c8 100644
--- a/ctrl/facemgr/src/interface.h
+++ b/ctrl/facemgr/src/interface.h
@@ -78,6 +78,11 @@ typedef struct interface_s {
int interface_register(const interface_ops_t * ops);
/**
+ * \brief Unregister all interface types
+ */
+int interface_unregister_all();
+
+/**
* \brief Create a new instance of an interface of a given type.
* \param [in] name - Name of the newly create interface instance.
* \param [in] type - Name of the interface type to create.
diff --git a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
index a4aa2cbfc..e7c73df8b 100644
--- a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
+++ b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
@@ -24,17 +24,18 @@
#include <hicn/ctrl/face.h>
#include <hicn/util/log.h>
#include "../../common.h"
-#include "../../facelet.h"
#include "../../interface.h"
#include <hicn/android_utility/android_utility.h>
#define FACEMGR_ANDROID_UTILITY_CLASS "com/cisco/hicn/forwarder/supportlibrary/AndroidUtility"
+
#define AU_INTERFACE_TYPE_UNDEFINED 0
#define AU_INTERFACE_TYPE_WIRED 1
#define AU_INTERFACE_TYPE_WIFI 2
#define AU_INTERFACE_TYPE_CELLULAR 3
-#define AU_INTERFACE_TYPE_LOOPBACK 4 /* not supported yet */
+#define AU_INTERFACE_TYPE_LOOPBACK 4
+#define AU_INTERFACE_TYPE_UNAVAILABLE 5
#define ERR_STR_JAVA "Java VM parameters are required in the interface configuration."
@@ -77,14 +78,12 @@ int au_on_event(interface_t * interface, const facelet_t * facelet)
* correct interface type, based on the value returned by the Android
* utility shipped with the Android forwarder.
*/
- DEBUG("Android utility received request");
au_data_t * data = (au_data_t*)interface->data;
netdevice_t netdevice = NETDEVICE_EMPTY;
int rc = facelet_get_netdevice(facelet, &netdevice);
if (rc < 0)
return -1;
- DEBUG("[au_on_event] netdevice=%s", netdevice.name);
JNIEnv *env;
JavaVM *jvm = data->cfg.jvm;
@@ -95,8 +94,6 @@ int au_on_event(interface_t * interface, const facelet_t * facelet)
jint interface_type = (*env)->CallStaticIntMethod(env, cls, getNetworkType,
(*env)->NewStringUTF(env, netdevice.name));
- DEBUG("Processing results for interface %s", netdevice.name);
-
netdevice_type_t netdevice_type = AU_INTERFACE_TYPE_UNDEFINED;
switch(interface_type) {
case AU_INTERFACE_TYPE_UNDEFINED:
@@ -114,15 +111,17 @@ int au_on_event(interface_t * interface, const facelet_t * facelet)
netdevice_type = NETDEVICE_TYPE_LOOPBACK;
break;
default:
+ DEBUG("AU RETURNED ERROR");
return -1;
}
+ DEBUG("AU RETURNED %s : %s", netdevice.name, netdevice_type_str[netdevice_type]);
+
facelet_t * facelet_new = facelet_create();
facelet_set_netdevice(facelet_new, netdevice);
facelet_set_status(facelet_new, FACELET_STATUS_CLEAN);
facelet_set_netdevice_type(facelet_new, netdevice_type);
- DEBUG("sending AU udpate");
facelet_set_event(facelet_new, FACELET_EVENT_UPDATE);
interface_raise_event(interface, facelet_new);
diff --git a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c
index 4d09d89bb..87f1e1257 100644
--- a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c
+++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c
@@ -26,7 +26,6 @@
#include <hicn/util/log.h>
#include "../../common.h"
-#include "../../facelet.h"
#include "../../interface.h"
#include "../../util/map.h"
#include "mdns/mdns.h"
@@ -107,10 +106,15 @@ int bj_initialize(interface_t * interface, void * cfg)
WSAStartup(versionWanted, &wsaData);
#endif
- interface_register_fd(interface, data->sock, NULL);
+ if (interface_register_fd(interface, data->sock, NULL) < 0) {
+ ERROR("[bj_initialize] Error registering fd");
+ goto ERR_FD;
+ }
return 0;
+ERR_FD:
+ free(data->buffer);
ERR_BUFFER:
#ifndef __ANDROID__
ERR_SOCK_OPT:
diff --git a/ctrl/facemgr/src/interfaces/dummy/dummy.c b/ctrl/facemgr/src/interfaces/dummy/dummy.c
index 6a21792a2..25180465e 100644
--- a/ctrl/facemgr/src/interfaces/dummy/dummy.c
+++ b/ctrl/facemgr/src/interfaces/dummy/dummy.c
@@ -24,7 +24,6 @@
#include <hicn/facemgr.h>
#include "../../common.h"
-#include "../../facelet.h"
#include "../../interface.h"
#include "dummy.h"
@@ -65,6 +64,12 @@ int dummy_initialize(interface_t * interface, void * cfg)
/* ... */
data->fd = 0;
+#if 0
+ if (interface_register_fd(interface, data->fd, NULL) < 0) {
+ ERROR("[dummy_initialize] Error registering fd");
+ goto ERR_FD;
+ }
+#endif
/* ... */
@@ -74,8 +79,9 @@ int dummy_initialize(interface_t * interface, void * cfg)
* - a file descriptor (>0) will be added to the event loop; or
* - 0 if we don't use any file descriptor
*/
- return data->fd;
+ return 0;
+ERR_FD:
ERR_MALLOC:
return -1;
}
diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
index 1f20177c2..e8f168706 100644
--- a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
+++ b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
@@ -27,7 +27,6 @@
#include <hicn/util/ip_address.h>
#include <hicn/util/log.h>
-#include "../../facelet.h"
#include "../../interface.h"
#include "../../util/map.h"
@@ -69,18 +68,6 @@ int hl_process_state(interface_t * interface)
return -1;
}
break;
-#if 0
- foreach_face(f, faces) {
-#if 0
- hc_face_snprintf(buf, MAXSZ_FACE, f);
- printf("Face: %s\n", buf);
-#endif
- facelet_t * facelet = facelet_create_from_face(&f->face);
- facelet_set_event(facelet, FACELET_EVENT_GET);
- interface_raise_event(interface, facelet);
- }
- break;
-#endif
case HL_STATE_FACES_SENT:
break;
@@ -97,7 +84,6 @@ int
hl_after_connect(interface_t * interface)
{
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) {
@@ -123,7 +109,7 @@ 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);
+ DEBUG("[hl_initialize] Error during connection reattempt; next attempt in %ds", INTERVAL_MS / 1000);
return -1;
}
@@ -149,11 +135,11 @@ _hl_connect(interface_t * interface)
}
if (hc_sock_connect(data->s) < 0) {
- ERROR("[hc_connect] Could not connect control socket");
+ DEBUG("[hc_connect] Could not connect control socket");
goto ERR_CONNECT;
}
- return hl_after_connect(interface);
+ return 0;
ERR_CONNECT:
hc_sock_free(data->s);
@@ -183,7 +169,7 @@ hl_connect(interface_t * interface)
hl_data_t * data = interface->data;
if (_hl_connect(interface) >= 0)
- return 0;
+ return hl_after_connect(interface);
/* Timer for managing the connection to the forwarder */
DEBUG("Connection to forwarder failed... next retry in %ds", INTERVAL_MS / 1000);
@@ -250,12 +236,12 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
*/
if (facelet_get_face(facelet, &face) < 0) {
ERROR("Could not retrieve face from facelet");
- return -1;
+ goto ERR_FACE;
}
if (!data->s) {
/* We are not connected to the forwarder */
- return -1;
+ goto ERR;
}
@@ -270,7 +256,7 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
ERROR("Failed to create face\n");
goto ERR;
}
- INFO("Created face id=%d\n", hc_face.id);
+ INFO("Created face id=%d", hc_face.id);
/* Adding default routs e*/
#if 1
@@ -336,7 +322,6 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
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");
@@ -356,8 +341,6 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
goto ERR;
}
- 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;
@@ -377,6 +360,7 @@ int hl_on_event(interface_t * interface, const facelet_t * facelet)
ERR:
face_free(face);
+ERR_FACE:
return -1;
}
@@ -398,15 +382,14 @@ int hl_callback(interface_t * interface, int fd, void * unused)
if (faces->complete) {
foreach_face(f, faces) {
-#if 1
+#if 0
char buf[MAXSZ_FACE];
hc_face_snprintf(buf, MAXSZ_FACE, f);
printf("Face: %s\n", buf);
-#else
+#endif
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);
diff --git a/ctrl/facemgr/src/interfaces/netlink/netlink.c b/ctrl/facemgr/src/interfaces/netlink/netlink.c
index babf1c305..a9c8c889e 100644
--- a/ctrl/facemgr/src/interfaces/netlink/netlink.c
+++ b/ctrl/facemgr/src/interfaces/netlink/netlink.c
@@ -29,7 +29,6 @@
#include <hicn/util/log.h>
#include "../../common.h"
-#include "../../facelet.h"
#include "../../interface.h"
typedef enum {
@@ -142,7 +141,7 @@ int nl_initialize(interface_t * interface, void * cfg)
data->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (data->fd < 0) {
- printf("Failed to create netlink socket: %s\n", (char*)strerror(errno));
+ ERROR("[nl_initialize] Failed to create netlink socket: %s", (char*)strerror(errno));
goto ERR_SOCKET;
}
@@ -164,13 +163,16 @@ int nl_initialize(interface_t * interface, void * cfg)
local.nl_pid = getpid(); // set out id using current process id
if (bind(data->fd, (struct sockaddr*)&local, sizeof(local)) < 0) { // bind socket
- printf("Failed to bind netlink socket: %s\n", (char*)strerror(errno));
+ ERROR("[nl_initialize] Failed to bind netlink socket: %s", (char*)strerror(errno));
goto ERR_BIND;
}
interface->data = data;
- interface_register_fd(interface, data->fd, NULL);
+ if (interface_register_fd(interface, data->fd, NULL) < 0) {
+ ERROR("[nl_initialize] Error registering fd");
+ goto ERR_FD;
+ }
#if 1
nl_process_state(interface);
@@ -178,6 +180,7 @@ int nl_initialize(interface_t * interface, void * cfg)
return 0;
+ERR_FD:
ERR_BIND:
close(data->fd);
ERR_SOCKET:
diff --git a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
index f438d34d5..19fe7bbe2 100644
--- a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
+++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
@@ -32,7 +32,6 @@
#include "../../common.h"
#include <hicn/ctrl/face.h>
-#include "../../facelet.h"
#include "../../interface.h"
#include "../../util/map.h"
diff --git a/ctrl/facemgr/src/interfaces/updown/updown.c b/ctrl/facemgr/src/interfaces/updown/updown.c
index c864c8c04..6a7ab83f4 100644
--- a/ctrl/facemgr/src/interfaces/updown/updown.c
+++ b/ctrl/facemgr/src/interfaces/updown/updown.c
@@ -28,7 +28,6 @@
#include <hicn/facemgr.h>
#include "../../common.h"
-#include "../../facelet.h"
#include "../../interface.h"
/**
@@ -71,7 +70,12 @@ int updown_initialize(interface_t * interface, void * cfg)
return -1;
}
- return data->fd;
+ if (interface_register_fd(interface, data->fd, NULL) < 0) {
+ ERROR("[updown_initialize] Error registering fd");
+ goto ERR_FD;
+ }
+
+ return 0;
ERR_MALLOC:
return -1;
diff --git a/ctrl/facemgr/src/loop_dispatcher.c b/ctrl/facemgr/src/loop_dispatcher.c
index 7e7f9d667..d2177ba21 100644
--- a/ctrl/facemgr/src/loop_dispatcher.c
+++ b/ctrl/facemgr/src/loop_dispatcher.c
@@ -49,16 +49,18 @@ loop_free(loop_t * loop)
/* Nothing to do */
}
-void
+int
loop_dispatch(loop_t * loop)
{
dispatch_main();
+ return 0;
}
-void
+int
loop_undispatch(loop_t * loop)
{
/* Nothing to do */
+ return 0;
}
void
diff --git a/ctrl/facemgr/src/loop_libevent.c b/ctrl/facemgr/src/loop_libevent.c
index 4042c717a..966129730 100644
--- a/ctrl/facemgr/src/loop_libevent.c
+++ b/ctrl/facemgr/src/loop_libevent.c
@@ -160,30 +160,32 @@ loop_free(loop_t * loop)
free(loop);
}
-void
+int
loop_dispatch(loop_t * loop)
{
#ifdef WITH_THREAD
- if (pthread_create(loop->thread, NULL, start_dispatch, loop)) {
+ if (pthread_create(&loop->thread, NULL, (void * (*)(void *))event_base_dispatch, loop->event_base)) {
fprintf(stderr, "Error creating thread\n");
- return EXIT_FAILURE;
+ return -1;
}
#else
event_base_dispatch(loop->event_base);
#endif /* WITH_THREAD */
+ return 0;
}
-void
+int
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;
+ return -1;
}
DEBUG("Loop terminated !");
#endif /* WITH_THREAD */
+ return 0;
}
void
@@ -210,7 +212,7 @@ 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 */
+ /* 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,
@@ -220,14 +222,20 @@ _loop_register_fd(loop_t * loop, int fd, void * callback_owner,
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)
+ if (!event) {
+ ERROR("[_loop_register_fd] event_new");
goto ERR_EVENT_NEW;
+ }
- if (event_add(event, NULL) < 0)
+ if (event_add(event, NULL) < 0) {
+ ERROR("[_loop_register_fd] event_add");
goto ERR_EVENT_ADD;
+ }
- if (event_map_add(loop->event_map, fd, event) < 0)
+ if (event_map_add(loop->event_map, fd, event) < 0) {
+ ERROR("[_loop_register_fd] event_map_add");
goto ERR_EVENT_MAP;
+ }
return 0;
@@ -249,7 +257,7 @@ _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");
+ ERROR("[_loop_unregister_fd] Error removing event associated to fd");
return -1;
}
@@ -317,13 +325,13 @@ _loop_register_timer(loop_t * loop, timer_callback_data_t * timer_callback_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");
+ ERROR("[_loop_register_timer] 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");
+ ERROR("[_loop_register_timer] Error registering fd to event loop");
return -1;
}
@@ -352,14 +360,14 @@ _loop_unregister_timer(loop_t * loop, int fd)
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");
+ ERROR("[_loop_unregister_timer] 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");
+ ERROR("[_loop_unregister_timer] Error unregistering fd from event loop");
return -1;
}
@@ -386,10 +394,10 @@ loop_callback(loop_t * loop, facemgr_cb_type_t type, void * data)
case FACEMGR_CB_TYPE_UNREGISTER_FD:
{
- int fd = *(int*)data;
+ fd_callback_data_t * fd_callback_data = (fd_callback_data_t *)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");
+ if (_loop_unregister_fd(loop, fd_callback_data->fd) < 0) {
+ ERROR("[loop_callback] Error unregistering fd from event loop");
return -1;
}
break;
diff --git a/ctrl/facemgr/src/main.c b/ctrl/facemgr/src/main.c
index be5ff3c68..9eba2aa0c 100644
--- a/ctrl/facemgr/src/main.c
+++ b/ctrl/facemgr/src/main.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h> // sleep
#include <hicn/facemgr.h>
#include <hicn/policy.h>
@@ -44,6 +45,12 @@ static struct event_base * loop;
#endif
static loop_t * loop = NULL;
+#ifdef __linux__
+#ifdef WITH_THREAD
+static bool stop = false;
+#endif /* WITH_THREAD */
+#endif /* __linux__ */
+
static struct option long_options[] =
{
{"config", required_argument, 0, 'c'},
@@ -69,6 +76,11 @@ void facemgr_signal_handler(int signal) {
fprintf(stderr, "Received ^C... quitting !\n");
if (loop) {
loop_break(loop);
+#ifdef __linux__
+#ifdef WITH_THREAD
+ stop = true;
+#endif /* WITH_THREAD */
+#endif /* __linux__ */
}
}
@@ -95,6 +107,16 @@ int parse_cmdline(int argc, char ** argv, facemgr_options_t * opts)
#endif /* __linux__ */
+int
+dump_facelet(const facemgr_t * facemgr, const facelet_t * facelet,
+ void * user_data)
+{
+ char facelet_s[MAXSZ_FACELET];
+ facelet_snprintf(facelet_s, MAXSZ_FACELET, facelet);
+ DEBUG("%s", facelet_s);
+ return 0;
+}
+
int main(int argc, char ** argv)
{
facemgr_cfg_t * cfg = NULL;
@@ -176,20 +198,41 @@ MAIN_LOOP:
if (facemgr_bootstrap(facemgr) < 0 )
goto ERR_BOOTSTRAP;
- loop_dispatch(loop);
+ if (loop_dispatch(loop) < 0) {
+ ERROR("Failed to run main loop");
+ return EXIT_FAILURE;
+ }
#ifdef __linux__
#ifdef WITH_THREAD
- for(;;) {
- facemgr_list_faces(facemgr, NULL, NULL);
- sleep(5);
+ unsigned cpt = 0;
+ while(!stop) {
+ if (cpt == 10) {
+ DEBUG("<facelets>");
+#if 1
+ facemgr_list_facelets(facemgr, dump_facelet, NULL);
+#else
+ char * buffer;
+ int n = facemgr_list_facelets_json(facemgr, &buffer);
+ printf("%s\n", buffer);
+ free(buffer);
+#endif
+
+ DEBUG("</facelets>");
+ cpt = 0;
+ }
+ usleep(500000);
+ cpt++;
}
#endif /* WITH_THREAD */
#endif /* __linux__ */
facemgr_stop(facemgr);
- loop_undispatch(loop);
+ if (loop_undispatch(loop) < 0) {
+ ERROR("Failed to terminate main loop");
+ return EXIT_FAILURE;
+ }
facemgr_free(facemgr);
diff --git a/ctrl/facemgr/src/util/map.h b/ctrl/facemgr/src/util/map.h
index b113954a6..19a308d86 100644
--- a/ctrl/facemgr/src/util/map.h
+++ b/ctrl/facemgr/src/util/map.h
@@ -108,6 +108,16 @@ NAME ## _initialize(NAME ## _t * map)
int \
NAME ## _finalize(NAME ## _t * map) \
{ \
+ NAME ## _pair_t ** array; \
+ int n = NAME ## _pair_set_get_array(&map->pair_set, &array); \
+ if (n < 0) \
+ return -1; \
+ for (unsigned i = 0; i < n; i++) { \
+ NAME ## _pair_t * pair = array[i]; \
+ NAME ## _pair_set_remove(&map->pair_set, pair, NULL); \
+ NAME ## _pair_free(pair); \
+ } \
+ free(array); \
return NAME ## _pair_set_finalize(&map->pair_set); \
} \
\
diff --git a/ctrl/facemgr/src/util/set.h b/ctrl/facemgr/src/util/set.h
index 0dad17423..b9d66c16e 100644
--- a/ctrl/facemgr/src/util/set.h
+++ b/ctrl/facemgr/src/util/set.h
@@ -96,7 +96,19 @@ NAME ## _initialize(NAME ## _t * set) \
} \
\
int \
-NAME ## _finalize(NAME ## _t * set) { return 0; } \
+NAME ## _finalize(NAME ## _t * set) \
+{ \
+ T * array; \
+ int n = NAME ## _get_array(set, &array); \
+ if (n < 0) \
+ return -1; \
+ for (unsigned i = 0; i < n; i++) { \
+ T element = array[i]; \
+ NAME ## _remove(set, element, NULL); \
+ } \
+ free(array); \
+ return 0; \
+} \
\
NAME ## _t * \
NAME ## _create() \
diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c
index 0e5b529c5..783245e8a 100644
--- a/ctrl/libhicnctrl/src/api.c
+++ b/ctrl/libhicnctrl/src/api.c
@@ -325,7 +325,7 @@ hc_data_create(size_t in_element_size, size_t out_element_size)
return data;
ERR_BUFFER:
- free(data);
+ hc_data_free(data);
ERR_MALLOC:
return NULL;
}
@@ -645,12 +645,9 @@ hc_sock_process(hc_sock_t * s, hc_data_t ** data)
}
s->remaining = msg->hdr.length;
if (s->remaining == 0) {
- if (data) {
- *data = request->data;
-// } else {
-// free(request->data);
- }
hc_data_set_complete(request->data);
+ if (data)
+ *data = request->data;
hc_sock_request_free(request);
} else {
/* We only remember it if there is still data to parse */
@@ -696,12 +693,9 @@ hc_sock_process(hc_sock_t * s, hc_data_t ** data)
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);
+ if (data)
+ *data = s->cur_request->data;
hc_sock_request_free(s->cur_request);
s->cur_request = NULL;
}
@@ -724,9 +718,9 @@ hc_sock_process(hc_sock_t * s, hc_data_t ** data)
}
int
-hc_sock_callback(hc_sock_t * s, hc_data_t ** data)
+hc_sock_callback(hc_sock_t * s, hc_data_t ** pdata)
{
- *data = NULL;
+ hc_data_t * data;
for (;;) {
int n = hc_sock_recv(s);
@@ -739,22 +733,28 @@ hc_sock_callback(hc_sock_t * s, hc_data_t ** data)
case ENODEV:
/* Forwarder restarted */
WARN("Forwarder likely restarted: not (yet) implemented");
- goto ERR_EOF;
+ goto ERR;
case EWOULDBLOCK:
//DEBUG("Would block... stop reading from socket");
goto END;
default:
perror("hc_sock_recv");
- goto ERR_EOF;
+ goto ERR;
}
}
- if (hc_sock_process(s, data) < 0) {
- return -1;
+ if (hc_sock_process(s, &data) < 0) {
+ goto ERR;
}
}
END:
+ if (pdata)
+ *pdata = data;
+ else
+ hc_data_free(data);
return 0;
+ERR:
+ hc_data_free(data);
ERR_EOF:
return -1;
}
@@ -865,6 +865,9 @@ hc_execute_command(hc_sock_t * s, hc_msg_t * msg, size_t msg_len,
}
}
+ if (!pdata)
+ hc_data_free(data);
+
return 0;
ERR_PROCESS:
@@ -872,7 +875,7 @@ ERR_MAP:
hc_sock_request_free(request);
ERR_REQUEST:
ERR_SEQ:
- free(data);
+ hc_data_free(data);
ERR_DATA:
return -1;
}