From 176f50b6bace73ba225011e4ce3f23bb0aedb989 Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Fri, 23 Jul 2021 13:08:35 +0900 Subject: [PATCH 01/16] Support NAN discovery Change-Id: Id4d0fed38d50ec94206d59a47322af7d1c8e09e5 --- CMakeLists.txt | 2 + include/vine.h | 1 + plugins/nan/nan-plugin.cpp | 80 +++++++++++++++++++++++++++++++++----- src/include/vine-disc-plugin.h | 1 + src/vine-disc.cpp | 6 ++- src/vine-session.cpp | 3 ++ tests/vine-test/vine-test-glib.cpp | 35 +++++++++++++++++ 7 files changed, 117 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c9dfd61..60f50de 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,6 +96,8 @@ IF(NAN_SUPPORT) IF(NOT TIZEN_OS OR NOT USE_EVENT_LOOP_EXTERNAL_GLIB) MESSAGE("NAN is supported in Tizen with external glib loop") SET(NAN_SUPPORT OFF) + ELSE(NOT TIZEN_OS OR NOT USE_EVENT_LOOP_EXTERNAL_GLIB) + ADD_DEFINITIONS("-DNAN_SUPPORT") ENDIF(NOT TIZEN_OS OR NOT USE_EVENT_LOOP_EXTERNAL_GLIB) ENDIF(NAN_SUPPORT) diff --git a/include/vine.h b/include/vine.h index 0544f77..e68d347 100755 --- a/include/vine.h +++ b/include/vine.h @@ -268,6 +268,7 @@ typedef void *vine_security_h; typedef enum { VINE_DISCOVERY_METHOD_DNS_SD = 0, VINE_DISCOVERY_METHOD_BLE, + VINE_DISCOVERY_METHOD_NAN, } vine_discovery_method_e; /** diff --git a/plugins/nan/nan-plugin.cpp b/plugins/nan/nan-plugin.cpp index 0739860..9f2f9a6 100755 --- a/plugins/nan/nan-plugin.cpp +++ b/plugins/nan/nan-plugin.cpp @@ -16,6 +16,7 @@ */ #include +#include #include #include @@ -34,8 +35,10 @@ typedef struct { wifi_aware_publish_h publish_config; wifi_aware_subscribe_h subscribe_config; wifi_aware_session_h session; - //char service_type[NAN_SERVICE_TYPE_LEN + 1]; + std::map peer_map; // + char service_name[VINE_MAX_NAN_SERVICE_NAME_LEN + 1]; + int port; } vine_nan_s; static bool __is_nan_enabled = false; @@ -63,6 +66,7 @@ vine_disc_error nan_resolve_ip(void *plugin_handle, VINE_LOGD("type[%s] name[%s]", service_type, service_name); vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle; + return VINE_DISC_ERROR_NONE; } @@ -84,6 +88,8 @@ vine_disc_error nan_init(void **plugin_handle, void *disc_handle) handle->subscribe_config = nullptr; handle->session = nullptr; + handle->port = -1; + // NAN will be enabled when publish() or subscribe() // because enable function works asynchronously. @@ -97,11 +103,49 @@ void nan_deinit(void *plugin_handle) // TODO // Disable NAN here. - // However, we have to check if NAN is used for data path + // However, we have to check if NAN is used for data path or not + // , and if NAN data path is broken or not when NAN is disabled. delete nan_handle; } +static bool __is_interest_message(const unsigned char *message, size_t len) +{ + // TODO: We have to determine message format. + return true; +} + +static void __open_nan_data_path(wifi_aware_session_h session, + wifi_aware_peer_h peer, vine_nan_s *nan_handle) +{ + VINE_LOGD("Open NAN data path. session[%p]", session); + + wifi_aware_data_path_h ndp; + int ret = wifi_aware_data_path_create(session, peer, &ndp); + + // TODO + // Need to keep ndp +} + +static void __received_cb(wifi_aware_session_h session, wifi_aware_peer_h peer, + const unsigned char *message, size_t len, void *user_data) +{ + RET_IF(!user_data, "user_data is NULL"); + VINE_LOGD("NAN message is received. session[%p], peer[%p], nan_handle[%p]", + session, peer, user_data); + + if (!__is_interest_message(message, len)) { + VINE_LOGD("This message will be not used"); + return; + } + + vine_nan_s *nan_handle = (vine_nan_s *)user_data; + __open_nan_data_path(session, peer, nan_handle); + + // TODO + // Need to keep peer +} + static void __published_cb(wifi_aware_session_h session, wifi_aware_error_e error, void *user_data) { @@ -120,14 +164,25 @@ static void __publish(vine_nan_s *nan_handle) int ret = wifi_aware_session_create(WIFI_AWARE_SESSION_PUBLISH, &session); RET_IF(ret != WIFI_AWARE_ERROR_NONE, "wifi_aware_session_create() fails"); + ret = wifi_aware_session_set_message_received_cb(session, __received_cb, nan_handle); + if (ret != WIFI_AWARE_ERROR_NONE) { + VINE_LOGE("wifi_aware_session_publish() fails"); + goto ERR; + } + + VINE_LOGD("Publish a NAN service"); + ret = wifi_aware_session_publish(session, nan_handle->publish_config, __published_cb, nan_handle); if (ret != WIFI_AWARE_ERROR_NONE) { VINE_LOGE("wifi_aware_session_publish() fails"); - wifi_aware_session_destroy(session); + goto ERR; } nan_handle->session = session; + return; +ERR: + wifi_aware_session_destroy(session); } static void __subscribed_cb(wifi_aware_session_h session, @@ -150,6 +205,8 @@ static void __subscribe(vine_nan_s *nan_handle) int ret = wifi_aware_session_create(WIFI_AWARE_SESSION_SUBSCRIBE, &session); RET_IF(ret != WIFI_AWARE_ERROR_NONE, "wifi_aware_session_create() fails"); + VINE_LOGD("Subscribe a NAN service"); + ret = wifi_aware_session_subscribe(session, nan_handle->subscribe_config, __subscribed_cb, nan_handle); if (ret != WIFI_AWARE_ERROR_NONE) { @@ -173,6 +230,7 @@ static void __start_session(vine_nan_s *nan_handle) static void __stop_session(vine_nan_s *nan_handle) { if (nan_handle->session) { + VINE_LOGD("Stop NAN session"); wifi_aware_session_stop(nan_handle->session); wifi_aware_session_destroy(nan_handle->session); } @@ -181,6 +239,8 @@ static void __stop_session(vine_nan_s *nan_handle) static void __enabled_cb(wifi_aware_error_e error, void *user_data) { RET_IF(!user_data, "nan_handle is NULL"); + + VINE_LOGD("NAN is enabled. nan_handle[%p]", user_data); __start_session((vine_nan_s *)user_data); } @@ -233,13 +293,10 @@ vine_disc_error nan_publish(void *plugin_handle, const char *service_type, "Too long service name"); RET_VAL_IF(__check_attr_len(attributes) == false, VINE_DISC_ERROR_INVALID_PARAMETER, "Too long attributes"); - for (const auto &kv : attributes) { - auto key = kv.first.c_str(); - auto val = kv.second.c_str(); - } vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle; - VINE_LOGD("Publish a service. plugin_handle[%p]\n", plugin_handle); + VINE_LOGD("Publish. plugin_handle[%p], service_type[%s], service_name[%s], port[%d]", + plugin_handle, service_type, service_name, port); strncpy(nan_handle->service_name, service_name, VINE_MAX_NAN_SERVICE_NAME_LEN); @@ -263,8 +320,8 @@ vine_disc_error nan_publish(void *plugin_handle, const char *service_type, } __fill_specific_info(info, service_name, attributes); - nan_handle->publish_config = config; + nan_handle->port = port; // port will be set for NAN data path ret = wifi_aware_enable(__enabled_cb, nan_handle); if (ret != WIFI_AWARE_ERROR_NONE) { @@ -283,6 +340,7 @@ vine_disc_error nan_stop_publish(void *plugin_handle) { RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL"); + VINE_LOGD("Stop publish. plugin_handle[%p]", plugin_handle); vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle; __stop_session(nan_handle); @@ -301,7 +359,8 @@ vine_disc_error nan_subscribe(void *plugin_handle, "Too long service type"); vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle; - VINE_LOGD("Publish a service. plugin_handle[%p]\n", plugin_handle); + VINE_LOGD("Subscribe. plugin_handle[%p], service_type[%s]", + plugin_handle, service_type); wifi_aware_subscribe_h config = nullptr; int ret = wifi_aware_subscribe_create(&config); @@ -339,6 +398,7 @@ vine_disc_error nan_stop_subscribe(void *plugin_handle) { RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL"); + VINE_LOGD("Stop subscribe. plugin_handle[%p]", plugin_handle); vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle; __stop_session(nan_handle); diff --git a/src/include/vine-disc-plugin.h b/src/include/vine-disc-plugin.h index fd8330e..cf36d20 100755 --- a/src/include/vine-disc-plugin.h +++ b/src/include/vine-disc-plugin.h @@ -23,6 +23,7 @@ #define DNS_SD_PLUGIN_PATH "libvine-plugin-dns-sd.so" #define BLE_PLUGIN_PATH "libvine-plugin-ble.so" +#define NAN_PLUGIN_PATH "libvine-plugin-nan.so" using namespace std; diff --git a/src/vine-disc.cpp b/src/vine-disc.cpp index b6ddf24..77083a2 100755 --- a/src/vine-disc.cpp +++ b/src/vine-disc.cpp @@ -34,6 +34,9 @@ static struct { #ifdef BT_SUPPORT [VINE_DISCOVERY_METHOD_BLE] = {"BLE", BLE_PLUGIN_PATH}, #endif +#ifdef NAN_SUPPORT + [VINE_DISCOVERY_METHOD_NAN] = {"NAN", NAN_PLUGIN_PATH}, +#endif {NULL, NULL}, }; @@ -48,6 +51,8 @@ static struct { {NULL, NULL, NULL, NULL, NULL}, NULL}, {{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, {NULL, NULL, NULL, NULL, NULL}, NULL}, + {{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {NULL, NULL, NULL, NULL, NULL}, NULL}, }; typedef struct { @@ -168,7 +173,6 @@ static void __invoke_ip_resolved_user_cb(void *event, void *user_data) disc_handle->ip_resolved_cb_data); } - static void __free_pub_event(void *data) { VINE_LOGD("Free pub_event[%p]", data); diff --git a/src/vine-session.cpp b/src/vine-session.cpp index 6ca5d53..8652e96 100755 --- a/src/vine-session.cpp +++ b/src/vine-session.cpp @@ -170,6 +170,9 @@ static bool __check_disc_method(vine_discovery_method_e method) #ifdef BT_SUPPORT ret = ret || (method == VINE_DISCOVERY_METHOD_BLE); #endif +#ifdef NAN_SUPPORT + ret = ret || (method == VINE_DISCOVERY_METHOD_NAN); +#endif return ret; } diff --git a/tests/vine-test/vine-test-glib.cpp b/tests/vine-test/vine-test-glib.cpp index bfb0deb..b973466 100755 --- a/tests/vine-test/vine-test-glib.cpp +++ b/tests/vine-test/vine-test-glib.cpp @@ -55,6 +55,8 @@ static vine_dp_h g_client_dp = NULL; static vine_dp_h g_pubsub_dp = NULL; static std::list g_datapath_list; static std::list g_service_list; +static int g_disc_method = 0; +static int g_dp_method = 0; static bool test_get_user_string(const char *msg, char *buf, int buf_size) { @@ -83,6 +85,29 @@ static void __quit() exit(1); } +static void __select_method() +{ + if (g_session) { + _test_print_error("Session is already running"); + return; + } + + printf(" >> Select method (0-Default, 1-BLE, 2-NAN): "); + if (scanf(" %d", &g_disc_method) < 1) { + _test_print_error("Scan failed"); + return; + } + + if (g_disc_method < 0 || g_disc_method > 2) { + _test_print_error("Invalid method"); + g_disc_method = 0; + return; + } + + if (g_disc_method == 2) + g_dp_method = 0; +} + static void __init() { PRINT_IF_ERROR(vine_initialize(), "vine_initialize()"); @@ -236,6 +261,11 @@ static void __create_session() return; } + ret = vine_session_set_discovery_method(g_session, (vine_discovery_method_e)g_disc_method); + if (ret != VINE_ERROR_NONE) { + PRINT_IF_ERROR(ret, "vine_session_set_discovery_method"); + return; + } __set_callbacks(); printf("Session Created\n"); } @@ -538,6 +568,7 @@ static void __open_server() } vine_dp_create(g_session, VINE_DP_TYPE_SERVER, &g_server_dp); + vine_dp_set_method(g_server_dp, (vine_dp_method_e)g_dp_method); vine_dp_set_accepted_cb(g_server_dp, __accepted_cb, NULL); vine_dp_set_terminated_cb(g_server_dp, __terminated_cb, NULL); vine_dp_set_address_family(g_server_dp, (vine_address_family_e)addr_family); @@ -581,6 +612,7 @@ static void __connect_server() } vine_dp_create(g_session, VINE_DP_TYPE_CLIENT, &g_client_dp); + vine_dp_set_method(g_client_dp, (vine_dp_method_e)g_dp_method); vine_dp_set_remote_ip(g_client_dp, addr_type ? VINE_ADDRESS_FAMILY_IPV6 : VINE_ADDRESS_FAMILY_IPV4, ip); PRINT_RESULT(vine_dp_set_remote_port(g_client_dp, port), "vine_dp_set_remote_port"); @@ -616,6 +648,7 @@ static void __join_service() } vine_dp_create(g_session, VINE_DP_TYPE_PUBSUB, &g_pubsub_dp); + vine_dp_set_method(g_pubsub_dp, (vine_dp_method_e)g_dp_method); vine_dp_set_address_family(g_pubsub_dp, (vine_address_family_e)addr_family); vine_dp_set_port(g_pubsub_dp, port); vine_dp_set_topic(g_pubsub_dp, topic); @@ -685,6 +718,7 @@ static void __close_data_path() enum { CMD_QUIT = 0, + CMD_SELECT_METHOD, CMD_CREATE_SESSION, CMD_DESTROY_SESSION, CMD_CREATE_SERVICE, @@ -709,6 +743,7 @@ static struct { void (*func)(void); } __menus[] = { [CMD_QUIT] = {"quit", __quit}, + [CMD_SELECT_METHOD] = {"Select method", __select_method}, [CMD_CREATE_SESSION] = {"Create session", __create_session}, [CMD_DESTROY_SESSION] = {"Destroy session", __destroy_session}, [CMD_CREATE_SERVICE] = {"Create service", __create_service}, -- 2.7.4 From c6a0e2b2475337ded684ae1a7c2f15c0ed975cca Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Mon, 26 Jul 2021 21:09:13 +0900 Subject: [PATCH 02/16] Integrate ble_discovered_cb with discovered_cb To identify peer device, host name or MAC address may be used. DNS-SD uses host name while BLE and NAN use MAC address. Change-Id: I4ac6deaea26ed4551c3b7dd1de65a3d5719d0a8f Signed-off-by: Cheoleun Moon --- plugins/ble/ble-plugin.cpp | 13 +++++---- plugins/dns-sd/dns-sd-plugin.cpp | 6 ++-- plugins/nan/nan-plugin.cpp | 5 ++-- src/include/vine-disc-plugin.h | 7 ++--- src/include/vine-disc.h | 4 +-- src/vine-disc.cpp | 48 +++++++------------------------ src/vine-dp.cpp | 4 +-- src/vine-session.cpp | 14 ++++----- tests/unittest/mocks/vine-mock-dns-sd.cpp | 2 +- 9 files changed, 37 insertions(+), 66 deletions(-) mode change 100644 => 100755 tests/unittest/mocks/vine-mock-dns-sd.cpp diff --git a/plugins/ble/ble-plugin.cpp b/plugins/ble/ble-plugin.cpp index 4388042..3896483 100755 --- a/plugins/ble/ble-plugin.cpp +++ b/plugins/ble/ble-plugin.cpp @@ -149,7 +149,7 @@ static vine_disc_error __convert_ble_error_to_vine_disc_error(int error) vine_disc_error ble_resolve_ip(void *plugin_handle, const char *service_type, const char *service_name, - const char *host_name, const char *iface_name, int family) + const char *host_name, const char *mac, const char *iface_name, int family) { VINE_LOGE("Not supported function"); return VINE_DISC_ERROR_NOT_SUPPORTED; @@ -348,10 +348,12 @@ static void __le_scan_result_cb(int result, bt_adapter_le_device_scan_result_inf char mac[VINE_MAC_LEN + 1] = {0, }; strncpy(mac, info->remote_address, VINE_MAC_LEN); - if (event_callbacks.ble_discovered_cb) { + if (event_callbacks.discovered_cb) { std::map empty_map; - event_callbacks.ble_discovered_cb(ble_handle, true, - ble_handle->service_type, service_name, mac, ble_handle->disc_handle); + event_callbacks.discovered_cb(ble_handle, true, + ble_handle->service_type, service_name, + nullptr, mac, -1, empty_map, + nullptr, 0, ble_handle->disc_handle); } } @@ -423,11 +425,10 @@ vine_disc_error ble_process_event(void *plugin_handle, int fd) void ble_register_callbacks(vine_disc_plugin_callbacks callbacks) { event_callbacks.published_cb = callbacks.published_cb; - event_callbacks.discovered_cb = NULL; + event_callbacks.discovered_cb = callbacks.discovered_cb; event_callbacks.ip_resolved_cb = NULL; event_callbacks.fd_added_cb = NULL; event_callbacks.fd_removed_cb = NULL; - event_callbacks.ble_discovered_cb = callbacks.ble_discovered_cb; } void vine_disc_plugin_init(vine_disc_plugin_fn *fn) diff --git a/plugins/dns-sd/dns-sd-plugin.cpp b/plugins/dns-sd/dns-sd-plugin.cpp index f741843..7637bb5 100755 --- a/plugins/dns-sd/dns-sd-plugin.cpp +++ b/plugins/dns-sd/dns-sd-plugin.cpp @@ -325,7 +325,7 @@ static DNSServiceProtocol get_protocol(int family) vine_disc_error dns_sd_resolve_ip(void *plugin_handle, const char *service_type, const char *service_name, - const char *host_name, const char *iface_name, int family) + const char *host_name, const char *mac, const char *iface_name, int family) { RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL"); RET_VAL_IF(!service_type, VINE_DISC_ERROR_INVALID_PARAMETER, "service_type is NULL"); @@ -400,7 +400,7 @@ static void __resolve_reply(DNSServiceRef sdRef, unsigned int flags, char iface_name[IF_NAMESIZE + 1] = {0, }; if (if_indextoname(if_index, iface_name)) event_callbacks.discovered_cb(dns_sd_handle, true, - service->service_type, service->service_name, host_name, + service->service_type, service->service_name, host_name, nullptr, service->port, service->attributes, iface_name, flags & kDNSServiceFlagsMoreComing, dns_sd_handle->user_data); else @@ -472,7 +472,7 @@ static void __browse_reply(DNSServiceRef sdRef, unsigned int flags, map empty_map; if (event_callbacks.discovered_cb) event_callbacks.discovered_cb(dns_sd_handle, false, - dns_sd_handle->service_type, service_name, NULL, + dns_sd_handle->service_type, service_name, nullptr, nullptr, 0, empty_map, iface_name, flags & kDNSServiceFlagsMoreComing, dns_sd_handle->user_data); diff --git a/plugins/nan/nan-plugin.cpp b/plugins/nan/nan-plugin.cpp index 9f2f9a6..3bcadb8 100755 --- a/plugins/nan/nan-plugin.cpp +++ b/plugins/nan/nan-plugin.cpp @@ -52,7 +52,7 @@ static vine_disc_error __convert_nan_error_to_vine_disc_error(int error) vine_disc_error nan_resolve_ip(void *plugin_handle, const char *service_type, const char *service_name, - const char *host_name, const char *iface_name, int family) + const char *host_name, const char *mac, const char *iface_name, int family) { RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL"); RET_VAL_IF(!service_type, VINE_DISC_ERROR_INVALID_PARAMETER, "service_type is NULL"); @@ -195,7 +195,7 @@ static void __subscribed_cb(wifi_aware_session_h session, if (event_callbacks.discovered_cb) { std::map empty_map; event_callbacks.discovered_cb(nan_handle, false, - nullptr, nullptr, nullptr, -1, empty_map, nullptr, 0, nan_handle->disc_handle); + nullptr, nullptr, nullptr, nullptr, -1, empty_map, nullptr, 0, nan_handle->disc_handle); } } @@ -416,7 +416,6 @@ void nan_register_callbacks(vine_disc_plugin_callbacks callbacks) event_callbacks.ip_resolved_cb = callbacks.ip_resolved_cb; event_callbacks.fd_added_cb = nullptr; event_callbacks.fd_removed_cb = nullptr; - event_callbacks.ble_discovered_cb = nullptr; } vine_disc_error nan_process_event(void *plugin_handle, int fd) diff --git a/src/include/vine-disc-plugin.h b/src/include/vine-disc-plugin.h index cf36d20..60eac58 100755 --- a/src/include/vine-disc-plugin.h +++ b/src/include/vine-disc-plugin.h @@ -54,16 +54,13 @@ typedef struct { const char *service_name, vine_disc_error error, void *disc_handle); void (*discovered_cb)(void *plugin_handle, bool available, const char *service_type, const char *service_name, - const char *host_name, int port, const map &attr, + const char *host_name, const char *mac, int port, const map &attr, const char *iface_name, int more_coming, void *disc_handle); void (*ip_resolved_cb)(void *plugin_handle, bool add, const char *ip, sa_family_t address_family, void *disc_handle); void (*fd_added_cb)(int fd, void *disc_handle); void (*fd_removed_cb)(int fd, void *disc_handle); - void (*ble_discovered_cb)(void *plugin_handle, bool available, - const char *service_type, const char *service_name, const char *mac, - void *disc_handle); } vine_disc_plugin_callbacks; typedef struct { @@ -79,7 +76,7 @@ typedef struct { vine_disc_error (*stop_subscribe)(void *plugin_handle); vine_disc_error (*resolve_ip)(void *plugin_handle, const char *service_type, const char *service_name, - const char *host_name, const char *iface_name, int family); + const char *host_name, const char *mac, const char *iface_name, int family); vine_disc_error (*cancel_resolve_ip)(void *plugin_handle); vine_disc_error (*process_event)(void *plugin_handle, int fd); diff --git a/src/include/vine-disc.h b/src/include/vine-disc.h index 42faa43..820a9c9 100755 --- a/src/include/vine-disc.h +++ b/src/include/vine-disc.h @@ -31,8 +31,8 @@ typedef void (*vine_disc_published_cb)(vine_disc_h disc, const char *service_name, vine_error_e error, void *user_data); typedef void (*vine_disc_discovered_cb)(vine_disc_h disc, bool available, const char *service_type, const char *service_name, - const char *host_name, int port, const map &attr, - const char *iface_name, int more_coming, const char *mac, void *user_data); + const char *host_name, const char *mac, int port, const map &attr, + const char *iface_name, int more_coming, void *user_data); typedef void (*vine_disc_ip_resolved_cb)(vine_disc_h disc, vine_service_h service, bool add, const char *ip, vine_address_family_e address_family, void *user_data); diff --git a/src/vine-disc.cpp b/src/vine-disc.cpp index 77083a2..084172d 100755 --- a/src/vine-disc.cpp +++ b/src/vine-disc.cpp @@ -146,11 +146,11 @@ static void __invoke_discovered_user_cb(void *event, void *user_data) discovered_event->service_type, discovered_event->service_name, discovered_event->host_name, + discovered_event->mac, discovered_event->port, discovered_event->attributes, discovered_event->iface_name, discovered_event->more_coming, - discovered_event->mac, disc_handle->discovered_cb_data); } @@ -217,15 +217,15 @@ static void __published_cb(void *plugin_handle, static void __discovered_cb(void *plugin_handle, bool available, const char *service_type, const char *service_name, - const char *host_name, int port, const map &attr, + const char *host_name, const char *mac, int port, const map &attr, const char *iface_name, int more_coming, void *user_data) { RET_IF(service_type == NULL, "service type is NULL"); RET_IF(service_name == NULL, "service_name type is NULL"); VINE_LOGD("Discovered callback from plugin available[%d]", available); - VINE_LOGD("service type[%s] service_name[%s] host_name[%s] port[%d] iface[%s] user_data[%p]", - service_type, service_name, host_name, port, iface_name, user_data); + VINE_LOGD("service type[%s] service_name[%s] host_name[%s] mac[%s] port[%d] iface[%s] user_data[%p]", + service_type, service_name, host_name, mac, port, iface_name, user_data); vine_discovered_event *discovered_event = new vine_discovered_event; @@ -235,6 +235,12 @@ static void __discovered_cb(void *plugin_handle, bool available, strncpy(discovered_event->iface_name, iface_name, IF_NAMESIZE); if (host_name != NULL) strncpy(discovered_event->host_name, host_name, VINE_MAX_HOST_NAME_LEN); + else + memset(discovered_event->host_name, 0, VINE_MAX_HOST_NAME_LEN + 1); + if (mac != NULL) + strncpy(discovered_event->mac, mac, VINE_MAC_LEN); + else + memset(discovered_event->mac, 0, VINE_MAC_LEN + 1); discovered_event->port = port; discovered_event->attributes = attr; @@ -251,37 +257,6 @@ static void __discovered_cb(void *plugin_handle, bool available, __free_discovered_event(discovered_event); } -static void __ble_discovered_cb(void *plugin_handle, bool available, - const char *service_type, const char *service_name, const char *mac, - void *user_data) -{ - RET_IF(service_type == NULL, "service type is NULL"); - RET_IF(service_name == NULL, "service_name type is NULL"); - RET_IF(mac == NULL, "service mac is NULL"); - - VINE_LOGD("Discovered callback from plugin available[%d]", available); - VINE_LOGD("service type[%s] service_name[%s] mac[%s] user_data[%p]", - service_type, service_name, mac, user_data); - - vine_discovered_event *discovered_event = new vine_discovered_event; - - discovered_event->available = available; - strncpy(discovered_event->service_type, service_type, VINE_MAX_SERVICE_TYPE_LEN); - strncpy(discovered_event->service_name, service_name, VINE_MAX_SERVICE_NAME_LEN); - strncpy(discovered_event->mac, mac, VINE_MAC_LEN); - discovered_event->port = -1; - - VINE_LOGD("Create a discovered_event[%p]", discovered_event); - - vine_disc_s *disc_handle = (vine_disc_s *)user_data; - if (disc_handle) { - if (vine_event_loop_add_event(disc_handle->event_queue, discovered_event, - __invoke_discovered_user_cb, __free_discovered_event, user_data) == VINE_ERROR_NONE) - return; - } - __free_discovered_event(discovered_event); -} - static void __ip_resolved_cb(void *plugin_handle, bool add, const char *ip, sa_family_t address_family, void *user_data) { @@ -375,7 +350,6 @@ static void __init_plugins() __vine_disc_plugins[i].callbacks.ip_resolved_cb = __ip_resolved_cb; __vine_disc_plugins[i].callbacks.fd_added_cb = __fd_added_cb; __vine_disc_plugins[i].callbacks.fd_removed_cb = __fd_removed_cb; - __vine_disc_plugins[i].callbacks.ble_discovered_cb = __ble_discovered_cb; __vine_disc_plugins[i].fn.register_callbacks(__vine_disc_plugins[i].callbacks); } } @@ -683,7 +657,7 @@ vine_error_e __vine_disc_plugin_resolve_ip(vine_disc_h disc, vine_service_h serv } error = disc_handle->plugin_fn->resolve_ip(plugin_handle, _vine_service_get_type(service), _vine_service_get_name(service), - _vine_service_get_host_name(service), _vine_service_get_iface_name(service), + _vine_service_get_host_name(service), nullptr, _vine_service_get_iface_name(service), (int)_vine_service_get_address_family(service)); if (error != VINE_DISC_ERROR_NONE) { VINE_LOGE("Fail to resolve ip %d", error); diff --git a/src/vine-dp.cpp b/src/vine-dp.cpp index e66715f..94a94d0 100755 --- a/src/vine-dp.cpp +++ b/src/vine-dp.cpp @@ -327,8 +327,8 @@ static std::string __get_full_topic(const map &attr) static void _service_discovered_cb(vine_disc_h disc, bool available, const char *service_type, const char *service_name, - const char *host_name, int port, const map &attr, - const char *iface_name, int more_coming, const char *mac, void *user_data) + const char *host_name, const char *mac, int port, const map &attr, + const char *iface_name, int more_coming, void *user_data) { VINE_LOGD("%s is discovered. %s", service_name, available ? "available" : "not available"); diff --git a/src/vine-session.cpp b/src/vine-session.cpp index 8652e96..4415aef 100755 --- a/src/vine-session.cpp +++ b/src/vine-session.cpp @@ -262,8 +262,8 @@ int _vine_session_unregister(vine_session_h session) static int __vine_set_discovered_service(vine_service_h service, const char *service_type, const char *service_name, - const char *host_name, int port, const map &attr, - const char *iface_name, const char *mac) + const char *host_name, const char *mac, int port, const map &attr, + const char *iface_name) { int ret = VINE_ERROR_NONE; ret = _vine_service_set_type(service, service_type); @@ -272,6 +272,8 @@ static int __vine_set_discovered_service(vine_service_h service, RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to set service name"); ret = _vine_service_set_host_name(service, host_name); RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to set host name"); + ret = _vine_service_set_mac(service, mac); + RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to set mac"); if (port >= 0) { ret = _vine_service_set_port(service, port); @@ -284,15 +286,13 @@ static int __vine_set_discovered_service(vine_service_h service, ret = _vine_service_set_iface_name(service, iface_name); RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to set iface_name"); - ret = _vine_service_set_mac(service, mac); - RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to set mac"); return VINE_ERROR_NONE; } static void __discovered_cb(vine_disc_h disc, bool available, const char *service_type, const char *service_name, - const char *host_name, int port, const map &attr, - const char *iface_name, int more_coming, const char *mac, void *user_data) + const char *host_name, const char *mac, int port, const map &attr, + const char *iface_name, int more_coming, void *user_data) { VINE_LOGD("Service is discovered. Available[%d]", available); int ret = VINE_ERROR_NONE; @@ -306,7 +306,7 @@ static void __discovered_cb(vine_disc_h disc, bool available, RET_IF(ret != VINE_ERROR_NONE, "Fail to create a service"); ret = __vine_set_discovered_service(discovered_service, - service_type, service_name, host_name, port, attr, iface_name, mac); + service_type, service_name, host_name, mac, port, attr, iface_name); if (ret != VINE_ERROR_NONE) { VINE_LOGE("Fail to set a service. error(%d)", ret); _vine_service_destroy(discovered_service); diff --git a/tests/unittest/mocks/vine-mock-dns-sd.cpp b/tests/unittest/mocks/vine-mock-dns-sd.cpp old mode 100644 new mode 100755 index c574d79..a51c9dd --- a/tests/unittest/mocks/vine-mock-dns-sd.cpp +++ b/tests/unittest/mocks/vine-mock-dns-sd.cpp @@ -74,7 +74,7 @@ vine_disc_error __mock_disc_plugin_stop_subscribe(void *plugin_handle) vine_disc_error __mock_disc_plugin_resolve_ip(void *plugin_handle, const char *service_type, const char *service_name, - const char *host_name, const char *iface_name, int family) + const char *host_name, const char *mac, const char *iface_name, int family) { return VINE_DISC_ERROR_NONE; } -- 2.7.4 From 20d9305138dda490dde6fadc7cc31849bef4ef7d Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Wed, 28 Jul 2021 13:55:39 +0900 Subject: [PATCH 03/16] nan-plugin: add resolve_ip Change-Id: Ib0d10a908b4ba73baedf07629004bfc56bf1768e --- include/vine.h | 1 + packaging/capi-network-vine.spec | 2 +- plugins/nan/nan-plugin.cpp | 315 ++++++++++++++++++++++++++++++++------- plugins/nan/nan-plugin.h | 1 + 4 files changed, 261 insertions(+), 58 deletions(-) diff --git a/include/vine.h b/include/vine.h index e68d347..fd77cbc 100755 --- a/include/vine.h +++ b/include/vine.h @@ -463,6 +463,7 @@ int vine_session_unset_registered_cb(vine_session_h session); /** * @brief Called when service is discovered. * @remarks @a service will be freed after this callback. Use @a vine_service_clone(). + * @remarks If there is an internal error, @a service will be NULL. * @since_tizen 6.5 * @param[in] session The session handle * @param[in] discovered_service The discovered service diff --git a/packaging/capi-network-vine.spec b/packaging/capi-network-vine.spec index 105abde..1b5adbb 100755 --- a/packaging/capi-network-vine.spec +++ b/packaging/capi-network-vine.spec @@ -3,7 +3,7 @@ %bcond_without use_glib_event_loop Name: capi-network-vine Summary: An service discovery framework -Version: 1.1.7 +Version: 1.1.8 Release: 0 Group: Network & Connectivity/API License: Apache-2.0 diff --git a/plugins/nan/nan-plugin.cpp b/plugins/nan/nan-plugin.cpp index 3bcadb8..ef108e8 100755 --- a/plugins/nan/nan-plugin.cpp +++ b/plugins/nan/nan-plugin.cpp @@ -18,6 +18,8 @@ #include #include +#include + #include #include #include @@ -35,9 +37,11 @@ typedef struct { wifi_aware_publish_h publish_config; wifi_aware_subscribe_h subscribe_config; wifi_aware_session_h session; - std::map peer_map; // + std::map peers; // + std::map ndps; // - char service_name[VINE_MAX_NAN_SERVICE_NAME_LEN + 1]; + char published_service_name[VINE_MAX_NAN_SERVICE_NAME_LEN + 1]; + char service_type[VINE_MAX_NAN_SERVICE_TYPE_LEN + 1]; int port; } vine_nan_s; @@ -49,6 +53,132 @@ static vine_disc_error __convert_nan_error_to_vine_disc_error(int error) return VINE_DISC_ERROR_NONE; } +static bool __is_data_path_request_message(const unsigned char *message, size_t len) +{ + RET_VAL_IF(len != strlen(VINE_FOLLOWUP_MESSAGE), false, "Wrong message"); + return memcmp(message, VINE_FOLLOWUP_MESSAGE, strlen(VINE_FOLLOWUP_MESSAGE)) == 0; +} + +static void __add_ndp(vine_nan_s *nan_handle, + wifi_aware_data_path_h ndp, wifi_aware_peer_h peer) +{ + VINE_LOGD("Add NDP[%p]. peer[%p]", ndp, peer); + auto v = nan_handle->ndps.find(peer); + if (v == nan_handle->ndps.end()) { + // TODO: Can the same peer request NAN data path? + } + nan_handle->ndps[peer] = ndp; +} + +static void __terminated_cb(wifi_aware_data_path_h ndp, + wifi_aware_termination_reason_e reason, void *user_data) +{ + VINE_LOGD("NDP is terminated [%p]. reason[%d]", ndp, (int)reason); + + vine_nan_s *nan_handle = (vine_nan_s *)user_data; + if (event_callbacks.ip_resolved_cb) + event_callbacks.ip_resolved_cb(nan_handle, false, + nullptr, VINE_DISC_ADDR_FAMILY_IPV6, nan_handle->disc_handle); +} + +static void __open_cb(wifi_aware_data_path_h ndp, + wifi_aware_error_e error, void *user_data) +{ + RET_IF(!event_callbacks.ip_resolved_cb, "No callbacks"); + + char *ipv6; + if (wifi_aware_data_path_get_peer_ipv6_address(ndp, &ipv6) != WIFI_AWARE_ERROR_NONE) { + VINE_LOGE("wifi_aware_data_path_get_peer_ipv6_address() fails"); + return; + } + + vine_nan_s *nan_handle = (vine_nan_s *)user_data; + + event_callbacks.ip_resolved_cb(nan_handle, true, + ipv6, VINE_DISC_ADDR_FAMILY_IPV6, nan_handle->disc_handle); + g_free(ipv6); +} + +static void __open_nan_data_path(wifi_aware_session_h session, + wifi_aware_peer_h peer, vine_nan_s *nan_handle) +{ + VINE_LOGD("Open NAN data path. session[%p]", session); + + /* + std::string mac; + bool found = false; + for (const auto &kv : nan_handle->peers) { + if (kv.second == peer) { + mac = kv.first; + found = true; + break; + } + } + + if (!found) { + VINE_LOGE("Invalid peer"); + return; + } + */ + + wifi_aware_data_path_h ndp; + if (wifi_aware_data_path_create(session, peer, &ndp) != WIFI_AWARE_ERROR_NONE) { + VINE_LOGE("wifi_aware_data_path_create() fails"); + return; + } + + if (wifi_aware_data_path_set_terminated_cb(ndp, __terminated_cb, nan_handle) + != WIFI_AWARE_ERROR_NONE) { + VINE_LOGE("wifi_aware_data_path_set_terminated_cb() fails"); + return; + } + + if (wifi_aware_data_path_open(ndp, __open_cb, nan_handle) != WIFI_AWARE_ERROR_NONE) { + VINE_LOGE("wifi_aware_data_path_open() fails"); + return; + } + + // TODO: Need to maintain ndp list? + __add_ndp(nan_handle, ndp, peer); +} + +static void __received_cb(wifi_aware_session_h session, wifi_aware_peer_h peer, + const unsigned char *message, size_t len, void *user_data) +{ + RET_IF(!user_data, "user_data is NULL"); + VINE_LOGD("NAN message is received. session[%p], peer[%p], nan_handle[%p]", + session, peer, user_data); + + if (!__is_data_path_request_message(message, len)) { + VINE_LOGD("This message will be not used"); + return; + } + + __open_nan_data_path(session, peer, (vine_nan_s *)user_data); +} + +static void __message_result_cb(wifi_aware_session_h session, + wifi_aware_error_e error, void *user_data) +{ + if (error == WIFI_AWARE_ERROR_NONE) { + VINE_LOGD("Message is successfully sent"); + return; + } + + // TODO + // How can inform the failure to app? + // Use ip_resolved_cb with nullptr IP address? + // Then, in terminated_cb, I think ip_resolved_cb is called with ip address (add is false) +} + +static int __send_nan_dp_request(wifi_aware_session_h session, + wifi_aware_peer_h peer, vine_nan_s *nan_handle) +{ + VINE_LOGD("Send NAN Datapath request message"); + return wifi_aware_session_send_message(session, peer, + (unsigned char *)VINE_FOLLOWUP_MESSAGE, strlen(VINE_FOLLOWUP_MESSAGE), + __message_result_cb, nan_handle); +} vine_disc_error nan_resolve_ip(void *plugin_handle, const char *service_type, const char *service_name, @@ -57,17 +187,30 @@ vine_disc_error nan_resolve_ip(void *plugin_handle, RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL"); RET_VAL_IF(!service_type, VINE_DISC_ERROR_INVALID_PARAMETER, "service_type is NULL"); RET_VAL_IF(!service_name, VINE_DISC_ERROR_INVALID_PARAMETER, "service_name is NULL"); + RET_VAL_IF(!mac, VINE_DISC_ERROR_INVALID_PARAMETER, "mac is NULL"); // Ignore host_name and iface_name - RET_VAL_IF(family == VINE_DISC_ADDR_FAMILY_IPV4, VINE_DISC_ERROR_NOT_SUPPORTED, "Only IPv6 is allowed for NAN"); + vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle; + RET_VAL_IF(nan_handle->peers.find(mac) == nan_handle->peers.end(), + VINE_DISC_ERROR_INVALID_PARAMETER, "Invalid mac[%s]", mac); + VINE_LOGD("Start to resolve IP. plugin_handle[%p]\n", plugin_handle); - VINE_LOGD("type[%s] name[%s]", service_type, service_name); + VINE_LOGD("type[%s] name[%s] mac[%s]", service_type, service_name, mac); - vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle; + int ret = wifi_aware_session_set_message_received_cb(nan_handle->session, + __received_cb, nan_handle); + if (ret != WIFI_AWARE_ERROR_NONE) { + VINE_LOGE("wifi_aware_session_set_message_received_cb() fails"); + return __convert_nan_error_to_vine_disc_error(ret); + } - return VINE_DISC_ERROR_NONE; + ret = __send_nan_dp_request(nan_handle->session, nan_handle->peers[mac], nan_handle); + if (ret != WIFI_AWARE_ERROR_NONE) + VINE_LOGE("__send_nan_dp_request() fails"); + + return __convert_nan_error_to_vine_disc_error(ret); } vine_disc_error nan_cancel_resolve_ip(void *plugin_handle) @@ -102,50 +245,13 @@ void nan_deinit(void *plugin_handle) vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle; // TODO - // Disable NAN here. + // Disable NAN here? // However, we have to check if NAN is used for data path or not // , and if NAN data path is broken or not when NAN is disabled. delete nan_handle; } -static bool __is_interest_message(const unsigned char *message, size_t len) -{ - // TODO: We have to determine message format. - return true; -} - -static void __open_nan_data_path(wifi_aware_session_h session, - wifi_aware_peer_h peer, vine_nan_s *nan_handle) -{ - VINE_LOGD("Open NAN data path. session[%p]", session); - - wifi_aware_data_path_h ndp; - int ret = wifi_aware_data_path_create(session, peer, &ndp); - - // TODO - // Need to keep ndp -} - -static void __received_cb(wifi_aware_session_h session, wifi_aware_peer_h peer, - const unsigned char *message, size_t len, void *user_data) -{ - RET_IF(!user_data, "user_data is NULL"); - VINE_LOGD("NAN message is received. session[%p], peer[%p], nan_handle[%p]", - session, peer, user_data); - - if (!__is_interest_message(message, len)) { - VINE_LOGD("This message will be not used"); - return; - } - - vine_nan_s *nan_handle = (vine_nan_s *)user_data; - __open_nan_data_path(session, peer, nan_handle); - - // TODO - // Need to keep peer -} - static void __published_cb(wifi_aware_session_h session, wifi_aware_error_e error, void *user_data) { @@ -154,7 +260,7 @@ static void __published_cb(wifi_aware_session_h session, if (event_callbacks.published_cb) event_callbacks.published_cb(nan_handle, - nan_handle->service_name, __convert_nan_error_to_vine_disc_error(error), + nan_handle->published_service_name, __convert_nan_error_to_vine_disc_error(error), nan_handle->disc_handle); } @@ -185,20 +291,104 @@ ERR: wifi_aware_session_destroy(session); } -static void __subscribed_cb(wifi_aware_session_h session, - wifi_aware_error_e error, void *user_data) +static bool __get_attributes(const unsigned char *info, size_t len, map &attr) { - RET_IF(error == WIFI_AWARE_ERROR_NONE, "No error"); + VINE_LOGD("Get Attributes"); + + const unsigned char *ptr = &info[VINE_MAX_NAN_SERVICE_NAME_LEN]; + const unsigned char *max = info + len; + char key_buf[MAX_SPECIFIC_INFO_LEN + 1]; + char value_buf[MAX_SPECIFIC_INFO_LEN + 1]; + + while (ptr < max) { + const unsigned char *const end = ptr + 1 + ptr[0]; + if (end > max) { + VINE_LOGE("Invalid attribute"); + return false; + } + char *buf = &key_buf[0]; + while (++ptr < end) { + if (*ptr == '=') { + *buf = 0; + buf = &value_buf[0]; + } else { + *buf = *ptr; + ++buf; + } + } + *buf = 0; + VINE_LOGD("Key[%s] Value[%s]", key_buf, value_buf); + string key(key_buf); + string value(value_buf); + attr[key] = value; + } + return true; +} + +static void __add_peer(vine_nan_s *nan_handle, wifi_aware_peer_h peer, const char *mac) +{ + VINE_LOGD("Add peer[%p]. mac[%s]", peer, mac); + nan_handle->peers[mac] = peer; +} + +static void __discovered_cb(wifi_aware_session_h session, + wifi_aware_peer_h peer, const unsigned char *service_specific_info, size_t len, + int distance, void *user_data) +{ + VINE_LOGD("Service Discovered. session[%p] peer[%p]", session, peer); + RET_IF(event_callbacks.discovered_cb == NULL, "discovered_cb is NULL"); + + if (len > MAX_SPECIFIC_INFO_LEN || len < VINE_MAX_NAN_SERVICE_NAME_LEN) { + VINE_LOGE("Invalid info len[%d]", len); + return; + } + + char service_name[VINE_MAX_SERVICE_NAME_LEN + 1]; + memcpy(service_name, service_specific_info, VINE_MAX_NAN_SERVICE_NAME_LEN); + service_name[VINE_MAX_NAN_SERVICE_NAME_LEN] = 0; + + map attributes; + if (__get_attributes(service_specific_info, len, attributes) == false) + return; + + char *mac; + int ret = wifi_aware_peer_get_mac(peer, (unsigned char **)&mac); + RET_IF(ret != WIFI_AWARE_ERROR_NONE, "wifi_aware_peer_get_mac() fails"); + vine_nan_s *nan_handle = (vine_nan_s *)user_data; + __add_peer(nan_handle, peer, mac); + g_free(mac); - VINE_LOGE("Fails to subscribe. error: %s", __convert_nan_error_to_vine_disc_error(error)); + event_callbacks.discovered_cb(nan_handle, true, + nan_handle->service_type, service_name, nullptr, + mac, -1, attributes, nullptr, 0, + nan_handle->disc_handle); +} + +/** + * When NAN subscription is failed, it is informed with discovered_cb. + * If service_type and service_name are nullptr, it is considered as an error. + * vine_session_discovered_cb will be called with NULL vine_service_h. + */ +static void __subscribe_failed(vine_nan_s *nan_handle) +{ if (event_callbacks.discovered_cb) { std::map empty_map; event_callbacks.discovered_cb(nan_handle, false, - nullptr, nullptr, nullptr, nullptr, -1, empty_map, nullptr, 0, nan_handle->disc_handle); + nullptr, nullptr, nullptr, nullptr, -1, empty_map, nullptr, 0, + nan_handle->disc_handle); } } +static void __subscribed_cb(wifi_aware_session_h session, + wifi_aware_error_e error, void *user_data) +{ + RET_IF(error == WIFI_AWARE_ERROR_NONE, "No error"); + + VINE_LOGE("Fails to subscribe. error: %s", __convert_nan_error_to_vine_disc_error(error)); + __subscribe_failed((vine_nan_s *)user_data); +} + static void __subscribe(vine_nan_s *nan_handle) { wifi_aware_session_h session; @@ -207,14 +397,25 @@ static void __subscribe(vine_nan_s *nan_handle) VINE_LOGD("Subscribe a NAN service"); - ret = wifi_aware_session_subscribe(session, nan_handle->subscribe_config, - __subscribed_cb, nan_handle); + ret = wifi_aware_session_set_service_discovered_cb(session, __discovered_cb, nan_handle); + if (ret != WIFI_AWARE_ERROR_NONE) { + VINE_LOGE("wifi_aware_session_publish() fails"); + goto ERR; + } + + ret = wifi_aware_session_subscribe(session, + nan_handle->subscribe_config, __subscribed_cb, nan_handle); if (ret != WIFI_AWARE_ERROR_NONE) { VINE_LOGE("wifi_aware_session_publish() fails"); - wifi_aware_session_destroy(session); + goto ERR; } nan_handle->session = session; + return; + +ERR: + wifi_aware_session_destroy(session); + __subscribe_failed(nan_handle); } static void __start_session(vine_nan_s *nan_handle) @@ -298,8 +499,6 @@ vine_disc_error nan_publish(void *plugin_handle, const char *service_type, VINE_LOGD("Publish. plugin_handle[%p], service_type[%s], service_name[%s], port[%d]", plugin_handle, service_type, service_name, port); - strncpy(nan_handle->service_name, service_name, VINE_MAX_NAN_SERVICE_NAME_LEN); - wifi_aware_publish_h config = nullptr; int ret = wifi_aware_publish_create(&config); RET_VAL_IF(ret != WIFI_AWARE_ERROR_NONE, __convert_nan_error_to_vine_disc_error(ret), @@ -320,8 +519,6 @@ vine_disc_error nan_publish(void *plugin_handle, const char *service_type, } __fill_specific_info(info, service_name, attributes); - nan_handle->publish_config = config; - nan_handle->port = port; // port will be set for NAN data path ret = wifi_aware_enable(__enabled_cb, nan_handle); if (ret != WIFI_AWARE_ERROR_NONE) { @@ -329,6 +526,10 @@ vine_disc_error nan_publish(void *plugin_handle, const char *service_type, goto ERR; } + nan_handle->publish_config = config; + nan_handle->port = port; // port will be set for NAN data path + strncpy(nan_handle->published_service_name, service_name, VINE_MAX_SERVICE_NAME_LEN); + return VINE_DISC_ERROR_NONE; ERR: diff --git a/plugins/nan/nan-plugin.h b/plugins/nan/nan-plugin.h index 890b51e..47ebd51 100755 --- a/plugins/nan/nan-plugin.h +++ b/plugins/nan/nan-plugin.h @@ -18,3 +18,4 @@ #define NAN_MAX_SERVICE_NAME_LEN 255 #define MAX_SPECIFIC_INFO_LEN 1024 +#define VINE_FOLLOWUP_MESSAGE "VINE_REQ_NAN_DATAPATH" -- 2.7.4 From 9c69a3c53226759044f6f420f51c97ff0f524668 Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Wed, 28 Jul 2021 16:18:44 +0900 Subject: [PATCH 04/16] nan-plugin: add NAN init/deinit Change-Id: I8c342786e9908a5a25ef80526036afd203ff4cd3 Signed-off-by: Cheoleun Moon --- plugins/nan/nan-plugin.cpp | 16 ++++++++++++++-- tests/vine-test/vine-test-glib.cpp | 12 ++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/plugins/nan/nan-plugin.cpp b/plugins/nan/nan-plugin.cpp index ef108e8..8393d61 100755 --- a/plugins/nan/nan-plugin.cpp +++ b/plugins/nan/nan-plugin.cpp @@ -224,7 +224,14 @@ vine_disc_error nan_cancel_resolve_ip(void *plugin_handle) vine_disc_error nan_init(void **plugin_handle, void *disc_handle) { + int ret = wifi_aware_initialize(); + if (ret != WIFI_AWARE_ERROR_NONE && ret != WIFI_AWARE_ERROR_ALREADY_INITIALIZED) { + VINE_LOGE("wifi_aware_initialize() fails"); + return __convert_nan_error_to_vine_disc_error(ret); + } + vine_nan_s *handle = new vine_nan_s; + VINE_LOGD("Create plugin_handle[%p]", handle); handle->disc_handle = disc_handle; handle->publish_config = nullptr; @@ -233,6 +240,7 @@ vine_disc_error nan_init(void **plugin_handle, void *disc_handle) handle->port = -1; + *plugin_handle = handle; // NAN will be enabled when publish() or subscribe() // because enable function works asynchronously. @@ -250,6 +258,7 @@ void nan_deinit(void *plugin_handle) // , and if NAN data path is broken or not when NAN is disabled. delete nan_handle; + wifi_aware_deinitialize(); } static void __published_cb(wifi_aware_session_h session, @@ -383,9 +392,12 @@ static void __subscribe_failed(vine_nan_s *nan_handle) static void __subscribed_cb(wifi_aware_session_h session, wifi_aware_error_e error, void *user_data) { - RET_IF(error == WIFI_AWARE_ERROR_NONE, "No error"); + if (error == WIFI_AWARE_ERROR_NONE) { + VINE_LOGD("No error"); + return; + } - VINE_LOGE("Fails to subscribe. error: %s", __convert_nan_error_to_vine_disc_error(error)); + VINE_LOGE("Fails to subscribe. error: %d", __convert_nan_error_to_vine_disc_error(error)); __subscribe_failed((vine_nan_s *)user_data); } diff --git a/tests/vine-test/vine-test-glib.cpp b/tests/vine-test/vine-test-glib.cpp index b973466..163e204 100755 --- a/tests/vine-test/vine-test-glib.cpp +++ b/tests/vine-test/vine-test-glib.cpp @@ -106,6 +106,18 @@ static void __select_method() if (g_disc_method == 2) g_dp_method = 0; + + switch (g_disc_method) { + case 0: + printf("Default is selected\n"); + break; + case 1: + printf("BLE is selected\n"); + break; + case 2: + printf("NAN is selected\n"); + break; + } } static void __init() -- 2.7.4 From 9d7db32fc7465981d8dbfd814c46ec884472fb24 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Mon, 2 Aug 2021 18:31:46 +0900 Subject: [PATCH 05/16] Add vine_dp_set_service() Change-Id: I899bb36b330c10db9f0a40a174e1c14865cc7a86 --- include/vine.h | 16 ++++++++++++++++ src/include/vine-dp.h | 7 +++++++ src/vine-dp.cpp | 32 ++++++++++++++++++++++++++++++++ src/vine.cpp | 8 ++++++++ tests/unittest/vine-unittest-dp.cpp | 24 ++++++++++++++++++++++++ 5 files changed, 87 insertions(+) diff --git a/include/vine.h b/include/vine.h index fd77cbc..5a4cf69 100755 --- a/include/vine.h +++ b/include/vine.h @@ -1125,6 +1125,22 @@ int vine_dp_set_max_connections(vine_dp_h dp, int max_conn); int vine_dp_set_security(vine_dp_h dp, vine_security_h security); /** + * @brief Sets the service information. + * @remarks This API works only for @a VINE_DP_METHOD_BLE_GATT. + * @since_tizen 6.5 + * @param[in] dp The data path handle + * @param[in] service The service handle + * @return 0 on success, otherwise a negative error value + * @retval #VINE_ERROR_NONE Successful + * @retval #VINE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VINE_ERROR_INVALID_OPERATION Invalid operation + * @retval #VINE_ERROR_NOT_SUPPORTED Not supported + * @see vine_dp_create() + * @see vine_service_create() + */ +int vine_dp_set_service(vine_dp_h dp, vine_service_h service); + +/** * @brief Called whenever the peer is accepted. * @remarks @a dp must be released by vine_dp_destroy() if you don't use it anymore. * @since_tizen 6.5 diff --git a/src/include/vine-dp.h b/src/include/vine-dp.h index 06c2aa2..2e86615 100755 --- a/src/include/vine-dp.h +++ b/src/include/vine-dp.h @@ -62,6 +62,7 @@ public: virtual int update_local_address_info() = 0; virtual int set_topic(std::string topic) = 0; virtual int set_max_connections(int max_conn) = 0; + virtual int set_service(vine_service_h service) = 0; virtual int set_accepted_cb(vine_dp_accepted_cb callback, void *user_data) = 0; virtual int unset_accepted_cb() = 0; virtual int set_peer_joined_cb(vine_dp_peer_joined_cb callback, void *user_data) = 0; @@ -125,6 +126,7 @@ public: virtual int update_local_address_info(); virtual int set_topic(std::string topic); virtual int set_max_connections(int max_conn); + virtual int set_service(vine_service_h service); virtual int set_accepted_cb(vine_dp_accepted_cb callback, void *user_data); virtual int unset_accepted_cb(); virtual int set_peer_joined_cb(vine_dp_peer_joined_cb callback, void *user_data); @@ -141,6 +143,7 @@ private: int mListenPort; std::string mLocalIp; int mMaxConnNum; + vine_service_h mService; vine_dp_accepted_cb mAcceptedCb; void *mAcceptedCbData; }; @@ -172,6 +175,7 @@ public: virtual int update_local_address_info(); virtual int set_topic(std::string topic); virtual int set_max_connections(int max_conn){ return VINE_ERROR_NONE; }; + virtual int set_service(vine_service_h service); virtual int set_accepted_cb(vine_dp_accepted_cb callback, void *user_data); virtual int unset_accepted_cb(); virtual int set_peer_joined_cb(vine_dp_peer_joined_cb callback, void *user_data); @@ -187,6 +191,7 @@ private: int mPeerPort; std::string mLocalIp; int mPort; + vine_service_h mService; bool isCreatedByServerDp; }; @@ -231,6 +236,7 @@ public: virtual int set_topic(std::string topic); virtual std::string get_topic() { return mTopic; } virtual int set_max_connections(int max_conn); + virtual int set_service(vine_service_h service); virtual int set_accepted_cb(vine_dp_accepted_cb callback, void *user_data); virtual int unset_accepted_cb(); virtual int set_peer_joined_cb(vine_dp_peer_joined_cb callback, void *user_data); @@ -310,6 +316,7 @@ int _vine_dp_get_port(vine_dp_h dp, int *port); int _vine_dp_set_topic(vine_dp_h dp, const char *topic); int _vine_dp_set_max_connections(vine_dp_h dp, int max_conn); int _vine_dp_set_security(vine_dp_h dp, vine_security_h security); +int _vine_dp_set_service(vine_dp_h dp, vine_service_h service); int _vine_dp_set_accepted_cb(vine_dp_h dp, vine_dp_accepted_cb callback, void *user_data); int _vine_dp_unset_accepted_cb(vine_dp_h dp); int _vine_dp_open(vine_dp_h dp, vine_dp_opened_cb callback, void *user_data); diff --git a/src/vine-dp.cpp b/src/vine-dp.cpp index 94a94d0..2d83fcd 100755 --- a/src/vine-dp.cpp +++ b/src/vine-dp.cpp @@ -486,6 +486,7 @@ DPServer::DPServer(void *event_queue) mDataPath = NULL; mListenPort = 0; mMaxConnNum = VINE_DP_DEFAULT_CONNECTIONS_NUM; + mService = NULL; mAcceptedCb = NULL; mAcceptedCbData = NULL; mReceivedCb = NULL; @@ -500,6 +501,7 @@ DPServer::~DPServer() { VINE_LOGD("DPServer[%p] is deleted.", this); _vine_security_destroy(mSecurity); + vine_service_destroy(mService); vine_data_path_destroy(mDataPath); } @@ -606,6 +608,13 @@ int DPServer::set_max_connections(int max_conn) return VINE_ERROR_NONE; } +int DPServer::set_service(vine_service_h service) +{ + if (mMethod != VINE_DATA_PATH_METHOD_BLE_GATT) + return VINE_ERROR_INVALID_OPERATION; + return vine_service_clone(service, &mService); +} + int DPServer::set_accepted_cb(vine_dp_accepted_cb callback, void *user_data) { mAcceptedCb = callback; @@ -695,6 +704,7 @@ DPClient::DPClient(void *event_queue) mPeerIp = ""; mPeerPort = 0; mPort = 0; + mService = NULL; mReceivedCb = NULL; mReceivedCbData = NULL; mOpenedCb = NULL; @@ -730,6 +740,7 @@ DPClient::~DPClient() { VINE_LOGD("DPClient[%p] is deleted.", this); _vine_security_destroy(mSecurity); + vine_service_destroy(mService); vine_data_path_destroy(mDataPath); } @@ -841,6 +852,13 @@ int DPClient::set_topic(std::string topic) return VINE_ERROR_INVALID_OPERATION; } +int DPClient::set_service(vine_service_h service) +{ + if (mMethod != VINE_DATA_PATH_METHOD_BLE_GATT) + return VINE_ERROR_INVALID_OPERATION; + return vine_service_clone(service, &mService); +} + int DPClient::set_accepted_cb(vine_dp_accepted_cb callback, void *user_data) { return VINE_ERROR_INVALID_OPERATION; @@ -1056,6 +1074,11 @@ int DPPubSub::set_max_connections(int max_conn) return VINE_ERROR_NONE; } +int DPPubSub::set_service(vine_service_h service) +{ + return VINE_ERROR_INVALID_OPERATION; +} + int DPPubSub::set_accepted_cb(vine_dp_accepted_cb callback, void *user_data) { return VINE_ERROR_INVALID_OPERATION; @@ -1682,6 +1705,15 @@ int _vine_dp_set_security(vine_dp_h dp, vine_security_h security) return _dp->set_security(security); } +int _vine_dp_set_service(vine_dp_h dp, vine_service_h service) +{ + RET_VAL_IF(dp == NULL, VINE_ERROR_INVALID_PARAMETER, "dp is null."); + RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is null."); + + DataPath *_dp = static_cast(dp); + return _dp->set_service(service); +} + int _vine_dp_set_accepted_cb(vine_dp_h dp, vine_dp_accepted_cb callback, void *user_data) { RET_VAL_IF(dp == NULL, VINE_ERROR_INVALID_PARAMETER, "dp is null."); diff --git a/src/vine.cpp b/src/vine.cpp index 8290152..22057e8 100755 --- a/src/vine.cpp +++ b/src/vine.cpp @@ -478,6 +478,14 @@ API int vine_dp_set_security(vine_dp_h dp, vine_security_h security) return _vine_dp_set_security(dp, security); } +API int vine_dp_set_service(vine_dp_h dp, vine_service_h service) +{ + __VINE_FUNC_ENTER__; + CHECK_FEATURE_SUPPORTED; + + return _vine_dp_set_service(dp, service); +} + API int vine_dp_set_accepted_cb(vine_dp_h dp, vine_dp_accepted_cb callback, void *user_data) { __VINE_FUNC_ENTER__; diff --git a/tests/unittest/vine-unittest-dp.cpp b/tests/unittest/vine-unittest-dp.cpp index 8dd6838..718da0e 100755 --- a/tests/unittest/vine-unittest-dp.cpp +++ b/tests/unittest/vine-unittest-dp.cpp @@ -467,6 +467,30 @@ TEST_F(VineDpTest, SetSecurityP) vine_security_destroy(security); } +TEST_F(VineDpTest, SetServiceN) +{ + vine_service_h service; + + vine_service_create(&service); + EXPECT_EQ(VINE_ERROR_INVALID_PARAMETER, + vine_dp_set_service(NULL, service)); + EXPECT_EQ(VINE_ERROR_INVALID_PARAMETER, + vine_dp_set_service(client_dp, NULL)); + EXPECT_EQ(VINE_ERROR_INVALID_PARAMETER, + vine_dp_set_service(pubsub_dp, service)); + vine_service_destroy(service); +} + +TEST_F(VineDpTest, SetServiceP) +{ + vine_service_h service; + + vine_service_create(&service); + vine_dp_set_method(server_dp, VINE_DP_METHOD_BLE_GATT); + EXPECT_EQ(VINE_ERROR_NONE, vine_dp_set_service(server_dp, service)); + vine_service_destroy(service); +} + TEST_F(VineDpTest, SetIfaceNameN) { EXPECT_EQ(VINE_ERROR_INVALID_PARAMETER, -- 2.7.4 From aa0da66162336013b072a02850ba7e34d7c5437c Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Tue, 3 Aug 2021 18:24:01 +0900 Subject: [PATCH 06/16] ble-gatt: Use different UUID for each DP connection Change-Id: I1191781f0809cf7f1a08ec65f611d48e708d3003 --- plugins/ble-gatt/CMakeLists.txt | 15 ++++ plugins/ble-gatt/ble-gatt-plugin-utils.cpp | 134 +++++++++++++++++++++++++++++ plugins/ble-gatt/ble-gatt-plugin-utils.h | 21 +++++ plugins/ble-gatt/ble-gatt-plugin.cpp | 89 +++++++++++++++---- src/include/vine-data-path.h | 2 +- src/vine-data-path.cpp | 11 ++- src/vine-dp.cpp | 28 ++++-- tool/tool_run.cpp | 7 +- 8 files changed, 284 insertions(+), 23 deletions(-) create mode 100755 plugins/ble-gatt/ble-gatt-plugin-utils.cpp create mode 100755 plugins/ble-gatt/ble-gatt-plugin-utils.h diff --git a/plugins/ble-gatt/CMakeLists.txt b/plugins/ble-gatt/CMakeLists.txt index 977029e..f0af661 100755 --- a/plugins/ble-gatt/CMakeLists.txt +++ b/plugins/ble-gatt/CMakeLists.txt @@ -40,10 +40,25 @@ SET_TARGET_PROPERTIES( PROPERTIES SOVERSION ${BLE_GATT_PLUGIN_VERSION_MAJOR} ) +find_library( + LIBCRYPTO + NAMES libcrypto.so + HINTS /usr/local/lib /usr/lib /usr/lib64 /usr/lib/x86_64-linux-gnu + REQUIRED +) + +find_library( + LIBSSL + NAMES libssl.so + HINTS /usr/local/lib /usr/lib /usr/lib64 /usr/lib/x86_64-linux-gnu + REQUIRED +) TARGET_LINK_LIBRARIES(${BLE_GATT_PLUGIN} ${VINE_LOGGER} ${BLE_DEPS_LIBRARIES} + ${LIBCRYPTO} + ${LIBSSL} ${fw_name_deps_LIBRARIES} dl ) diff --git a/plugins/ble-gatt/ble-gatt-plugin-utils.cpp b/plugins/ble-gatt/ble-gatt-plugin-utils.cpp new file mode 100755 index 0000000..5a30831 --- /dev/null +++ b/plugins/ble-gatt/ble-gatt-plugin-utils.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + * + * + * RFC 4122 - A Universally Unique IDentifier (UUID) URN Namespace + * uuid_create_sha1_from_name and format_uuid_v3or5 are adapted to get UUID. + * These are copyrighted by following licenses. + * + * Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. + * Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & + * Digital Equipment Corporation, Maynard, Mass. + * Copyright (c) 1998 Microsoft. + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: permission to use, copy, + * modify, and distribute this file for any purpose is hereby + * granted without fee, provided that the above copyright notices and + * this notice appears in all source code copies, and that none of + * the names of Open Software Foundation, Inc., Hewlett-Packard + * Company, Microsoft, or Digital Equipment Corporation be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Neither Open Software + * Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital + * Equipment Corporation makes any representations about the + * suitability of this software for any purpose. + * +*/ + +#include +#include +#include + +#include "ble-gatt-plugin-utils.h" +#include "vine-data-path-plugin.h" +#include "vine-utils.h" + +using namespace std; + +// Hexadecimal representation +// [time_low]-[time_mid]-[time_hi_and_version]-[clock_seq_hi_and_reserved clock_seq_low]-[node] +// 8-4-4-4-12 +typedef struct { + unsigned int time_low; // 32bits + unsigned short time_mid; // 16 bits + unsigned short time_hi_and_version; // 16bits + unsigned char clock_seq_hi_and_reserved; // 8bits + unsigned char clock_seq_low; // 8bits + unsigned char node[6]; // 48bits +} uuid_t; + +// Name space for Vine +// 931da289-042b-4372-9fb9-299640817a15 +uuid_t NameSpace_Vine = { + 0x931da289, + 0x042b, + 0x4372, + 0x9f, 0xb9, + 0x29, 0x96, 0x40, 0x81, 0x7a, 0x15 +}; + +static void format_uuid_v5(uuid_t *uuid, unsigned char hash[16]) +{ + int version = 5; + /* convert UUID to local byte order */ + memcpy(uuid, hash, sizeof *uuid); + uuid->time_low = ntohl(uuid->time_low); + uuid->time_mid = ntohs(uuid->time_mid); + uuid->time_hi_and_version = ntohs(uuid->time_hi_and_version); + + /* put in the variant and version bits */ + uuid->time_hi_and_version &= 0x0FFF; + uuid->time_hi_and_version |= (version << 12); + uuid->clock_seq_hi_and_reserved &= 0x3F; + uuid->clock_seq_hi_and_reserved |= 0x80; +} + +static void uuid_create_sha1_from_name(uuid_t *uuid, uuid_t nsid, const void *name, int name_len) +{ + SHA_CTX c; + unsigned char hash[20]; + uuid_t net_nsid; + + /* put name space ID in network byte order so it hashes the same + no matter what endian machine we're on */ + net_nsid = nsid; + net_nsid.time_low = htonl(net_nsid.time_low); + net_nsid.time_mid = htons(net_nsid.time_mid); + net_nsid.time_hi_and_version = htons(net_nsid.time_hi_and_version); + + SHA1_Init(&c); + SHA1_Update(&c, &net_nsid, sizeof net_nsid); + SHA1_Update(&c, name, name_len); + SHA1_Final(hash, &c); + + /* the hash is in network byte order at this point */ + format_uuid_v5(uuid, hash); +} + +int gatt_utils_get_uuid(const char *token, const char *extra, char uuid_str[]) +{ + RET_VAL_IF(token == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "token is NULL"); + RET_VAL_IF(uuid_str == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "uuid_str is NULL"); + + VINE_LOGD("token: %s, extra: %s", token, extra); + + uuid_t uuid; + string name = token; + + if (extra) + name += extra; + uuid_create_sha1_from_name(&uuid, NameSpace_Vine, name.c_str(), name.size()); + + snprintf(uuid_str, GATT_UUID_STR_LEN + 1, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, + uuid.clock_seq_hi_and_reserved, + uuid.clock_seq_low, + uuid.node[0], uuid.node[1], uuid.node[2], + uuid.node[3], uuid.node[4], uuid.node[5]); + + VINE_LOGI("UUID: %s", uuid_str); + + return VINE_DATA_PATH_ERROR_NONE; +} diff --git a/plugins/ble-gatt/ble-gatt-plugin-utils.h b/plugins/ble-gatt/ble-gatt-plugin-utils.h new file mode 100755 index 0000000..6ca422b --- /dev/null +++ b/plugins/ble-gatt/ble-gatt-plugin-utils.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + * +*/ + +#pragma once + +#define GATT_UUID_STR_LEN 36 +int gatt_utils_get_uuid(const char *token, const char *extra, char uuid_str[]); diff --git a/plugins/ble-gatt/ble-gatt-plugin.cpp b/plugins/ble-gatt/ble-gatt-plugin.cpp index b3a0d5b..b8c8a04 100755 --- a/plugins/ble-gatt/ble-gatt-plugin.cpp +++ b/plugins/ble-gatt/ble-gatt-plugin.cpp @@ -21,17 +21,16 @@ #include #include "vine-data-path-plugin.h" +#include "vine-constants.h" #include "vine-log.h" #include "vine-utils.h" #include "vine-queue.h" +#include "ble-gatt-plugin-utils.h" using namespace std; -// TODO: change UUIDs -#define VINE_GATT_SERVICE_UUID "000018f2-0000-1000-8000-00805f9b34fb" -#define VINE_GATT_CONNECTION_CHAR_UUID "5fbfd598-ab0f-4c20-9966-60a11a41e974" -#define VINE_GATT_READ_WRITE_CHAR_UUID "00002af6-0000-1000-8000-00805f9b34fb" -#define VINE_GATT_DESC_UUID "fa87c0d0-afac-11de-8a39-0800200c9a66" +#define VINE_GATT_UUID_NAME_CONNECTION "Connection" +#define VINE_GATT_UUID_NAME_READ_WRITE "ReadWrite" // 2-way handshake for VINE GATT connection #define VINE_GATT_CONNECTION_SYN "VINE_GATT_CONNECTION_SYN" @@ -86,6 +85,7 @@ struct vine_gatt_s { VineQueue *write_buffer; bool ready_to_write; char *remote_address; + char *token; void *user; // vine_data_path_h }; @@ -483,7 +483,7 @@ static void __send_conn_fin(vine_gatt_s *gatt, const char *remote_address) if (gatt->type == VINE_GATT_ROLE_SERVER) { bt_gatt_server_notify_characteristic_changed_value(gatt->connection_char, __send_conn_fin_to_client_completed_cb, gatt->remote_address, (void *)gatt); - } else if (gatt->type = VINE_GATT_ROLE_CLIENT) { + } else if (gatt->type == VINE_GATT_ROLE_CLIENT) { bt_gatt_client_write_value(gatt->connection_char, __send_conn_fin_to_server_completed_cb, (void *)gatt); } @@ -573,6 +573,7 @@ static int __update_gatt_service_info(const char *remote_address, vine_gatt_s *g bt_gatt_h service = NULL; bt_gatt_h connection_char = NULL; bt_gatt_h characteristic = NULL; + char uuid[GATT_UUID_STR_LEN + 1] = {0, }; int ret = BT_ERROR_OPERATION_FAILED; ret = bt_gatt_client_create(remote_address, &client); @@ -591,12 +592,23 @@ static int __update_gatt_service_info(const char *remote_address, vine_gatt_s *g if (ret != BT_ERROR_NONE) goto ERR; - ret = bt_gatt_client_get_service(client, VINE_GATT_SERVICE_UUID, &service); + ret = gatt_utils_get_uuid(gatt->token, NULL, uuid); + if (ret != VINE_DATA_PATH_ERROR_NONE) { + VINE_LOGE("Failed to get servce uuid."); + goto ERR; + } + + ret = bt_gatt_client_get_service(client, uuid, &service); if (ret != BT_ERROR_NONE) goto ERR; - ret = bt_gatt_service_get_characteristic(service, - VINE_GATT_CONNECTION_CHAR_UUID, &connection_char); + ret = gatt_utils_get_uuid(gatt->token, VINE_GATT_UUID_NAME_CONNECTION, uuid); + if (ret != VINE_DATA_PATH_ERROR_NONE) { + VINE_LOGE("Failed to get connection char uuid."); + goto ERR; + } + + ret = bt_gatt_service_get_characteristic(service, uuid, &connection_char); if (ret != BT_ERROR_NONE) goto ERR; @@ -607,8 +619,13 @@ static int __update_gatt_service_info(const char *remote_address, vine_gatt_s *g goto ERR; } - ret = bt_gatt_service_get_characteristic(service, - VINE_GATT_READ_WRITE_CHAR_UUID, &characteristic); + ret = gatt_utils_get_uuid(gatt->token, VINE_GATT_UUID_NAME_READ_WRITE, uuid); + if (ret != VINE_DATA_PATH_ERROR_NONE) { + VINE_LOGE("Failed to get read write char uuid."); + goto ERR; + } + + ret = bt_gatt_service_get_characteristic(service, uuid, &characteristic); if (ret != BT_ERROR_NONE) goto ERR; @@ -656,7 +673,7 @@ static vine_gatt_s *__create_accepted_gatt(const char *remote_address, vine_gatt } static void __gatt_connection_state_changed_cb(int result, bool connected, - const char *remote_address, void *user_data) + const char *remote_address, void *user_data) { VINE_LOGI("result[%d] connected[%d] remote address[%s]", result, connected, remote_address); @@ -1003,6 +1020,8 @@ int gatt_destroy(vine_dp_plugin_h handle) gatt->read_write_desc = NULL; free(gatt->remote_address); gatt->remote_address = NULL; + free(gatt->token); + gatt->token = NULL; free(gatt); return VINE_DATA_PATH_ERROR_NONE; @@ -1021,6 +1040,7 @@ int gatt_open(vine_dp_plugin_h handle, int addr_family, bt_gatt_h connection_desc = NULL; bt_gatt_h read_write_char = NULL; bt_gatt_h read_write_desc = NULL; + char uuid[GATT_UUID_STR_LEN + 1] = {0, }; int ret = BT_ERROR_OPERATION_FAILED; // This returns OPERATION_FAILED when already initialized. ignore it. @@ -1032,13 +1052,25 @@ int gatt_open(vine_dp_plugin_h handle, int addr_family, goto ERR; } - ret = bt_gatt_service_create(VINE_GATT_SERVICE_UUID, BT_GATT_SERVICE_TYPE_PRIMARY, &service); + ret = gatt_utils_get_uuid(gatt->token, NULL, uuid); + if (ret != VINE_DATA_PATH_ERROR_NONE) { + VINE_LOGE("Failed to get servce uuid."); + goto ERR; + } + + ret = bt_gatt_service_create(uuid, BT_GATT_SERVICE_TYPE_PRIMARY, &service); if (ret != BT_ERROR_NONE) { VINE_LOGE("Failed to create service."); goto ERR; } - connection_char = _add_gatt_characteristic(service, VINE_GATT_CONNECTION_CHAR_UUID, + ret = gatt_utils_get_uuid(gatt->token, VINE_GATT_UUID_NAME_CONNECTION, uuid); + if (ret != VINE_DATA_PATH_ERROR_NONE) { + VINE_LOGE("Failed to get connection char uuid."); + goto ERR; + } + + connection_char = _add_gatt_characteristic(service, uuid, __gatt_server_read_connection_value_requested_cb, __gatt_server_write_connection_value_requested_cb, __gatt_server_noti_connection_state_changed_cb, handle); @@ -1049,7 +1081,13 @@ int gatt_open(vine_dp_plugin_h handle, int addr_family, goto ERR; } - read_write_char = _add_gatt_characteristic(service, VINE_GATT_READ_WRITE_CHAR_UUID, + ret = gatt_utils_get_uuid(gatt->token, VINE_GATT_UUID_NAME_READ_WRITE, uuid); + if (ret != VINE_DATA_PATH_ERROR_NONE) { + VINE_LOGE("Failed to get read write char uuid."); + goto ERR; + } + + read_write_char = _add_gatt_characteristic(service, uuid, __gatt_server_read_value_requested_cb, __gatt_server_write_value_requested_cb, __gatt_server_noti_state_changed_cb, handle); @@ -1247,11 +1285,32 @@ int gatt_get_local_address_info(vine_dp_plugin_h handle, int gatt_set_token(vine_dp_plugin_h handle, const char *token) { + RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL"); + RET_VAL_IF(token == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "token is NULL"); + + vine_gatt_s *gatt = (vine_gatt_s *)handle; + int len = strlen(token); + if (len < 0 || len > VINE_MAX_SERVICE_TYPE_LEN) + return -1; + + if (gatt->token) + free(gatt->token); + gatt->token = strdup(token); return VINE_DATA_PATH_ERROR_NONE; } int gatt_get_token(vine_dp_plugin_h handle, char **token) { + RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL"); + RET_VAL_IF(token == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "token is NULL"); + + vine_gatt_s *gatt = (vine_gatt_s *)handle; + if (strlen(gatt->token) == 0) { + *token = NULL; + return VINE_DATA_PATH_ERROR_INVALID_OPERATION; + } + + *token = strdup(gatt->token); return VINE_DATA_PATH_ERROR_NONE; } diff --git a/src/include/vine-data-path.h b/src/include/vine-data-path.h index 775cb21..34846f7 100755 --- a/src/include/vine-data-path.h +++ b/src/include/vine-data-path.h @@ -44,7 +44,7 @@ int vine_data_path_deinit(void); int vine_data_path_open(vine_data_path_method_e method, vine_address_family_e addr_family, int port, const char *iface_name, int max_conn, - vine_security_h security, const char *host_name, + vine_security_h security, const char *host_name, const char *token, vine_data_path_opened_cb opened_cb, void *opened_cb_data, vine_data_path_accepted_cb accepted_cb, void *accepted_cb_data, vine_data_path_h *opened_datapath, diff --git a/src/vine-data-path.cpp b/src/vine-data-path.cpp index a723849..89fd74f 100755 --- a/src/vine-data-path.cpp +++ b/src/vine-data-path.cpp @@ -728,7 +728,7 @@ static void _destroy_security_info(vine_dp_ssl *dest) int vine_data_path_open(vine_data_path_method_e method, vine_address_family_e addr_family, int port, const char *iface_name, - int max_conn, vine_security_h security, const char *host_name, + int max_conn, vine_security_h security, const char *host_name, const char *token, vine_data_path_opened_cb opened_cb, void *opened_cb_data, vine_data_path_accepted_cb accepted_cb, void *accepted_cb_data, vine_data_path_h *opened_datapath, @@ -764,6 +764,15 @@ int vine_data_path_open(vine_data_path_method_e method, } } + if (token && dp->plugin_fn->set_token) { + ret = dp->plugin_fn->set_token(dp->plugin_handle, token); + if (ret != VINE_DATA_PATH_ERROR_NONE) { + vine_data_path_destroy(dp); + _destroy_security_info(&ssl); + return __convert_data_path_error_to_vine_error((vine_data_path_error)ret); + } + } + ret = dp->plugin_fn->open(dp->plugin_handle, dp_addr_family, port, iface_name, max_conn, ssl); _destroy_security_info(&ssl); diff --git a/src/vine-dp.cpp b/src/vine-dp.cpp index 2d83fcd..99bdba4 100755 --- a/src/vine-dp.cpp +++ b/src/vine-dp.cpp @@ -659,14 +659,23 @@ int DPServer::open(vine_dp_opened_cb callback, void *user_data) { RET_ERR_IF_DP_OPEN_STATE_ISNT_IDLE(mOpenState); + int ret; + char *service_type = NULL; + + if (mService && mMethod == VINE_DATA_PATH_METHOD_BLE_GATT) { + ret = vine_service_get_type(mService, &service_type); + if (ret != VINE_ERROR_NONE) + return ret; + } + mOpenedCb = callback; mOpenedCbData = user_data; mOpenState = VINE_DP_OPEN_STATE_WAIT; - int ret = vine_data_path_open(mMethod, + ret = vine_data_path_open(mMethod, mAddrFamily, mListenPort, mIfaceName.size() > 0 ? mIfaceName.c_str() : NULL, - mMaxConnNum, mSecurity, NULL, + mMaxConnNum, mSecurity, NULL, service_type, _opened_cb, static_cast(this), _accepted_cb, static_cast(this), &mDataPath, mEventQueue); @@ -894,16 +903,25 @@ int DPClient::open(vine_dp_opened_cb callback, void *user_data) RET_VAL_IF(isCreatedByServerDp, VINE_ERROR_INVALID_OPERATION, "cannot open"); RET_ERR_IF_DP_OPEN_STATE_ISNT_IDLE(mOpenState); + int ret; + char *service_type = NULL; + + if (mService && mMethod == VINE_DATA_PATH_METHOD_BLE_GATT) { + ret = vine_service_get_type(mService, &service_type); + if (ret != VINE_ERROR_NONE) + return ret; + } + mOpenedCb = callback; mOpenedCbData = user_data; mOpenState = VINE_DP_OPEN_STATE_WAIT; - int ret = vine_data_path_connect(mMethod, + ret = vine_data_path_connect(mMethod, mAddrFamily, mMethod == VINE_DATA_PATH_METHOD_BLE_GATT ? mPeerAddr.c_str() : mPeerIp.c_str(), mPeerPort, mIfaceName.size() > 0 ? mIfaceName.c_str() : NULL, - mSecurity, NULL, NULL, + mSecurity, NULL, service_type, _connected_cb, static_cast(this), &mDataPath, mEventQueue); if (ret != VINE_ERROR_NONE) mOpenState = VINE_DP_OPEN_STATE_NONE; @@ -1283,7 +1301,7 @@ int DPPubSub::open(vine_dp_opened_cb callback, void *user_data) int ret = vine_data_path_open(mMethod, mAddrFamily, mListenPort, mIfaceName.size() > 0 ? mIfaceName.c_str() : NULL, - mMaxConnNum, mSecurity, mId.c_str(), + mMaxConnNum, mSecurity, mId.c_str(), NULL, _pubsub_opened_cb, static_cast(this), _pubsub_accepted_cb, static_cast(this), &mServerDataPath, mEventQueue); diff --git a/tool/tool_run.cpp b/tool/tool_run.cpp index e8d800f..f003adf 100755 --- a/tool/tool_run.cpp +++ b/tool/tool_run.cpp @@ -561,7 +561,12 @@ static void _set_dp_info(vine_dp_type_e type) if (vine_configs.with_ble) { vine_dp_set_method(vine_configs.dp, VINE_DP_METHOD_BLE_GATT); - vine_dp_set_remote_address(vine_configs.dp, tool_config_get_remote_address()); + if (type == VINE_DP_TYPE_CLIENT) { + vine_service_create(&vine_configs.service); + vine_service_set_type(vine_configs.service, tool_config_get_service_type()); + } + vine_dp_set_remote_address(vine_configs.dp, tool_config_get_remote_address()); + vine_dp_set_service(vine_configs.dp, vine_configs.service); } if (type == VINE_DP_TYPE_CLIENT) { -- 2.7.4 From efb3b2dbdb5007bedb191a049603dec72d7a92f4 Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Mon, 30 Aug 2021 21:16:38 +0900 Subject: [PATCH 07/16] Fix svace issues Change-Id: Ib296f3b17f92925e25da51acd605bbc225cd7a7c Signed-off-by: Cheoleun Moon --- plugins/nan/nan-plugin.cpp | 2 +- src/vine-dp.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/nan/nan-plugin.cpp b/plugins/nan/nan-plugin.cpp index 8393d61..8438d4e 100755 --- a/plugins/nan/nan-plugin.cpp +++ b/plugins/nan/nan-plugin.cpp @@ -366,12 +366,12 @@ static void __discovered_cb(wifi_aware_session_h session, vine_nan_s *nan_handle = (vine_nan_s *)user_data; __add_peer(nan_handle, peer, mac); - g_free(mac); event_callbacks.discovered_cb(nan_handle, true, nan_handle->service_type, service_name, nullptr, mac, -1, attributes, nullptr, 0, nan_handle->disc_handle); + g_free(mac); } /** diff --git a/src/vine-dp.cpp b/src/vine-dp.cpp index 99bdba4..d1b883b 100755 --- a/src/vine-dp.cpp +++ b/src/vine-dp.cpp @@ -735,6 +735,7 @@ DPClient::DPClient(void *event_queue, void *datapath) mPeerIp = vine_data_path_get_ip(mDataPath); mPeerPort = vine_data_path_get_port(mDataPath); mPort = 0; + mService = NULL; mReceivedCb = NULL; mReceivedCbData = NULL; mOpenedCb = NULL; -- 2.7.4 From a8a75aa7f23735ecb075c5bf5a60677e47fe6251 Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Tue, 7 Sep 2021 13:46:01 +0900 Subject: [PATCH 08/16] Ensure null-terminated string Change-Id: I9dc10563bf3b321bfdca92d581fe491ca15a84e6 Signed-off-by: Cheoleun Moon --- src/vine-disc.cpp | 17 +++++++++++++---- src/vine-dp.cpp | 4 ++-- src/vine-service.cpp | 3 ++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/vine-disc.cpp b/src/vine-disc.cpp index 084172d..cc994ff 100755 --- a/src/vine-disc.cpp +++ b/src/vine-disc.cpp @@ -231,16 +231,25 @@ static void __discovered_cb(void *plugin_handle, bool available, discovered_event->available = available; strncpy(discovered_event->service_type, service_type, VINE_MAX_SERVICE_TYPE_LEN); + discovered_event->service_type[VINE_MAX_SERVICE_TYPE_LEN] = 0; strncpy(discovered_event->service_name, service_name, VINE_MAX_SERVICE_NAME_LEN); + discovered_event->service_type[VINE_MAX_SERVICE_NAME_LEN] = 0; strncpy(discovered_event->iface_name, iface_name, IF_NAMESIZE); - if (host_name != NULL) + discovered_event->iface_name[IF_NAMESIZE] = 0; + if (host_name != NULL) { strncpy(discovered_event->host_name, host_name, VINE_MAX_HOST_NAME_LEN); - else + discovered_event->host_name[VINE_MAX_HOST_NAME_LEN] = 0; + } + else { memset(discovered_event->host_name, 0, VINE_MAX_HOST_NAME_LEN + 1); - if (mac != NULL) + } + if (mac != NULL) { strncpy(discovered_event->mac, mac, VINE_MAC_LEN); - else + discovered_event->mac[VINE_MAC_LEN] = 0; + } + else { memset(discovered_event->mac, 0, VINE_MAC_LEN + 1); + } discovered_event->port = port; discovered_event->attributes = attr; diff --git a/src/vine-dp.cpp b/src/vine-dp.cpp index d1b883b..c9475ee 100755 --- a/src/vine-dp.cpp +++ b/src/vine-dp.cpp @@ -330,8 +330,8 @@ static void _service_discovered_cb(vine_disc_h disc, bool available, const char *host_name, const char *mac, int port, const map &attr, const char *iface_name, int more_coming, void *user_data) { - VINE_LOGD("%s is discovered. %s", - service_name, available ? "available" : "not available"); + VINE_LOGD("service_type[%s] service_name[%s] is discovered. %s", + service_type, service_name, available ? "available" : "not available"); if (!user_data || !available) return; diff --git a/src/vine-service.cpp b/src/vine-service.cpp index 9d3a5e5..a86e371 100755 --- a/src/vine-service.cpp +++ b/src/vine-service.cpp @@ -141,8 +141,9 @@ int _vine_service_set_type( vine_service_h service, const char *service_type) { RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL"); + RET_VAL_IF(service_type == NULL, VINE_ERROR_INVALID_PARAMETER, "service_type is NULL"); RET_VAL_IF(_vine_service_check_service_type(service_type) == false, - VINE_ERROR_INVALID_PARAMETER, "invalid length of service_type"); + VINE_ERROR_INVALID_PARAMETER, "invalid length of service_type[%s]", service_type); vine_service_s *s = (vine_service_s *)service; strncpy(s->service_type, service_type, VINE_MAX_SERVICE_TYPE_LEN); -- 2.7.4 From ca14d0cf3bd7fd678ea84f98d24c14a3f3a10abe Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Wed, 15 Sep 2021 12:30:49 +0900 Subject: [PATCH 09/16] Disable NAN feature on emulator Change-Id: I607b9454f99bb1e84e936ccd152d31374a91dfc1 --- packaging/capi-network-vine.spec | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packaging/capi-network-vine.spec b/packaging/capi-network-vine.spec index 1b5adbb..9bfc807 100755 --- a/packaging/capi-network-vine.spec +++ b/packaging/capi-network-vine.spec @@ -24,7 +24,9 @@ BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(dlog) +%ifnarch %i586 i686 x86_64 BuildRequires: pkgconfig(capi-network-wifi-aware) +%endif BuildRequires: pkgconfig(capi-network-bluetooth) %endif @@ -104,7 +106,9 @@ export LDFLAGS+=" -lgcov" %else -DUSE_LIBWEBSOCKETS_STATIC=OFF \ %endif +%ifnarch %i586 i686 x86_64 -DNAN_SUPPORT=ON \ +%endif %if %{with lws_static_prebuilt} -DUSE_LIBWEBSOCKETS_STATIC_PREBUILT=ON \ %else -- 2.7.4 From 5f266f62ff63afcf0aaf169b65308a1a3d18d4e7 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Fri, 24 Sep 2021 18:04:56 +0900 Subject: [PATCH 10/16] Fix timing issue Following scenario can occur. (Th: thread) 1. Th1: Call vine_dp_open() 2. Th2: opened_cb isn't invoked yet. 3. Th1: Call vine_dp_close() or vine_dp_destroy() 4. Th2: Access to freed memory LWS with external poll doesn't provide API for cancel websocket creation. So, This patch handles close() and destroy() request in internal thread(Th2). Change-Id: I394786fdfb5b7cf161ef4d2a904b9ba5d9960b2d --- packaging/capi-network-vine.spec | 2 +- plugins/libwebsockets/libwebsockets-plugin.cpp | 129 ++++++++++++++++--------- src/vine-data-path.cpp | 10 ++ tests/vine-test/vine-test.cpp | 12 +++ 4 files changed, 106 insertions(+), 47 deletions(-) diff --git a/packaging/capi-network-vine.spec b/packaging/capi-network-vine.spec index 9bfc807..5a17528 100755 --- a/packaging/capi-network-vine.spec +++ b/packaging/capi-network-vine.spec @@ -3,7 +3,7 @@ %bcond_without use_glib_event_loop Name: capi-network-vine Summary: An service discovery framework -Version: 1.1.8 +Version: 1.1.9 Release: 0 Group: Network & Connectivity/API License: Apache-2.0 diff --git a/plugins/libwebsockets/libwebsockets-plugin.cpp b/plugins/libwebsockets/libwebsockets-plugin.cpp index f9a5112..096fcf3 100755 --- a/plugins/libwebsockets/libwebsockets-plugin.cpp +++ b/plugins/libwebsockets/libwebsockets-plugin.cpp @@ -54,6 +54,7 @@ typedef struct { struct lws_vhost *vh; bool is_server; bool close_requested; + bool destroy_requested; int curr_conn; int max_conn; @@ -71,11 +72,13 @@ typedef enum { WEBSOCKET_OP_CONNECT, WEBSOCKET_OP_WRITE, WEBSOCKET_OP_TERMINATE, + WEBSOCKET_OP_DESTROY, } websocket_op_code_e; typedef struct { websocket_op_code_e code; websocket_s *ws; + struct lws_vhost *vh; int addr_family; char *ip; // connect only int port; // open, connect only @@ -227,10 +230,9 @@ static void _notify_websocket_op_request() } static int _add_websocket_op_request(websocket_op_code_e code, - websocket_s *ws, int addr_family, + websocket_s *ws, struct lws_vhost *vh, int addr_family, const char *ip, int port, const char *iface_name, - int max_conn, - vine_dp_ssl *ssl) + int max_conn, vine_dp_ssl *ssl) { websocket_op_s *op = (websocket_op_s *)calloc(1, sizeof(websocket_op_s)); if (!op) @@ -238,6 +240,7 @@ static int _add_websocket_op_request(websocket_op_code_e code, op->code = code; op->ws = ws; + op->vh = vh; op->addr_family = addr_family; op->ip = STRDUP(ip); op->port = port; @@ -268,13 +271,53 @@ static void _del_websocket_op_request(websocket_op_s *op) free(op); } -static void _process_pending_destroy(void) +static void _process_pending_destroy(struct lws_vhost *vh) { VINE_LOGD("Process pending destroy"); + if (!vh) + return; + + const struct lws_protocols *protocol = lws_vhost_name_to_protocol(vh, + VINE_PROTOCOL_NAME); + if (!protocol) + return; + + lws_callback_all_protocol_vhost_args(vh, protocol, LWS_CALLBACK_USER, NULL, 0); + listen_vh_list.erase(vh); + lws_vhost_destroy(vh); + VINE_LOGI("vh[%p] is destroyed", vh); + while (!lws_service_adjust_timeout(g_context, 1, 0)) lws_service_tsi(g_context, -1, 0); } + +static void _destroy_websocket(websocket_s *ws) +{ + if (!ws) + return; + + VINE_LOGD("ws[%s] is destroyed.", ws); + + ws->wsi = NULL; + ws->vh = NULL; + ws->user = NULL; + + free(ws->host_name); + ws->host_name = NULL; + free(ws->token); + ws->token = NULL; + ws->token_len = 0; + + delete ws->recv_buffer; + delete ws->write_buffer; + + ws->recv_buffer = NULL; + ws->write_buffer = NULL; + + free(ws); +} + static void _process_websocket_op_request(void) { RET_IF(op_queue.empty(), "operation queue is NULL"); @@ -299,7 +342,10 @@ static void _process_websocket_op_request(void) _request_write(op->ws); break; case WEBSOCKET_OP_TERMINATE: - _process_pending_destroy(); + _process_pending_destroy(op->vh); + break; + case WEBSOCKET_OP_DESTROY: + _destroy_websocket(op->ws); break; default: break; @@ -570,7 +616,7 @@ static int _websocket_protocol_cb(struct lws *wsi, /* --- client callbacks --- */ case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: VINE_LOGI("Failed connection request to server."); - if (ws && g_callbacks.connected_cb) + if (ws && !ws->destroy_requested && g_callbacks.connected_cb) _invoke_connected_cb(wsi, false, ws->user); break; @@ -591,7 +637,7 @@ static int _websocket_protocol_cb(struct lws *wsi, case LWS_CALLBACK_CLIENT_ESTABLISHED: VINE_LOGI("Connected with server."); - if (ws && g_callbacks.connected_cb) + if (ws && !ws->destroy_requested && g_callbacks.connected_cb) _invoke_connected_cb(wsi, true, ws->user); break; @@ -604,7 +650,8 @@ static int _websocket_protocol_cb(struct lws *wsi, size_t total_len = _save_data(ws, in, len, lws_is_first_fragment(wsi), lws_is_final_fragment(wsi)); - if (lws_is_final_fragment(wsi) && g_callbacks.received_cb) + if (lws_is_final_fragment(wsi) + && !ws->destroy_requested && g_callbacks.received_cb) g_callbacks.received_cb(total_len, ws->user); break; } @@ -620,6 +667,11 @@ static int _websocket_protocol_cb(struct lws *wsi, return -1; } + if (ws->destroy_requested) { + VINE_LOGI("ws[%p] will be destroyed.", ws); + return -1; + } + VINE_LOGI("Writeable to server."); n = _write_data(ws); if (g_callbacks.written_cb) @@ -629,7 +681,8 @@ static int _websocket_protocol_cb(struct lws *wsi, case LWS_CALLBACK_CLIENT_CLOSED: VINE_LOGI("Connected server is closed."); // call terminated_cb() when close isn't requested only. - if (ws && !ws->close_requested && g_callbacks.terminated_cb) + if (ws && !ws->close_requested + && !ws->destroy_requested && g_callbacks.terminated_cb) g_callbacks.terminated_cb(ws->user); break; @@ -759,7 +812,6 @@ static void _open_server(websocket_s *ws, int addr_family, return; } - //listen_vh_list.insert((void *)ws->vh); listen_vh_list.insert(ws->vh); void *user_data = lws_protocol_vh_priv_zalloc(ws->vh, protocols, sizeof(websocket_s)); @@ -781,7 +833,8 @@ static int websocket_open(vine_dp_plugin_h handle, ws->is_server = true; VINE_LOGD("ws[%p]", ws); if (_add_websocket_op_request(WEBSOCKET_OP_OPEN, - (websocket_s *)handle, addr_family, NULL, port, iface_name, max_conn, &ssl) < 0) + (websocket_s *)handle, NULL, + addr_family, NULL, port, iface_name, max_conn, &ssl) < 0) return VINE_DATA_PATH_ERROR_OPERATION_FAILED; _notify_websocket_op_request(); @@ -826,7 +879,8 @@ static int websocket_connect(vine_dp_plugin_h handle, RET_VAL_IF(!g_context, VINE_DATA_PATH_ERROR_INVALID_OPERATION, "g_context is NULL"); if (_add_websocket_op_request(WEBSOCKET_OP_CONNECT, - (websocket_s *)handle, addr_family, ip, port, iface_name, 0, &ssl) < 0) + (websocket_s *)handle, NULL, + addr_family, ip, port, iface_name, 0, &ssl) < 0) return VINE_DATA_PATH_ERROR_OPERATION_FAILED; _notify_websocket_op_request(); @@ -983,7 +1037,8 @@ static int websocket_write(vine_dp_plugin_h handle, unsigned char *buf, size_t l ws->write_buffer->push(wd); VINE_LOGD("websocket_data[%p] is pushed to write_buffer. len[%d]", wd, len); - if (_add_websocket_op_request(WEBSOCKET_OP_WRITE, ws, 0, NULL, -1, NULL, 0, NULL) < 0) + if (_add_websocket_op_request(WEBSOCKET_OP_WRITE, ws, NULL, + 0, NULL, -1, NULL, 0, NULL) < 0) return VINE_DATA_PATH_ERROR_OPERATION_FAILED; _notify_websocket_op_request(); @@ -996,22 +1051,17 @@ static int websocket_close(vine_dp_plugin_h handle) RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "plugin handle is NULL"); websocket_s *ws = (websocket_s *)handle; + if (ws->close_requested) { + VINE_LOGI("Already requested."); + return VINE_DATA_PATH_ERROR_NONE; + } + + VINE_LOGD("ws[%p] will be closed.", ws); ws->close_requested = true; if (ws->is_server) { - const struct lws_protocols *protocol = lws_vhost_name_to_protocol(ws->vh, - VINE_PROTOCOL_NAME); - if (!protocol) - return VINE_DATA_PATH_ERROR_OPERATION_FAILED; - - lws_callback_all_protocol_vhost_args(ws->vh, protocol, LWS_CALLBACK_USER, NULL, 0); - listen_vh_list.erase(ws->vh); - lws_vhost_destroy(ws->vh); - ws->vh = NULL; - _add_websocket_op_request(WEBSOCKET_OP_TERMINATE, - ws, 0, NULL, 0, NULL, 0, NULL); + ws, ws->vh, 0, NULL, 0, NULL, 0, NULL); _notify_websocket_op_request(); - return VINE_DATA_PATH_ERROR_NONE; } @@ -1058,8 +1108,6 @@ static int websocket_create(vine_dp_plugin_h *handle, void *plugin_data, void *u (websocket_s *)plugin_data : (websocket_s *)calloc(1, sizeof(websocket_s)); RET_VAL_IF(ws == NULL, VINE_DATA_PATH_ERROR_OUT_OF_MEMORY, "Out of memory"); - VINE_LOGD("ws[%p], user[%p]", ws, user); - ws->close_requested = false; ws->curr_conn = 0; ws->max_conn = 0; @@ -1075,27 +1123,16 @@ static int websocket_destroy(vine_dp_plugin_h handle) { RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL"); - VINE_LOGE("ws[%p] is destroyed", handle); - websocket_s *ws = (websocket_s *)handle; - - ws->wsi = NULL; - ws->vh = NULL; - ws->user = NULL; - free(ws->host_name); - ws->host_name = NULL; - free(ws->token); - ws->token = NULL; - ws->token_len = 0; - - delete ws->recv_buffer; - delete ws->write_buffer; - - ws->recv_buffer = NULL; - ws->write_buffer = NULL; - - free(ws); + websocket_s *ws = (websocket_s *)handle; + if (ws->destroy_requested) { + VINE_LOGD("Already requested."); + return VINE_DATA_PATH_ERROR_NONE; + } + ws->destroy_requested = true; + _add_websocket_op_request(WEBSOCKET_OP_DESTROY, ws, NULL, 0, NULL, 0, NULL, 0, NULL); + _notify_websocket_op_request(); return VINE_DATA_PATH_ERROR_NONE; } diff --git a/src/vine-data-path.cpp b/src/vine-data-path.cpp index 89fd74f..281059f 100755 --- a/src/vine-data-path.cpp +++ b/src/vine-data-path.cpp @@ -488,6 +488,10 @@ int vine_data_path_close(vine_data_path_h datapath) vine_data_path_s *dp = (vine_data_path_s *)datapath; RET_VAL_IF(!dp->plugin_fn || !dp->plugin_fn->close, VINE_ERROR_INVALID_PARAMETER, "plugin_fn is NULL"); + + // Unset callbacks related with vine_dp_open() before closing to avoid timing issue. + dp->opened_cb = NULL; + dp->connected_cb = NULL; dp->plugin_fn->close(dp->plugin_handle); return VINE_ERROR_NONE; @@ -569,6 +573,12 @@ int vine_data_path_destroy(vine_data_path_h datapath) dp->listen_dp = NULL; delete dp->state; + dp->opened_cb = NULL; + dp->accepted_cb = NULL; + dp->connected_cb = NULL; + dp->recv_cb = NULL; + dp->terminated_cb = NULL; + VINE_LOGD("data_path[%p] is destroyed", datapath); free(datapath); return VINE_ERROR_NONE; diff --git a/tests/vine-test/vine-test.cpp b/tests/vine-test/vine-test.cpp index 4e62d7f..bf77461 100755 --- a/tests/vine-test/vine-test.cpp +++ b/tests/vine-test/vine-test.cpp @@ -241,6 +241,16 @@ static void __opened_cb(vine_dp_h dp, vine_error_e result, void *user_data) __add_new_dp(dp); } +static void __joined_cb(vine_dp_h dp, const char *peer_id, void *user_data) +{ + printf(COLOR_GRN "[PEER_JOINED_CB] %s is joined." COLOR_RESET "\n", peer_id); +} + +static void __left_cb(vine_dp_h dp, const char *peer_id, void *user_data) +{ + printf(COLOR_GRN "[PEER_LEFT_CB] %s is left." COLOR_RESET "\n", peer_id); +} + static void __set_callbacks() { CHECK_SESSION; @@ -643,6 +653,8 @@ static void __join_service() vine_dp_set_address_family(g_pubsub_dp, (vine_address_family_e)addr_family); vine_dp_set_port(g_pubsub_dp, port); vine_dp_set_topic(g_pubsub_dp, topic); + vine_dp_set_peer_joined_cb(g_pubsub_dp, __joined_cb, NULL); + vine_dp_set_peer_left_cb(g_pubsub_dp, __left_cb, NULL); // TODO: set security. vine_dp_set_terminated_cb(g_pubsub_dp, __terminated_cb, NULL); -- 2.7.4 From 42b8270ac39b35517710f34918f55f49ad21e52f Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Tue, 28 Sep 2021 20:43:06 +0900 Subject: [PATCH 11/16] Return non-zero in lws callback when close request Change-Id: I230b34d087137fa65f762c9148339d2fe43aece2 --- plugins/libwebsockets/libwebsockets-plugin.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/plugins/libwebsockets/libwebsockets-plugin.cpp b/plugins/libwebsockets/libwebsockets-plugin.cpp index 096fcf3..428a445 100755 --- a/plugins/libwebsockets/libwebsockets-plugin.cpp +++ b/plugins/libwebsockets/libwebsockets-plugin.cpp @@ -297,7 +297,7 @@ static void _destroy_websocket(websocket_s *ws) if (!ws) return; - VINE_LOGD("ws[%s] is destroyed.", ws); + VINE_LOGD("ws[%p] is destroyed.", ws); ws->wsi = NULL; ws->vh = NULL; @@ -457,8 +457,18 @@ static int _websocket_protocol_cb(struct lws *wsi, lws_get_protocol(wsi)); // host private data. int n = 0; + if (ws && ws->close_requested + && reason != LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS) { + VINE_LOGD("ws[%p](user: %p) will be closed. Do nothing for it.", ws, ws->user); + return -1; + } + switch (reason) { - case LWS_CALLBACK_FILTER_NETWORK_CONNECTION : + case LWS_CALLBACK_WSI_DESTROY: + VINE_LOGI("wsi[%p](ws: %p) is destroyed.", wsi, ws); + break; + + case LWS_CALLBACK_FILTER_NETWORK_CONNECTION: if (vhd && vhd->max_conn > 0 && vhd->max_conn <= vhd->curr_conn) { VINE_LOGI("The max connection limit[%d] is reached. Reject the request.", vhd->max_conn); -- 2.7.4 From 88d7a85552527c83aec47ad1635f4ba731bedcd6 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Wed, 13 Oct 2021 17:25:15 +0900 Subject: [PATCH 12/16] Fix a crash issue Change-Id: Id36d4f16af7db555168b4f3cdc7ebad7c1584119 --- src/vine-disc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vine-disc.cpp b/src/vine-disc.cpp index cc994ff..8d092bd 100755 --- a/src/vine-disc.cpp +++ b/src/vine-disc.cpp @@ -298,7 +298,7 @@ void __vine_disc_epoll_handler(int fd, int events, void *user_data) { VINE_LOGD("Process event for fd[%d] events[%d] disc_handle[%p]", fd, events, user_data); vine_disc_s *disc_handle = (vine_disc_s *)user_data; - if (disc_handle->plugin_fn->process_event == NULL) { + if (!disc_handle || !disc_handle->plugin_fn || disc_handle->plugin_fn->process_event == NULL) { VINE_LOGE("No process_event() defined"); return; } -- 2.7.4 From 7619acc31ed099b8e78f291c59100d10e36e0b8e Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Fri, 15 Oct 2021 10:46:18 +0900 Subject: [PATCH 13/16] Change DP termination logic Change-Id: I123c9fd3babf9f37e68b1ad2d444f6b0b5f30cdb --- plugins/dns-sd/dns-sd-plugin.cpp | 5 + plugins/libwebsockets/libwebsockets-plugin.cpp | 129 ++++++++++++++++++------- src/include/vine-dp.h | 8 +- src/include/vine-queue.h | 25 ++++- src/vine-disc.cpp | 2 +- src/vine-dp.cpp | 45 +++++++-- src/vine-private.cpp | 6 +- src/vine-service.cpp | 1 + 8 files changed, 164 insertions(+), 57 deletions(-) diff --git a/plugins/dns-sd/dns-sd-plugin.cpp b/plugins/dns-sd/dns-sd-plugin.cpp index 7637bb5..0c6291d 100755 --- a/plugins/dns-sd/dns-sd-plugin.cpp +++ b/plugins/dns-sd/dns-sd-plugin.cpp @@ -164,6 +164,11 @@ void add_new_fd(vine_dns_sd_s *dns_sd_handle, static void __remove_service_ref(vine_dns_sd_s *dns_sd_handle, DNSServiceRef service_ref) { int fd = DNSServiceRefSockFD(service_ref); + if (fd < 0) { + VINE_LOGE("Invalid fd[%d]", fd); + return; + } + VINE_LOGD("fd[%d] to be removed", fd); if (event_callbacks.fd_removed_cb) event_callbacks.fd_removed_cb(fd, dns_sd_handle->user_data); diff --git a/plugins/libwebsockets/libwebsockets-plugin.cpp b/plugins/libwebsockets/libwebsockets-plugin.cpp index 428a445..60933ee 100755 --- a/plugins/libwebsockets/libwebsockets-plugin.cpp +++ b/plugins/libwebsockets/libwebsockets-plugin.cpp @@ -73,6 +73,7 @@ typedef enum { WEBSOCKET_OP_WRITE, WEBSOCKET_OP_TERMINATE, WEBSOCKET_OP_DESTROY, + WEBSOCKET_OP_DEINIT, } websocket_op_code_e; typedef struct { @@ -257,7 +258,6 @@ static int _add_websocket_op_request(websocket_op_code_e code, } op_queue.push(op); - return 0; } @@ -284,8 +284,8 @@ static void _process_pending_destroy(struct lws_vhost *vh) lws_callback_all_protocol_vhost_args(vh, protocol, LWS_CALLBACK_USER, NULL, 0); listen_vh_list.erase(vh); - lws_vhost_destroy(vh); - VINE_LOGI("vh[%p] is destroyed", vh); + //lws_vhost_destroy(vh); + VINE_LOGI("vh[%p] is erased.", vh); while (!lws_service_adjust_timeout(g_context, 1, 0)) lws_service_tsi(g_context, -1, 0); @@ -318,6 +318,31 @@ static void _destroy_websocket(websocket_s *ws) free(ws); } +static void _destroy_context(struct lws_context *context) +{ + lws_context_destroy(context); +} + +static void _clear_listen_vhosts(void) +{ + listen_vh_list.clear(); +} + +static void _deinit(void) +{ + _destroy_context(g_context); + g_context = NULL; + + auto it = g_pollfds.begin(); + while (it != g_pollfds.end()) { + free(it->second); + it = g_pollfds.erase(it); + } + + _clear_listen_vhosts(); + VINE_LOGI("-"); +} + static void _process_websocket_op_request(void) { RET_IF(op_queue.empty(), "operation queue is NULL"); @@ -326,7 +351,7 @@ static void _process_websocket_op_request(void) op_queue.pop(); RET_IF(op == NULL, "op is NULL"); - if (!op->ws) { + if (!op->ws && op->code != WEBSOCKET_OP_DEINIT) { _del_websocket_op_request(op); return; } @@ -347,6 +372,10 @@ static void _process_websocket_op_request(void) case WEBSOCKET_OP_DESTROY: _destroy_websocket(op->ws); break; + case WEBSOCKET_OP_DEINIT: + _deinit(); + break; + default: break; } @@ -354,6 +383,55 @@ static void _process_websocket_op_request(void) _del_websocket_op_request(op); } +static void do_func(websocket_op_s *op) +{ + if (op == NULL) + return; + + VINE_LOGD("op[%p] op->code[%d]", op, op->code); + switch (op->code) { + case WEBSOCKET_OP_OPEN: + VINE_LOGI("Ignore."); + break; + case WEBSOCKET_OP_CONNECT: + VINE_LOGI("Ignore."); + break; + case WEBSOCKET_OP_WRITE: + VINE_LOGI("Ignore."); + // Do! + break; + case WEBSOCKET_OP_TERMINATE: + VINE_LOGI("Terminate."); + _process_pending_destroy(op->vh); + // Do! + break; + case WEBSOCKET_OP_DESTROY: + VINE_LOGI("destroy."); + //_destroy_websocket(op->ws); + // error + break; + case WEBSOCKET_OP_DEINIT: + VINE_LOGI("This cannot be called here."); + break; + default: + break; + } + _del_websocket_op_request(op); +} + +static void _flush_op_queue(websocket_s *ws) +{ + VINE_LOGD("flush ws[%p]", ws); + + size_t count = op_queue.size(); + + while (count-- > 0) { + op_queue.do_remove_if([&](websocket_op_s *op) { + return (ws == NULL || (op && op->ws == ws)); + }, do_func); + } +} + static struct lws_context *_create_context(void) { struct lws_context_creation_info info; @@ -374,11 +452,6 @@ static struct lws_context *_create_context(void) return lws_create_context(&info); } -static void _destroy_context(struct lws_context *context) -{ - lws_context_destroy(context); -} - static void _add_websocket_poll_fd(struct lws_pollargs *args) { RET_IF(args == NULL, "args is NULL"); @@ -457,12 +530,6 @@ static int _websocket_protocol_cb(struct lws *wsi, lws_get_protocol(wsi)); // host private data. int n = 0; - if (ws && ws->close_requested - && reason != LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS) { - VINE_LOGD("ws[%p](user: %p) will be closed. Do nothing for it.", ws, ws->user); - return -1; - } - switch (reason) { case LWS_CALLBACK_WSI_DESTROY: VINE_LOGI("wsi[%p](ws: %p) is destroyed.", wsi, ws); @@ -718,13 +785,6 @@ static int websocket_init(void) return VINE_DATA_PATH_ERROR_NONE; } -static void _clear_listen_vhosts(void) -{ - for (auto &vh : listen_vh_list) - lws_vhost_destroy(vh); - listen_vh_list.clear(); -} - static void websocket_deinit(void) { if (__sync_sub_and_fetch(&g_ref_count, 1) > 0) { @@ -732,16 +792,12 @@ static void websocket_deinit(void) return; } - _destroy_context(g_context); - g_context = NULL; - - auto it = g_pollfds.begin(); - while (it != g_pollfds.end()) { - free(it->second); - it = g_pollfds.erase(it); - } + _flush_op_queue(NULL); + // Run deinit in eventloop thread + _add_websocket_op_request(WEBSOCKET_OP_DEINIT, + NULL, NULL, 0, NULL, 0, NULL, 0, NULL); + _notify_websocket_op_request(); - _clear_listen_vhosts(); VINE_LOGD("lws is deinitialized."); } @@ -1069,8 +1125,9 @@ static int websocket_close(vine_dp_plugin_h handle) VINE_LOGD("ws[%p] will be closed.", ws); ws->close_requested = true; if (ws->is_server) { - _add_websocket_op_request(WEBSOCKET_OP_TERMINATE, - ws, ws->vh, 0, NULL, 0, NULL, 0, NULL); + if (_add_websocket_op_request(WEBSOCKET_OP_TERMINATE, + ws, ws->vh, 0, NULL, 0, NULL, 0, NULL) < 0) + return VINE_DATA_PATH_ERROR_OPERATION_FAILED; _notify_websocket_op_request(); return VINE_DATA_PATH_ERROR_NONE; } @@ -1103,7 +1160,7 @@ static void websocket_process_event(int fd, int events) lws_service_fd(g_context, pollfd); // Check for any connection needing forced service. - while (!lws_service_adjust_timeout(g_context, 1, 0)) { + if (!lws_service_adjust_timeout(g_context, 1, 0)) { // Service any pending webscoket activity. // Only needed if multiple service threads. lws_service_tsi(g_context, -1, 0); @@ -1140,9 +1197,9 @@ static int websocket_destroy(vine_dp_plugin_h handle) return VINE_DATA_PATH_ERROR_NONE; } + _flush_op_queue(ws); + ws->destroy_requested = true; - _add_websocket_op_request(WEBSOCKET_OP_DESTROY, ws, NULL, 0, NULL, 0, NULL, 0, NULL); - _notify_websocket_op_request(); return VINE_DATA_PATH_ERROR_NONE; } diff --git a/src/include/vine-dp.h b/src/include/vine-dp.h index 2e86615..f0bb97d 100755 --- a/src/include/vine-dp.h +++ b/src/include/vine-dp.h @@ -42,7 +42,7 @@ public: virtual ~DataPath() {} virtual int open(vine_dp_opened_cb callback, void *user_data) = 0; - virtual void close() = 0; + virtual int close() = 0; virtual int send(unsigned char *buf, size_t len) = 0; virtual int recv(unsigned char *buf, size_t buf_len, size_t *read_len) = 0; @@ -106,7 +106,7 @@ public: virtual ~DPServer(); virtual int open(vine_dp_opened_cb callback, void *user_data); - virtual void close(); + virtual int close(); virtual int send(unsigned char *buf, size_t len); virtual int recv(unsigned char *buf, size_t buf_len, size_t *read_len); @@ -156,7 +156,7 @@ public: virtual ~DPClient(); virtual int open(vine_dp_opened_cb callback, void *user_data); - virtual void close(); + virtual int close(); virtual int send(unsigned char *buf, size_t len); virtual int recv(unsigned char *buf, size_t buf_len, size_t *read_len); @@ -216,7 +216,7 @@ public: virtual ~DPPubSub(); virtual int open(vine_dp_opened_cb callback, void *user_data); - virtual void close(); + virtual int close(); virtual int send(unsigned char *buf, size_t len); virtual int recv(unsigned char *buf, size_t buf_len, size_t *read_len); diff --git a/src/include/vine-queue.h b/src/include/vine-queue.h index 5b805e8..dd80d46 100755 --- a/src/include/vine-queue.h +++ b/src/include/vine-queue.h @@ -16,8 +16,9 @@ */ #pragma once +#include #include -#include +#include #include "vine-log.h" @@ -37,7 +38,7 @@ public: void push(const T &element) { std::lock_guard lock_guard(_q_mutex); - _queue.push(element); + _queue.push_back(element); } void pop() @@ -45,7 +46,7 @@ public: std::lock_guard lock_guard(_q_mutex); if (_queue.empty()) return; - _queue.pop(); + _queue.pop_front(); } T &front() @@ -72,7 +73,23 @@ public: return _queue.empty(); } + typedef void (*do_func)(T t); + + template void do_remove_if(UnaryPredicate comp_f, do_func do_f) + { + std::lock_guard lock_guard(_q_mutex); + for (auto it = _queue.begin(); it != _queue.end();) { + if (comp_f(*it)) { + do_f(*it); + it = _queue.erase(it); + } + else { + ++it; + } + } + } + private: - std::queue _queue; + std::list _queue; std::mutex _q_mutex; }; diff --git a/src/vine-disc.cpp b/src/vine-disc.cpp index 8d092bd..7b0679d 100755 --- a/src/vine-disc.cpp +++ b/src/vine-disc.cpp @@ -298,7 +298,7 @@ void __vine_disc_epoll_handler(int fd, int events, void *user_data) { VINE_LOGD("Process event for fd[%d] events[%d] disc_handle[%p]", fd, events, user_data); vine_disc_s *disc_handle = (vine_disc_s *)user_data; - if (!disc_handle || !disc_handle->plugin_fn || disc_handle->plugin_fn->process_event == NULL) { + if (!disc_handle || !disc_handle->plugin_fn || !disc_handle->plugin_fn->process_event) { VINE_LOGE("No process_event() defined"); return; } diff --git a/src/vine-dp.cpp b/src/vine-dp.cpp index c9475ee..e2e04d1 100755 --- a/src/vine-dp.cpp +++ b/src/vine-dp.cpp @@ -44,6 +44,15 @@ using namespace vine; } \ } while (0) +#define RET_ERR_IF_DP_OPEN_STATE_ISNT_DONE(state) \ + do { \ + if (state != VINE_DP_OPEN_STATE_DONE) { \ + VINE_LOGE("DP isn't opened."); \ + return VINE_ERROR_INVALID_OPERATION; \ + } \ + } while (0) + + extern vine_dp_plugin_fn g_dp_plugin_fn; static bool _check_if_valid_ip(vine_address_family_e addr_family, const char *ip) @@ -424,13 +433,17 @@ int DataPath::set_iface_name(const std::string &iface_name) void DataPath::invoke_opened_cb(int result) { + if (result == VINE_ERROR_NONE) + mOpenState = VINE_DP_OPEN_STATE_DONE; + else + mOpenState = VINE_DP_OPEN_STATE_NONE; + if (mOpenedCb) mOpenedCb(static_cast(this), (vine_error_e)result, mOpenedCbData); // called only once. mOpenedCb = NULL; mOpenedCbData = NULL; - mOpenState = VINE_DP_OPEN_STATE_DONE; } int DataPath::set_received_cb(vine_dp_received_cb callback, void *user_data) @@ -685,19 +698,23 @@ int DPServer::open(vine_dp_opened_cb callback, void *user_data) return ret; } -void DPServer::close() -{ +int DPServer::close() { + RET_ERR_IF_DP_OPEN_STATE_ISNT_DONE(mOpenState); mOpenState = VINE_DP_OPEN_STATE_NONE; + unset_received_cb(); vine_data_path_close(mDataPath); + return VINE_ERROR_NONE; } int DPServer::send(unsigned char *buf, size_t len) { + RET_ERR_IF_DP_OPEN_STATE_ISNT_DONE(mOpenState); return vine_data_path_write(mDataPath, buf, len); } int DPServer::recv(unsigned char *buf, size_t buf_len, size_t *read_len) { + RET_ERR_IF_DP_OPEN_STATE_ISNT_DONE(mOpenState); return vine_data_path_read(mDataPath, buf, buf_len, read_len); } @@ -707,6 +724,7 @@ DPClient::DPClient(void *event_queue) mMethod = VINE_DATA_PATH_METHOD_LWS; mEventQueue = event_queue; mSecurity = NULL; + mOpenState = VINE_DP_OPEN_STATE_NONE; mAddrFamily = VINE_ADDRESS_FAMILY_DEFAULT; mIfaceName = ""; mDataPath = NULL; @@ -729,7 +747,7 @@ DPClient::DPClient(void *event_queue, void *datapath) VINE_LOGD("DPClient[%p] is created with datapath[%p]", this, datapath); mEventQueue = event_queue; mSecurity = NULL; - mOpenState = VINE_DP_OPEN_STATE_NONE; + mOpenState = VINE_DP_OPEN_STATE_DONE; mDataPath = datapath; mAddrFamily = vine_data_path_get_addr_family(mDataPath); mPeerIp = vine_data_path_get_ip(mDataPath); @@ -929,19 +947,24 @@ int DPClient::open(vine_dp_opened_cb callback, void *user_data) return ret; } -void DPClient::close() +int DPClient::close() { + RET_ERR_IF_DP_OPEN_STATE_ISNT_DONE(mOpenState); mOpenState = VINE_DP_OPEN_STATE_NONE; + unset_received_cb(); vine_data_path_close(mDataPath); + return VINE_ERROR_NONE; } int DPClient::send(unsigned char *buf, size_t len) { + RET_ERR_IF_DP_OPEN_STATE_ISNT_DONE(mOpenState); return vine_data_path_write(mDataPath, buf, len); } int DPClient::recv(unsigned char *buf, size_t buf_len, size_t *read_len) { + RET_ERR_IF_DP_OPEN_STATE_ISNT_DONE(mOpenState); return vine_data_path_read(mDataPath, buf, buf_len, read_len); } @@ -982,7 +1005,6 @@ DPPubSub::~DPPubSub() { VINE_LOGD("DPPubSub[%p] is deleted.", this); _vine_security_destroy(mSecurity); - close(); } int DPPubSub::set_method(vine_dp_method_e method) @@ -1316,11 +1338,14 @@ int DPPubSub::open(vine_dp_opened_cb callback, void *user_data) return VINE_ERROR_NONE; } -void DPPubSub::close() +int DPPubSub::close() { + RET_ERR_IF_DP_OPEN_STATE_ISNT_DONE(mOpenState); vine_disc_stop_publish(mSdPub); vine_disc_stop_subscribe(mSdSub); + unset_received_cb(); + vine_disc_destroy(mSdSub); mSdSub = NULL; vine_disc_destroy(mSdPub); @@ -1332,10 +1357,12 @@ void DPPubSub::close() mServerDataPath = NULL; mOpenState = VINE_DP_OPEN_STATE_NONE; + return VINE_ERROR_NONE; } int DPPubSub::send(unsigned char *buf, size_t len) { + RET_ERR_IF_DP_OPEN_STATE_ISNT_DONE(mOpenState); int ret = VINE_ERROR_NONE; for (auto &peer : mDataPathList) { @@ -1353,6 +1380,7 @@ int DPPubSub::send(unsigned char *buf, size_t len) int DPPubSub::recv(unsigned char *buf, size_t buf_len, size_t *read_len) { + RET_ERR_IF_DP_OPEN_STATE_ISNT_DONE(mOpenState); auto &dp_info = mRecvDataPathList.front(); size_t bytes = 0; int ret = vine_data_path_read(dp_info.first, buf, buf_len, &bytes); @@ -1781,8 +1809,7 @@ int _vine_dp_close(vine_dp_h dp) RET_VAL_IF(dp == NULL, VINE_ERROR_INVALID_PARAMETER, "dp is null."); DataPath *_dp = static_cast(dp); - _dp->close(); - return VINE_ERROR_NONE; + return _dp->close(); } int _vine_dp_send(vine_dp_h dp, unsigned char *buf, size_t len) diff --git a/src/vine-private.cpp b/src/vine-private.cpp index c2561f4..7fb97d5 100755 --- a/src/vine-private.cpp +++ b/src/vine-private.cpp @@ -100,10 +100,10 @@ int _vine_deinit() } if (__vine_unref() == 0) { - vine_event_loop_stop(); - vine_event_loop_deinit(); vine_data_path_deinit(); vine_disc_deinit(); + vine_event_loop_stop(); + vine_event_loop_deinit(); } VINE_UNLOCK(&__vine_mutex); return VINE_ERROR_NONE; @@ -135,4 +135,4 @@ int _vine_set_event_loop(vine_event_loop_e loop) } VINE_UNLOCK(&__vine_mutex); return vine_event_loop_set(loop); -} \ No newline at end of file +} diff --git a/src/vine-service.cpp b/src/vine-service.cpp index a86e371..d5b8258 100755 --- a/src/vine-service.cpp +++ b/src/vine-service.cpp @@ -128,6 +128,7 @@ int _vine_service_clone(vine_service_h origin, vine_service_h *cloned) cloned_service->state = origin_service->state; cloned_service->disc_handle = NULL; + cloned_service->ip_resolving_session = NULL; cloned_service->ip_resolved_cb = NULL; cloned_service->ip_resolved_cb_data = NULL; -- 2.7.4 From 4368c76572fbb2e4f86d17901cc2495e30b74351 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Tue, 19 Oct 2021 10:42:36 +0900 Subject: [PATCH 14/16] Change DP termination logic #2 - Move destory operation to event loop thread - Move deinit operation to event loop thread - Destroy a vhost using lws_vhost_destroy() - Check a fd of websocket_op_s before processing op queue Change-Id: I572b2c7449362e47c6506fc121f4fcfdd2de0d65 --- plugins/libwebsockets/libwebsockets-plugin.cpp | 98 +++++++++++++++----------- src/vine-event-loop-epoll.cpp | 1 + 2 files changed, 58 insertions(+), 41 deletions(-) diff --git a/plugins/libwebsockets/libwebsockets-plugin.cpp b/plugins/libwebsockets/libwebsockets-plugin.cpp index 60933ee..748a117 100755 --- a/plugins/libwebsockets/libwebsockets-plugin.cpp +++ b/plugins/libwebsockets/libwebsockets-plugin.cpp @@ -86,6 +86,8 @@ typedef struct { char *iface_name; // open, connect only int max_conn; // open only vine_dp_ssl ssl; // open, connect only + + int fd; // eventfd } websocket_op_s; static VineQueue op_queue; @@ -220,24 +222,25 @@ static void _get_peer_network_info(struct lws *wsi, VINE_LOGD("address family[%d] peer ip[%s], peer port[%d]\n", addr.ss_family, ip, *port); } -static void _notify_websocket_op_request() +static void _notify_websocket_op_request(websocket_op_s *op) { uint64_t v = 1; int _eventfd = eventfd(0, 0); + op->fd = _eventfd; g_callbacks.pollfd_cb(VINE_DATA_PATH_POLLFD_OP, _eventfd, LWS_POLLOUT, NULL); if (write(_eventfd, &v, sizeof(v)) == -1) VINE_LOGE("Write error(%d)", errno); } -static int _add_websocket_op_request(websocket_op_code_e code, +static websocket_op_s *_add_websocket_op_request(websocket_op_code_e code, websocket_s *ws, struct lws_vhost *vh, int addr_family, const char *ip, int port, const char *iface_name, int max_conn, vine_dp_ssl *ssl) { websocket_op_s *op = (websocket_op_s *)calloc(1, sizeof(websocket_op_s)); if (!op) - return -1; + return NULL; op->code = code; op->ws = ws; @@ -258,7 +261,8 @@ static int _add_websocket_op_request(websocket_op_code_e code, } op_queue.push(op); - return 0; + return op; + //return 0; } static void _del_websocket_op_request(websocket_op_s *op) @@ -284,8 +288,8 @@ static void _process_pending_destroy(struct lws_vhost *vh) lws_callback_all_protocol_vhost_args(vh, protocol, LWS_CALLBACK_USER, NULL, 0); listen_vh_list.erase(vh); - //lws_vhost_destroy(vh); - VINE_LOGI("vh[%p] is erased.", vh); + VINE_LOGI("vh[%p] will be destroyed.", vh); + lws_vhost_destroy(vh); while (!lws_service_adjust_timeout(g_context, 1, 0)) lws_service_tsi(g_context, -1, 0); @@ -343,13 +347,15 @@ static void _deinit(void) VINE_LOGI("-"); } -static void _process_websocket_op_request(void) +static void _process_websocket_op_request(int fd) { RET_IF(op_queue.empty(), "operation queue is NULL"); websocket_op_s *op = op_queue.front(); - op_queue.pop(); RET_IF(op == NULL, "op is NULL"); + RET_IF(op->fd != fd, "Not matched event. op->fd[%d] fd[%d]", op->fd, fd); + + op_queue.pop(); if (!op->ws && op->code != WEBSOCKET_OP_DEINIT) { _del_websocket_op_request(op); @@ -398,21 +404,17 @@ static void do_func(websocket_op_s *op) break; case WEBSOCKET_OP_WRITE: VINE_LOGI("Ignore."); - // Do! + // TODO: do write. break; case WEBSOCKET_OP_TERMINATE: - VINE_LOGI("Terminate."); - _process_pending_destroy(op->vh); - // Do! - break; + VINE_LOGI("Terminate. Do not handle here. ws[%p]", op->ws); + return; case WEBSOCKET_OP_DESTROY: - VINE_LOGI("destroy."); - //_destroy_websocket(op->ws); - // error - break; + VINE_LOGI("Destroy. Do not handle here. ws[%p]", op->ws); + return; case WEBSOCKET_OP_DEINIT: - VINE_LOGI("This cannot be called here."); - break; + VINE_LOGE("This cannot be called here."); + return; default: break; } @@ -638,7 +640,7 @@ static int _websocket_protocol_cb(struct lws *wsi, case LWS_CALLBACK_RECEIVE: { VINE_LOGI("%d bytes is received from client.", len); - if (!ws) + if (!ws || len == 0) return 0; size_t total_len = _save_data(ws, in, len, @@ -721,7 +723,7 @@ static int _websocket_protocol_cb(struct lws *wsi, case LWS_CALLBACK_CLIENT_RECEIVE: { VINE_LOGI("%d bytes is received from server.", len); - if (!ws) + if (!ws || len == 0) return 0; size_t total_len = _save_data(ws, in, len, @@ -794,9 +796,13 @@ static void websocket_deinit(void) _flush_op_queue(NULL); // Run deinit in eventloop thread - _add_websocket_op_request(WEBSOCKET_OP_DEINIT, + websocket_op_s *op = _add_websocket_op_request(WEBSOCKET_OP_DEINIT, NULL, NULL, 0, NULL, 0, NULL, 0, NULL); - _notify_websocket_op_request(); + if (!op) { + VINE_LOGE("Failed to add deinit operation to queue"); + return; + } + _notify_websocket_op_request(op); VINE_LOGD("lws is deinitialized."); } @@ -898,12 +904,14 @@ static int websocket_open(vine_dp_plugin_h handle, websocket_s *ws = (websocket_s *)handle; ws->is_server = true; VINE_LOGD("ws[%p]", ws); - if (_add_websocket_op_request(WEBSOCKET_OP_OPEN, + + websocket_op_s *op = _add_websocket_op_request(WEBSOCKET_OP_OPEN, (websocket_s *)handle, NULL, - addr_family, NULL, port, iface_name, max_conn, &ssl) < 0) - return VINE_DATA_PATH_ERROR_OPERATION_FAILED; + addr_family, NULL, port, iface_name, max_conn, &ssl); + if (!op) + return VINE_DATA_PATH_ERROR_OUT_OF_MEMORY; - _notify_websocket_op_request(); + _notify_websocket_op_request(op); return VINE_DATA_PATH_ERROR_NONE; } @@ -944,12 +952,13 @@ static int websocket_connect(vine_dp_plugin_h handle, RET_VAL_IF(!handle, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL"); RET_VAL_IF(!g_context, VINE_DATA_PATH_ERROR_INVALID_OPERATION, "g_context is NULL"); - if (_add_websocket_op_request(WEBSOCKET_OP_CONNECT, + websocket_op_s *op = _add_websocket_op_request(WEBSOCKET_OP_CONNECT, (websocket_s *)handle, NULL, - addr_family, ip, port, iface_name, 0, &ssl) < 0) - return VINE_DATA_PATH_ERROR_OPERATION_FAILED; + addr_family, ip, port, iface_name, 0, &ssl); + if (!op) + return VINE_DATA_PATH_ERROR_OUT_OF_MEMORY; - _notify_websocket_op_request(); + _notify_websocket_op_request(op); return VINE_DATA_PATH_ERROR_NONE; } @@ -1103,11 +1112,12 @@ static int websocket_write(vine_dp_plugin_h handle, unsigned char *buf, size_t l ws->write_buffer->push(wd); VINE_LOGD("websocket_data[%p] is pushed to write_buffer. len[%d]", wd, len); - if (_add_websocket_op_request(WEBSOCKET_OP_WRITE, ws, NULL, - 0, NULL, -1, NULL, 0, NULL) < 0) - return VINE_DATA_PATH_ERROR_OPERATION_FAILED; + websocket_op_s *op = _add_websocket_op_request(WEBSOCKET_OP_WRITE, ws, NULL, + 0, NULL, -1, NULL, 0, NULL); + if (!op) + return VINE_DATA_PATH_ERROR_OUT_OF_MEMORY; - _notify_websocket_op_request(); + _notify_websocket_op_request(op); return VINE_DATA_PATH_ERROR_NONE; } @@ -1125,10 +1135,11 @@ static int websocket_close(vine_dp_plugin_h handle) VINE_LOGD("ws[%p] will be closed.", ws); ws->close_requested = true; if (ws->is_server) { - if (_add_websocket_op_request(WEBSOCKET_OP_TERMINATE, - ws, ws->vh, 0, NULL, 0, NULL, 0, NULL) < 0) - return VINE_DATA_PATH_ERROR_OPERATION_FAILED; - _notify_websocket_op_request(); + websocket_op_s *op = _add_websocket_op_request(WEBSOCKET_OP_TERMINATE, + ws, ws->vh, 0, NULL, 0, NULL, 0, NULL); + if (!op) + return VINE_DATA_PATH_ERROR_OUT_OF_MEMORY; + _notify_websocket_op_request(op); return VINE_DATA_PATH_ERROR_NONE; } @@ -1142,7 +1153,7 @@ static void websocket_process_event(int fd, int events) { auto it = g_pollfds.find(fd); if (it == g_pollfds.end()) { - _process_websocket_op_request(); + _process_websocket_op_request(fd); close(fd); return; } @@ -1198,8 +1209,13 @@ static int websocket_destroy(vine_dp_plugin_h handle) } _flush_op_queue(ws); - ws->destroy_requested = true; + websocket_op_s *op = _add_websocket_op_request(WEBSOCKET_OP_DESTROY, + (websocket_s *)handle, NULL, 0, NULL, 0, NULL, 0, NULL); + if (!op) + return VINE_DATA_PATH_ERROR_OPERATION_FAILED; + _notify_websocket_op_request(op); + return VINE_DATA_PATH_ERROR_NONE; } diff --git a/src/vine-event-loop-epoll.cpp b/src/vine-event-loop-epoll.cpp index 626da1c..5e7318a 100755 --- a/src/vine-event-loop-epoll.cpp +++ b/src/vine-event-loop-epoll.cpp @@ -141,6 +141,7 @@ void vine_event_loop_epoll_stop() __cleanup = true; _vine_event_loop_epoll_wake_up(); pthread_join(__vine_event_loop_epoll_tid, NULL); + VINE_LOGD("eventloop thread is terminated."); __vine_event_loop_epoll_tid = 0; } -- 2.7.4 From 7ef30077ebe316214d23e266b5bb2a278ce16503 Mon Sep 17 00:00:00 2001 From: cheoleun moon Date: Tue, 19 Oct 2021 14:55:31 +0900 Subject: [PATCH 15/16] Introduce VineMap for synchronized map Change-Id: I9f8940cef3fe8a8079bf30760e938099aaa464fb --- plugins/dns-sd/dns-sd-plugin.cpp | 39 ++++++++++---------- src/include/vine-map.h | 80 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 20 deletions(-) create mode 100755 src/include/vine-map.h diff --git a/plugins/dns-sd/dns-sd-plugin.cpp b/plugins/dns-sd/dns-sd-plugin.cpp index 0c6291d..5d8f5a9 100755 --- a/plugins/dns-sd/dns-sd-plugin.cpp +++ b/plugins/dns-sd/dns-sd-plugin.cpp @@ -26,6 +26,7 @@ #include "vine-constants.h" #include "vine-disc-plugin.h" #include "vine-log.h" +#include "vine-map.h" #include "vine-utils.h" #include "dns-sd-plugin.h" @@ -37,7 +38,7 @@ typedef struct { int fd; void *user_data; // vine_disc handle char service_type[VINE_MAX_SERVICE_TYPE_LEN + 1]; - map sdref_map; // + VineMap sdref_map; // DNSServiceRef get_addr_ref; // Used for only resolve_ip } vine_dns_sd_s; @@ -45,7 +46,7 @@ typedef struct { typedef struct { char service_type[VINE_MAX_SERVICE_TYPE_LEN + 1]; char service_name[VINE_MAX_SERVICE_NAME_LEN + 1]; - map attributes; + std::map attributes; int port; vine_dns_sd_s *dns_sd_handle; } dns_sd_discovered_service_s; @@ -150,8 +151,8 @@ void add_new_fd(vine_dns_sd_s *dns_sd_handle, int fd = DNSServiceRefSockFD(service_ref); VINE_LOGD("Insert new service ref[%p] fd[%d]", service_ref, fd); - if (dns_sd_handle->sdref_map.find(fd) == dns_sd_handle->sdref_map.end()) { - dns_sd_handle->sdref_map[fd] = service_ref; + if (!dns_sd_handle->sdref_map.find(fd)) { + dns_sd_handle->sdref_map.insert(fd, service_ref); VINE_LOGD("New fd[%d] to be added", fd); } else { VINE_LOGI("Duplicate fd[%d]", fd); @@ -182,17 +183,14 @@ static void __remove_service_ref(vine_dns_sd_s *dns_sd_handle, DNSServiceRef ser static void __remove_service_ref_all(vine_dns_sd_s *dns_sd_handle) { VINE_LOGD("Remove all DNSServiceRef for dns_sd_handle[%p]", dns_sd_handle); - for (auto iter = dns_sd_handle->sdref_map.begin(); - iter != dns_sd_handle->sdref_map.end(); ++iter) { - int fd = iter->first; - DNSServiceRef service_ref = iter->second; + dns_sd_handle->sdref_map.for_each([&](int fd, DNSServiceRef service_ref) { + if (event_callbacks.fd_removed_cb) + event_callbacks.fd_removed_cb(fd, dns_sd_handle->user_data); + DNSServiceRefDeallocate(service_ref); - if (event_callbacks.fd_removed_cb) - event_callbacks.fd_removed_cb(fd, dns_sd_handle->user_data); - DNSServiceRefDeallocate(service_ref); + VINE_LOGD("fd[%d]/service_ref[%p] is removed.", fd, service_ref); + }); - VINE_LOGD("fd[%d]/service_ref[%p] is removed.", fd, service_ref); - } dns_sd_handle->sdref_map.clear(); } @@ -499,11 +497,12 @@ void dns_sd_deinit(void *plugin_handle) RET_IF(plugin_handle == NULL, "Plugin handle is null"); vine_dns_sd_s *dns_sd_handle = (vine_dns_sd_s *)plugin_handle; - auto it = dns_sd_handle->sdref_map.begin(); - while (it != dns_sd_handle->sdref_map.end()) { - DNSServiceRefDeallocate(it->second); - it = dns_sd_handle->sdref_map.erase(it); - } + dns_sd_handle->sdref_map.for_each([&](int fd, DNSServiceRef service_ref) { + DNSServiceRefDeallocate(service_ref); + VINE_LOGD("fd[%d]/service_ref[%p] is removed.", fd, service_ref); + }); + + dns_sd_handle->sdref_map.clear(); delete dns_sd_handle; } @@ -610,9 +609,9 @@ vine_disc_error dns_sd_process_event(void *plugin_handle, int fd) RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL"); vine_dns_sd_s *dns_sd_handle = (vine_dns_sd_s *)plugin_handle; - DNSServiceRef service_ref = dns_sd_handle->sdref_map[fd]; - RET_VAL_IF(service_ref == NULL, VINE_DISC_ERROR_INVALID_PARAMETER, + RET_VAL_IF(!dns_sd_handle->sdref_map.find(fd), VINE_DISC_ERROR_INVALID_PARAMETER, "No DNSServiceRef for fd"); + DNSServiceRef service_ref = dns_sd_handle->sdref_map.at(fd); VINE_LOGD("service ref[%p] to be processed", service_ref); DNSServiceErrorType err = DNSServiceProcessResult(service_ref); if (err) { diff --git a/src/include/vine-map.h b/src/include/vine-map.h new file mode 100755 index 0000000..12e79a8 --- /dev/null +++ b/src/include/vine-map.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + * +*/ +#pragma once + +#include +#include +#include + +#include "vine-log.h" + +template +class VineMap +{ +public: + VineMap() + { + VINE_LOGD("New Map"); + } + virtual ~VineMap() + { + VINE_LOGD("Destroy Map"); + } + + // If the key of the inserted element already exists in the internal map, + // the element is not inserted. + void insert(const K &key, const V &val) + { + std::lock_guard lock_guard(_q_mutex); + _map.insert(std::pair(key, val)); + } + + const V &at(const K &key) + { + std::lock_guard lock_guard(_q_mutex); + return _map.at(key); + } + + bool find(const K &key) + { + std::lock_guard lock_guard(_q_mutex); + return _map.find(key) != _map.end(); + } + + void erase(const K &key) + { + std::lock_guard lock_guard(_q_mutex); + _map.erase(key); + } + + void clear() + { + std::lock_guard lock_guard(_q_mutex); + _map.clear(); + } + + // The protyotype of do_func(): void func(K &k, V & v) + template void for_each(BinaryPredicate do_func) + { + for (auto it = _map.begin(); it != _map.end(); ++it) + do_func(it->first, it->second); + } + +private: + std::map _map; + std::mutex _q_mutex; +}; -- 2.7.4 From 4578153184a65e0acc204e52a19e334c3d8a4f27 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Tue, 19 Oct 2021 19:52:41 +0900 Subject: [PATCH 16/16] Check datapath handle before invoking user callback Change-Id: Icf8f93326397a7372b0ed1c8b5ad8eb9a15efcf9 --- src/vine-data-path.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/src/vine-data-path.cpp b/src/vine-data-path.cpp index 281059f..b11baa1 100755 --- a/src/vine-data-path.cpp +++ b/src/vine-data-path.cpp @@ -49,6 +49,8 @@ struct { {NULL, NULL, NULL, NULL, NULL, NULL, NULL}, NULL}, }; +const int VALIDATOR_BITS = 0x12345678; + typedef struct { vine_data_path_method_e method; vine_dp_plugin_fn *plugin_fn; @@ -76,8 +78,20 @@ typedef struct { established_notifier established; vine_data_path_h listen_dp; // only for client dp in the server side + + int validator; } vine_data_path_s; +inline bool data_path_validate(vine_data_path_s *datapath, const char *func) +{ + RET_VAL_IF(datapath == NULL, false, "datapath is NULL"); + RET_VAL_IF(datapath->plugin_handle == NULL, false, "plugin_handle is NULL"); + RET_VAL_IF((((int)datapath->plugin_handle) ^ ((int)datapath->validator)) != VALIDATOR_BITS, false, + "validator fails. plugin_handle[%x] validator[%x]", datapath->plugin_handle, datapath->validator); + + return true; +} + typedef struct { int result; int port; @@ -206,7 +220,7 @@ static void __invoke_accepted_user_cb(void *event, void *user_data) VINE_LOGD("user callback is invoked by event queue."); - if (listen_dp && listen_dp->accepted_cb) + if (data_path_validate(listen_dp, __FUNCTION__) && listen_dp->accepted_cb) listen_dp->accepted_cb(accepted_event->connected_dp, listen_dp->accepted_cb_data); } @@ -233,7 +247,7 @@ void notify_accepted(vine_data_path_h datapath, int result) vine_data_path_s *listen_dp = (vine_data_path_s *)dp->listen_dp; VINE_LOGD("listen_dp[%p]", listen_dp); - if (listen_dp) + if (data_path_validate(listen_dp, __FUNCTION__)) vine_event_loop_add_event(listen_dp->event_queue, accepted_event, __invoke_accepted_user_cb, __free_accepted_event, listen_dp); } @@ -247,14 +261,18 @@ static void __invoke_opened_user_cb(void *event, void *user_data) VINE_LOGD("user callback is invoked by event queue"); - if (dp && dp->opened_cb) + if (data_path_validate(dp, __FUNCTION__) && dp->opened_cb) dp->opened_cb(dp, opened_event->result, opened_event->port, dp->opened_cb_data); } static void __opened_cb(int result, int port, void *user_data) { + VINE_LOGD("__opened_cb result[%d] port[%d] datapath[%p]", result, port, user_data); RET_IF(user_data == NULL, "dp is NULL"); vine_data_path_s *dp = (vine_data_path_s *)user_data; + if (!data_path_validate(dp, __FUNCTION__)) + return; + vine_dp_opened_event *opened_event = (vine_dp_opened_event *)calloc(1, sizeof(vine_dp_opened_event)); opened_event->result = result; @@ -285,6 +303,8 @@ static void __accepted_cb(vine_dp_addr_family_e addr_family, char *addr, RET_IF(user_data == NULL, "listen_dp is NULL"); vine_data_path_s *listen_dp = (vine_data_path_s *)user_data; + if (!data_path_validate(listen_dp, __FUNCTION__)) + return; VINE_LOGI("listen_dp[%p], security[%p]", listen_dp, listen_dp->security); vine_data_path_s *connected_dp = _vine_data_path_create(listen_dp->method, @@ -310,7 +330,7 @@ static void __invoke_connected_user_cb(void *event, void *user_data) VINE_LOGD("user callback is invoked by event queue."); - if (dp && dp->connected_cb) + if (data_path_validate(dp, __FUNCTION__) && dp->connected_cb) dp->connected_cb(dp, connected_event->result, dp->connected_cb_data); } @@ -325,8 +345,9 @@ void notify_connected(vine_data_path_h datapath, int result) connected_event->result = result; vine_data_path_s *dp = (vine_data_path_s *)datapath; - vine_event_loop_add_event(dp->event_queue, connected_event, - __invoke_connected_user_cb, free, datapath); + if (data_path_validate(dp, __FUNCTION__)) + vine_event_loop_add_event(dp->event_queue, connected_event, + __invoke_connected_user_cb, free, datapath); } static void __connected_cb(int result, void *user_data) @@ -336,6 +357,9 @@ static void __connected_cb(int result, void *user_data) RET_IF(user_data == NULL, "dp is NULL"); vine_data_path_s *dp = (vine_data_path_s *)user_data; + if (!data_path_validate(dp, __FUNCTION__)) + return; + if (result < 0) { VINE_LOGE("Fail to connect"); notify_connected(dp, result); @@ -356,7 +380,7 @@ static void __invoke_received_user_cb(void *event, void *user_data) VINE_LOGD("user callback is invoked by event queue."); - if (dp && dp->recv_cb) { + if (data_path_validate(dp, __FUNCTION__) && dp->recv_cb) { // user can read the data in recv_cb(). dp->recv_cb(dp, received_event->bytes, dp->recv_cb_data); } @@ -373,9 +397,11 @@ void notify_data_received(vine_data_path_h datapath, size_t bytes) VINE_LOGD("Create a received_event[%p] datapath[%p]", received_event, datapath); vine_data_path_s *dp = (vine_data_path_s *)datapath; - if (dp) + if (data_path_validate(dp, __FUNCTION__)) vine_event_loop_add_event(dp->event_queue, received_event, - __invoke_received_user_cb, free, datapath); + __invoke_received_user_cb, free, datapath); + else + free(received_event); } static void __received_cb(size_t bytes, void *user_data) @@ -383,6 +409,9 @@ static void __received_cb(size_t bytes, void *user_data) RET_IF(user_data == NULL, "dp is NULL"); vine_data_path_s *dp = (vine_data_path_s *)user_data; + if (!data_path_validate(dp, __FUNCTION__)) + return; + dp->state->received_cb(bytes); } @@ -390,6 +419,9 @@ static void __written_cb(int bytes, void *user_data) { VINE_LOGD("%d bytes are written through datapath[%p].", bytes, user_data); vine_data_path_s *dp = (vine_data_path_s *)user_data; + if (!data_path_validate(dp, __FUNCTION__)) + return; + dp->state->written_cb(bytes); } @@ -401,6 +433,9 @@ static void __invoke_terminated_user_cb(void *event, void *user_data) VINE_LOGD("user callback is invoked by event queue."); + if (!data_path_validate(dp, __FUNCTION__)) + return; + start_default_state(dp, dp->plugin_handle, *dp->plugin_fn, dp->state); if (dp->terminated_cb) dp->terminated_cb(dp, dp->terminated_cb_data); @@ -409,7 +444,7 @@ static void __invoke_terminated_user_cb(void *event, void *user_data) static void __terminated_cb(void *user_data) { vine_data_path_s *dp = (vine_data_path_s *)user_data; - if (dp) + if (data_path_validate(dp, __FUNCTION__)) vine_event_loop_add_event(dp->event_queue, NULL, __invoke_terminated_user_cb, NULL, user_data); } @@ -489,9 +524,14 @@ int vine_data_path_close(vine_data_path_h datapath) RET_VAL_IF(!dp->plugin_fn || !dp->plugin_fn->close, VINE_ERROR_INVALID_PARAMETER, "plugin_fn is NULL"); + //start_default_state(dp, dp->plugin_handle, *dp->plugin_fn, dp->state); + // Unset callbacks related with vine_dp_open() before closing to avoid timing issue. dp->opened_cb = NULL; + dp->accepted_cb = NULL; dp->connected_cb = NULL; + dp->recv_cb = NULL; + dp->terminated_cb = NULL; dp->plugin_fn->close(dp->plugin_handle); return VINE_ERROR_NONE; @@ -553,7 +593,9 @@ static vine_data_path_s *_vine_data_path_create(vine_data_path_method_e method, } dp->state = vine_get_default_state(dp, dp->plugin_handle, *dp->plugin_fn); - VINE_LOGD("datapath[%p] is created. method[%d]", dp, method); + dp->validator = (((int)dp->plugin_handle) ^ VALIDATOR_BITS); + VINE_LOGD("datapath[%p] is created. method[%d] validator[%x] plugin_handle[%p]", + dp, method, dp->validator, dp->plugin_handle); return dp; } @@ -562,6 +604,8 @@ int vine_data_path_destroy(vine_data_path_h datapath) RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL"); vine_data_path_s *dp = (vine_data_path_s *)datapath; + start_default_state(dp, dp->plugin_handle, *dp->plugin_fn, dp->state); + if (dp->plugin_fn && dp->plugin_fn->destroy) dp->plugin_fn->destroy(dp->plugin_handle); @@ -578,6 +622,7 @@ int vine_data_path_destroy(vine_data_path_h datapath) dp->connected_cb = NULL; dp->recv_cb = NULL; dp->terminated_cb = NULL; + dp->validator = 0; VINE_LOGD("data_path[%p] is destroyed", datapath); free(datapath); @@ -620,6 +665,9 @@ static void __established(vine_data_path_h datapath, int result) RET_IF(datapath == NULL, "datapath is NULL"); vine_data_path_s *dp = (vine_data_path_s *)datapath; + if (!data_path_validate(dp, __FUNCTION__)) + return; + dp->established(dp, result); } -- 2.7.4