From 95170bf3a69597b49238bb7ff396d41f6dc94f30 Mon Sep 17 00:00:00 2001 From: Jordan Augé Date: Wed, 30 Oct 2019 17:56:08 +0100 Subject: [HICN-369] Implement reconciliation state machine in face manager incl. reattempts in case of errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ia4ecf621fbd513d9e29313d2aaa487aa65811183 Signed-off-by: Jordan Augé --- ctrl/facemgr/includes/CMakeLists.txt | 3 + ctrl/facemgr/includes/facemgr.h | 3 +- ctrl/facemgr/includes/hicn/facemgr/api.h | 6 +- ctrl/facemgr/includes/hicn/facemgr/facelet.h | 198 +++++ ctrl/facemgr/includes/hicn/facemgr/loop.h | 5 +- ctrl/facemgr/src/CMakeLists.txt | 1 - ctrl/facemgr/src/api.c | 815 ++++++++++++++------- ctrl/facemgr/src/cfg.c | 20 +- ctrl/facemgr/src/facelet.c | 331 ++++++--- ctrl/facemgr/src/facelet.h | 192 ----- ctrl/facemgr/src/interface.c | 16 +- ctrl/facemgr/src/interface.h | 5 + .../interfaces/android_utility/android_utility.c | 13 +- ctrl/facemgr/src/interfaces/bonjour/bonjour.c | 8 +- ctrl/facemgr/src/interfaces/dummy/dummy.c | 10 +- .../facemgr/src/interfaces/hicn_light/hicn_light.c | 37 +- ctrl/facemgr/src/interfaces/netlink/netlink.c | 11 +- .../network_framework/network_framework.c | 1 - ctrl/facemgr/src/interfaces/updown/updown.c | 8 +- ctrl/facemgr/src/loop_dispatcher.c | 6 +- ctrl/facemgr/src/loop_libevent.c | 42 +- ctrl/facemgr/src/main.c | 53 +- ctrl/facemgr/src/util/map.h | 10 + ctrl/facemgr/src/util/set.h | 14 +- ctrl/libhicnctrl/src/api.c | 39 +- 25 files changed, 1199 insertions(+), 648 deletions(-) create mode 100644 ctrl/facemgr/includes/hicn/facemgr/facelet.h delete mode 100644 ctrl/facemgr/src/facelet.h (limited to 'ctrl') 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 #include #include +#include +#include #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 +#include #include #ifdef __ANDROID__ #include @@ -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/includes/hicn/facemgr/facelet.h b/ctrl/facemgr/includes/hicn/facemgr/facelet.h new file mode 100644 index 000000000..7fc2745f1 --- /dev/null +++ b/ctrl/facemgr/includes/hicn/facemgr/facelet.h @@ -0,0 +1,198 @@ +/* + * 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 facelet.h + * \brief Facelet + * + * A facelet consists in partial information and annotations collected towards + * the contruction of the final face that will be sent to the forwarder. + * + * It might also consist in a pattern allowing the deletion of a group of face + * for instance. + */ +#ifndef FACEMGR_FACELET_H +#define FACEMGR_FACELET_H + +#include + +#include +#include + +#define MAXSZ_FACELET 1024 + +/* NOTE: Any test should be sufficient */ +#define IS_VALID_NETDEVICE(netdevice) ((netdevice.index != 0) && (netdevice.name[0] != '\0')) + +typedef struct facelet_s facelet_t; + +/* Facelet status */ +#define foreach_facelet_status \ + _(UNDEFINED) \ + _(UNCERTAIN) \ + _(INCOMPLETE) \ + _(CREATE) \ + _(CLEAN) \ + _(IGNORED) \ + _(UPDATE) \ + _(DELETE) \ + _(DELETED) \ + _(N) + +typedef enum { +#define _(x) FACELET_STATUS_ ## x, + foreach_facelet_status +#undef _ +} facelet_status_t; + +extern const char * facelet_status_str[]; + +/* Facelet attribute status */ + +/* + * We expect an attribute in the cache to be able to take any value but + * UNDEFINED and N, which facelet events should either be UNSET or CLEAN + */ +#define foreach_facelet_attr_status \ + _(UNDEFINED, '?') \ + _(UNSET, 'X') \ + _(CLEAN, ' ') \ + _(DIRTY, '*') \ + _(PENDING, 'P') \ + _(CONFLICT, '!') \ + _(N, '-') + +typedef enum { +#define _(x, y) FACELET_ATTR_STATUS_ ## x, + foreach_facelet_attr_status +#undef _ +} facelet_attr_status_t; + +extern const char * facelet_attr_status_str[]; +extern const char * facelet_attr_status_str_short[]; + +/* Facelet attribute */ + +#define foreach_facelet_attr \ + _(netdevice_type_t, netdevice_type) \ + _(netdevice_t, netdevice) \ + _(int, family) \ + _(ip_address_t, local_addr) \ + _(u16, local_port) \ + _(ip_address_t, remote_addr) \ + _(u16, remote_port) \ + _(face_state_t, admin_state) \ + _(face_state_t, state) \ + _(facemgr_face_type_t, face_type) + +#define foreach_facelet_event \ + _(UNDEFINED) \ + _(GET) \ + _(CREATE) \ + _(UPDATE) \ + _(DELETE) \ + _(SET_PARAMS) \ + _(SET_UP) \ + _(SET_DOWN) \ + _(SET_TAGS) \ + _(CLEAR_TAGS) \ + _(ADD_TAG) \ + _(REMOVE_TAG) \ + _(N) + +#define MAXSZ_EVENT__ 10 +#define MAXSZ_EVENT_ MAXSZ_EVENT_ + 1 + +/** + * \brief Enumeration of the possible types of event + */ +typedef enum { +#define _(x) FACELET_EVENT_ ## x, +foreach_facelet_event +#undef _ +} facelet_event_t; + +extern const char * facelet_event_str[]; + +/** + * \brief Create a facelet. + */ +facelet_t * facelet_create(); + +facelet_t * facelet_create_from_netdevice(netdevice_t * netdevice); + +int facelet_validate_face(const facelet_t * facelet); + +facelet_t * facelet_create_from_face(face_t * face); + +void facelet_free(facelet_t * facelet); + +facelet_t * facelet_dup(const facelet_t * current_facelet); + +int facelet_cmp(const facelet_t * f1, const facelet_t * f2); + +/* NOTE: only clean attributes are matched */ +bool facelet_match(const facelet_t * facelet, const facelet_t * facelet_match); + +/** + * \brief Returns whether the specified facelet has all key attributes defined. + * + * Key attributes are netdevice and family. If both are present, this allows to + * uniquely identify a facelet, otherwise it is a 'wildcard' facelet + * specification and might match several facelets. + */ +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_unset_ ## NAME(facelet_t * facelet); + +#define _(TYPE, NAME) FACELET_ACCESSORS_H(TYPE, NAME) +foreach_facelet_attr +#undef _ + +int facelet_get_face(const facelet_t * facelet, face_t ** pface); + +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); +void facelet_set_au_done(facelet_t * facelet); +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, const facelet_t * facelet); + +#define DUMP_FACELET(msg, facelet) do { \ + char buf[MAXSZ_FACELET]; \ + facelet_snprintf(buf, MAXSZ_FACELET, 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 +#include #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 #include #include +#include #include -#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 @@ -748,6 +726,18 @@ facelet_set_status(facelet_t * facelet, facelet_status_t status) facelet->status = 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) { @@ -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, "event], + rc = snprintf(cur, s + size - cur, "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/facelet.h b/ctrl/facemgr/src/facelet.h deleted file mode 100644 index 16c23b12e..000000000 --- a/ctrl/facemgr/src/facelet.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 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 facelet.h - * \brief Facelet - * - * A facelet consists in partial information and annotations collected towards - * the contruction of the final face that will be sent to the forwarder. - * - * It might also consist in a pattern allowing the deletion of a group of face - * for instance. - */ -#ifndef FACEMGR_FACELET_H -#define FACEMGR_FACELET_H - -#include - -#include -#include - -#define MAXSZ_FACELET 1024 - -/* NOTE: Any test should be sufficient */ -#define IS_VALID_NETDEVICE(netdevice) ((netdevice.index != 0) && (netdevice.name[0] != '\0')) - -typedef struct facelet_s facelet_t; - -/* Facelet status */ -#define foreach_facelet_status \ - _(UNDEFINED) \ - _(NEW) \ - _(CLEAN) \ - _(DIRTY) \ - _(CONFLICT) \ - _(DELETED) \ - _(IGNORED) \ - _(ERROR) \ - _(N) - -typedef enum { -#define _(x) FACELET_STATUS_ ## x, - foreach_facelet_status -#undef _ -} facelet_status_t; - -extern const char * facelet_status_str[]; - -/* Facelet attribute status */ - -/* - * We expect an attribute in the cache to be able to take any value but - * UNDEFINED and N, which facelet events should either be UNSET or CLEAN - */ -#define foreach_facelet_attr_status \ - _(UNDEFINED, '?') \ - _(UNSET, 'X') \ - _(CLEAN, ' ') \ - _(DIRTY, '*') \ - _(PENDING, 'P') \ - _(CONFLICT, '!') \ - _(N, '-') - -typedef enum { -#define _(x, y) FACELET_ATTR_STATUS_ ## x, - foreach_facelet_attr_status -#undef _ -} facelet_attr_status_t; - -extern const char * facelet_attr_status_str[]; -extern const char * facelet_attr_status_str_short[]; - -/* Facelet attribute */ - -#define foreach_facelet_attr \ - _(netdevice_type_t, netdevice_type) \ - _(netdevice_t, netdevice) \ - _(int, family) \ - _(ip_address_t, local_addr) \ - _(u16, local_port) \ - _(ip_address_t, remote_addr) \ - _(u16, remote_port) \ - _(face_state_t, admin_state) \ - _(face_state_t, state) \ - _(facemgr_face_type_t, face_type) - -#define foreach_facelet_event \ - _(UNDEFINED) \ - _(GET) \ - _(CREATE) \ - _(UPDATE) \ - _(DELETE) \ - _(SET_PARAMS) \ - _(SET_UP) \ - _(SET_DOWN) \ - _(SET_TAGS) \ - _(CLEAR_TAGS) \ - _(ADD_TAG) \ - _(REMOVE_TAG) \ - _(N) - -#define MAXSZ_EVENT__ 10 -#define MAXSZ_EVENT_ MAXSZ_EVENT_ + 1 - -/** - * \brief Enumeration of the possible types of event - */ -typedef enum { -#define _(x) FACELET_EVENT_ ## x, -foreach_facelet_event -#undef _ -} facelet_event_t; - -extern const char * facelet_event_str[]; - -/** - * \brief Create a facelet. - */ -facelet_t * facelet_create(); - -facelet_t * facelet_create_from_netdevice(netdevice_t * netdevice); - -int facelet_validate_face(const facelet_t * facelet); - -facelet_t * facelet_create_from_face(face_t * face); - -void facelet_free(facelet_t * facelet); - -facelet_t * facelet_dup(const facelet_t * current_facelet); - -int facelet_cmp(const facelet_t * f1, const facelet_t * f2); - -/* NOTE: only clean attributes are matched */ -bool facelet_match(const facelet_t * facelet, const facelet_t * facelet_match); - -/** - * \brief Returns whether the specified facelet has all key attributes defined. - * - * Key attributes are netdevice and family. If both are present, this allows to - * uniquely identify a facelet, otherwise it is a 'wildcard' facelet - * specification and might match several facelets. - */ -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_unset_ ## NAME(facelet_t * facelet); - -#define _(TYPE, NAME) FACELET_ACCESSORS_H(TYPE, NAME) -foreach_facelet_attr -#undef _ - -int facelet_get_face(const facelet_t * facelet, face_t ** pface); - -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_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); - -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); - -#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 5cefcb98c..72a78ef56 100644 --- a/ctrl/facemgr/src/interface.c +++ b/ctrl/facemgr/src/interface.c @@ -21,9 +21,11 @@ #include #include #include -#include "facelet.h" -#include "interface.h" + +#include #include /* *_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 @@ -77,6 +77,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. 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 #include #include "../../common.h" -#include "../../facelet.h" #include "../../interface.h" #include #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 #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 #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 #include -#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 #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 -#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 #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 #include #include +#include // sleep #include #include @@ -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(""); +#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(""); + 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; } -- cgit 1.2.3-korg