From: Cheoleun Moon Date: Fri, 23 Jul 2021 03:11:37 +0000 (+0900) Subject: nan plugin: add publish and subscribe X-Git-Tag: submit/tizen/20210831.025107~8^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b543f236889512e4b49dc5aaba598508f6ad4923;p=platform%2Fcore%2Fapi%2Fvine.git nan plugin: add publish and subscribe Change-Id: I891c5e17cd87909b6fabbffec45509610a20f69f Signed-off-by: Cheoleun Moon --- diff --git a/CMakeLists.txt b/CMakeLists.txt index a6834a7..c9dfd61 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,8 @@ OPTION(WITH_VINE_TEST "With vine command-line test tools" OFF) OPTION(ENABLE_INSTRUMENTATION_MODE "Enable instrumentation mode" OFF) OPTION(ENABLE_DATAPATH_PLUGIN_DEBUG "Enable debug mode for data path plugin" OFF) +OPTION(NAN_SUPPORT "Support NAN" OFF) + INCLUDE(FindPkgConfig) SET(BUILD_OS "default") @@ -90,6 +92,13 @@ IF(TIZEN_OS AND USE_EVENT_LOOP_EXTERNAL_GLIB) SET(BT_SUPPORT ON) ENDIF(TIZEN_OS AND USE_EVENT_LOOP_EXTERNAL_GLIB) +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) + ENDIF(NOT TIZEN_OS OR NOT USE_EVENT_LOOP_EXTERNAL_GLIB) +ENDIF(NAN_SUPPORT) + IF(ENABLE_INSTRUMENTATION_MODE) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finstrument-functions -finstrument-functions-exclude-file-list=src/logger") ADD_DEFINITIONS("-DENABLE_INSTRUMENTATION_MODE") @@ -129,6 +138,9 @@ IF(BT_SUPPORT) ADD_SUBDIRECTORY(plugins/ble) ADD_SUBDIRECTORY(plugins/ble-gatt) ENDIF(BT_SUPPORT) +IF(NAN_SUPPORT) + ADD_SUBDIRECTORY(plugins/nan) +ENDIF(NAN_SUPPORT) ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(src/logger) diff --git a/packaging/capi-network-vine.spec b/packaging/capi-network-vine.spec index ddff2eb..0f7b057 100755 --- a/packaging/capi-network-vine.spec +++ b/packaging/capi-network-vine.spec @@ -24,6 +24,7 @@ BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(capi-network-wifi-aware) BuildRequires: pkgconfig(capi-network-bluetooth) %endif @@ -103,6 +104,7 @@ export LDFLAGS+=" -lgcov" %else -DUSE_LIBWEBSOCKETS_STATIC=OFF \ %endif + -DNAN_SUPPORT=ON \ %if %{with lws_static_prebuilt} -DUSE_LIBWEBSOCKETS_STATIC_PREBUILT=ON \ %else diff --git a/plugins/nan/CMakeLists.txt b/plugins/nan/CMakeLists.txt new file mode 100755 index 0000000..9367cb5 --- /dev/null +++ b/plugins/nan/CMakeLists.txt @@ -0,0 +1,51 @@ +# 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 applicanan 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. +# + +SET(NAN_PLUGIN "vine-plugin-nan") + +SET(NAN_PLUGIN_VERSION_MAJOR "1") +SET(NAN_PLUGIN_VERSION_MINOR "0") +SET(NAN_PLUGIN_VERSION_PATCH "0") +SET(NAN_PLUGIN_VERSION ${NAN_PLUGIN_VERSION_MAJOR}.${NAN_PLUGIN_VERSION_MINOR}.${NAN_PLUGIN_VERSION_PATCH}) + +PKG_CHECK_MODULES(NAN_DEPS REQUIRED "capi-network-wifi-aware") + +INCLUDE_DIRECTORIES( + ${VINE_PATH}/include + ${VINE_LOGGER_PATH} + ${CMAKE_CURRENT_SOURCE_DIR} + ${${fw_name}_INCLUDE_DIRS} + ${NAN_DEPS_INCLUDE_DIRS} +) + +FILE(GLOB VINE_NAN_PLUGIN_SOURCES *.cpp) + +ADD_DEFINITIONS("-fvisibility=default") +ADD_LIBRARY(${NAN_PLUGIN} SHARED ${VINE_NAN_PLUGIN_SOURCES}) + +SET_TARGET_PROPERTIES( + ${NAN_PLUGIN} + PROPERTIES + SOVERSION ${NAN_PLUGIN_VERSION_MAJOR} +) + +TARGET_LINK_LIBRARIES(${NAN_PLUGIN} + ${VINE_LOGGER} + ${NAN_DEPS_LIBRARIES} + ${fw_name_deps_LIBRARIES} + dl +) + +INSTALL(TARGETS ${NAN_PLUGIN} DESTINATION "${LIB_DIR}") diff --git a/plugins/nan/nan-plugin.cpp b/plugins/nan/nan-plugin.cpp new file mode 100755 index 0000000..0739860 --- /dev/null +++ b/plugins/nan/nan-plugin.cpp @@ -0,0 +1,380 @@ +/* + * 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. + * +*/ + +#include + +#include +#include +#include +#include +#include + +#include "vine-constants.h" +#include "vine-disc-plugin.h" +#include "vine-log.h" +#include "vine-utils.h" +#include "nan-plugin.h" + +typedef struct { + void *disc_handle; // vine_disc handle + 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]; + char service_name[VINE_MAX_NAN_SERVICE_NAME_LEN + 1]; +} vine_nan_s; + +static bool __is_nan_enabled = false; +static vine_disc_plugin_callbacks event_callbacks; + +static vine_disc_error __convert_nan_error_to_vine_disc_error(int error) +{ + return VINE_DISC_ERROR_NONE; +} + + +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) +{ + 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"); + // 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_LOGD("Start to resolve IP. plugin_handle[%p]\n", 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; +} + +vine_disc_error nan_cancel_resolve_ip(void *plugin_handle) +{ + RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL"); + VINE_LOGD("Cancel resolving IP. plugin_handle[%p]\n", plugin_handle); + + return VINE_DISC_ERROR_NONE; +} + + +vine_disc_error nan_init(void **plugin_handle, void *disc_handle) +{ + vine_nan_s *handle = new vine_nan_s; + + handle->disc_handle = disc_handle; + handle->publish_config = nullptr; + handle->subscribe_config = nullptr; + handle->session = nullptr; + + // NAN will be enabled when publish() or subscribe() + // because enable function works asynchronously. + + return VINE_DISC_ERROR_NONE; +} + +void nan_deinit(void *plugin_handle) +{ + RET_IF(plugin_handle == NULL, "Plugin handle is null"); + vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle; + + // TODO + // Disable NAN here. + // However, we have to check if NAN is used for data path + + delete nan_handle; +} + +static void __published_cb(wifi_aware_session_h session, + wifi_aware_error_e error, void *user_data) +{ + VINE_LOGD("Service is published"); + vine_nan_s *nan_handle = (vine_nan_s *)user_data; + + 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->disc_handle); +} + +static void __publish(vine_nan_s *nan_handle) +{ + wifi_aware_session_h session; + 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_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); + } + + nan_handle->session = session; +} + +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_nan_s *nan_handle = (vine_nan_s *)user_data; + + VINE_LOGE("Fails to subscribe. error: %s", __convert_nan_error_to_vine_disc_error(error)); + 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); + } +} + +static void __subscribe(vine_nan_s *nan_handle) +{ + wifi_aware_session_h session; + int ret = wifi_aware_session_create(WIFI_AWARE_SESSION_SUBSCRIBE, &session); + RET_IF(ret != WIFI_AWARE_ERROR_NONE, "wifi_aware_session_create() fails"); + + 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); + } + + nan_handle->session = session; +} + +static void __start_session(vine_nan_s *nan_handle) +{ + if (nan_handle->publish_config) + __publish(nan_handle); + else if (nan_handle->subscribe_config) + __subscribe(nan_handle); + else + VINE_LOGE("Invalid operation"); +} + +static void __stop_session(vine_nan_s *nan_handle) +{ + if (nan_handle->session) { + wifi_aware_session_stop(nan_handle->session); + wifi_aware_session_destroy(nan_handle->session); + } +} + +static void __enabled_cb(wifi_aware_error_e error, void *user_data) +{ + RET_IF(!user_data, "nan_handle is NULL"); + __start_session((vine_nan_s *)user_data); +} + +static bool __check_attr_len(const map &attributes) +{ + int info_len = VINE_MAX_NAN_SERVICE_NAME_LEN; + for (const auto &kv : attributes) { + auto key = kv.first; + auto val = kv.second; + info_len += key.size() + val.size() + 1; + if (info_len > MAX_SPECIFIC_INFO_LEN) + return false; + } + return true; +} + +static void __fill_specific_info(unsigned char *info, const char *service_name, + const map &attributes) +{ + int service_name_len = strlen(service_name); + memcpy(info, service_name, service_name_len); + info[service_name_len] = 0; + + unsigned char *ptr = &info[VINE_MAX_NAN_SERVICE_NAME_LEN]; + for (const auto &kv : attributes) { + auto key = kv.first; + auto val = kv.second; + int key_len = key.size(); + int val_len = val.size(); + *ptr = (unsigned char)(key_len + val_len + 1); + ptr++; + memcpy(ptr, key.c_str(), key_len); + ptr += key_len; + *ptr++ = '='; + memcpy(ptr, val.c_str(), val_len); + ptr += val_len; + } +} + +vine_disc_error nan_publish(void *plugin_handle, const char *service_type, + const char *service_name, int port, const map &attributes, + const char *iface_name) +{ + 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(strlen(service_type) > NAN_MAX_SERVICE_NAME_LEN, VINE_DISC_ERROR_INVALID_PARAMETER, + "Too long service type"); + RET_VAL_IF(strlen(service_name) > VINE_MAX_NAN_SERVICE_NAME_LEN, VINE_DISC_ERROR_INVALID_PARAMETER, + "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); + + 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), + "wifi_aware_publish_create() fails"); + + unsigned char info[MAX_SPECIFIC_INFO_LEN + 1] = {0, }; + + ret = wifi_aware_publish_set_type(config, WIFI_AWARE_PUBLISH_TYPE_UNSOLICITED); + if (ret != WIFI_AWARE_ERROR_NONE) { + VINE_LOGE("wifi_aware_publish_set_type() fails"); + goto ERR; + } + + ret = wifi_aware_publish_set_service_name(config, service_type); + if (ret != WIFI_AWARE_ERROR_NONE) { + VINE_LOGE("wifi_aware_publish_set_service_name() fails"); + goto ERR; + } + + __fill_specific_info(info, service_name, attributes); + + nan_handle->publish_config = config; + + ret = wifi_aware_enable(__enabled_cb, nan_handle); + if (ret != WIFI_AWARE_ERROR_NONE) { + VINE_LOGE("wifi_aware_enable() fails"); + goto ERR; + } + + return VINE_DISC_ERROR_NONE; + +ERR: + wifi_aware_publish_destroy(config); + return __convert_nan_error_to_vine_disc_error(ret); +} + +vine_disc_error nan_stop_publish(void *plugin_handle) +{ + RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL"); + + vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle; + __stop_session(nan_handle); + + if (nan_handle->publish_config) + wifi_aware_publish_destroy(nan_handle->publish_config); + + return VINE_DISC_ERROR_NONE; +} + +vine_disc_error nan_subscribe(void *plugin_handle, + const char *service_type, const char *iface_name) +{ + 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(strlen(service_type) > NAN_MAX_SERVICE_NAME_LEN, VINE_DISC_ERROR_INVALID_PARAMETER, + "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); + + wifi_aware_subscribe_h config = nullptr; + int ret = wifi_aware_subscribe_create(&config); + RET_VAL_IF(ret != WIFI_AWARE_ERROR_NONE, __convert_nan_error_to_vine_disc_error(ret), + "wifi_aware_subscribe_create() fails"); + + ret = wifi_aware_subscribe_set_type(config, WIFI_AWARE_SUBSCRIBE_TYPE_ACTIVE); + if (ret != WIFI_AWARE_ERROR_NONE) { + VINE_LOGE("wifi_aware_subscribe_set_type() fails"); + goto ERR; + } + + ret = wifi_aware_subscribe_set_service_name(config, service_type); + if (ret != WIFI_AWARE_ERROR_NONE) { + VINE_LOGE("wifi_aware_subscribe_set_service_name() fails"); + goto ERR; + } + + nan_handle->subscribe_config = config; + + ret = wifi_aware_enable(__enabled_cb, nan_handle); + if (ret != WIFI_AWARE_ERROR_NONE) { + VINE_LOGE("wifi_aware_enable() fails"); + goto ERR; + } + + return VINE_DISC_ERROR_NONE; + +ERR: + wifi_aware_subscribe_destroy(config); + return __convert_nan_error_to_vine_disc_error(ret); +} + +vine_disc_error nan_stop_subscribe(void *plugin_handle) +{ + RET_VAL_IF(!plugin_handle, VINE_DISC_ERROR_INVALID_PARAMETER, "plugin_handle is NULL"); + + vine_nan_s *nan_handle = (vine_nan_s *)plugin_handle; + __stop_session(nan_handle); + + if (nan_handle->subscribe_config) + wifi_aware_subscribe_destroy(nan_handle->subscribe_config); + + return VINE_DISC_ERROR_NONE; +} + + +void nan_register_callbacks(vine_disc_plugin_callbacks callbacks) +{ + event_callbacks.published_cb = callbacks.published_cb; + event_callbacks.discovered_cb = callbacks.discovered_cb; + 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) +{ + VINE_LOGE("Not supported function"); + return VINE_DISC_ERROR_NOT_SUPPORTED; +} + +void vine_disc_plugin_init(vine_disc_plugin_fn *fn) +{ + fn->init = nan_init; + fn->deinit = nan_deinit; + fn->publish = nan_publish; + fn->stop_publish = nan_stop_publish; + fn->subscribe = nan_subscribe; + fn->stop_subscribe = nan_stop_subscribe; + fn->resolve_ip = nan_resolve_ip; + fn->cancel_resolve_ip = nan_cancel_resolve_ip; + fn->register_callbacks = nan_register_callbacks; + fn->process_event = nan_process_event; +} diff --git a/plugins/nan/nan-plugin.h b/plugins/nan/nan-plugin.h new file mode 100755 index 0000000..890b51e --- /dev/null +++ b/plugins/nan/nan-plugin.h @@ -0,0 +1,20 @@ +/* + * 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 NAN_MAX_SERVICE_NAME_LEN 255 +#define MAX_SPECIFIC_INFO_LEN 1024 diff --git a/src/include/vine-constants.h b/src/include/vine-constants.h index 206f28d..6ca58e1 100755 --- a/src/include/vine-constants.h +++ b/src/include/vine-constants.h @@ -36,4 +36,7 @@ #define VINE_MAX_BLE_SERVICE_NAME_LEN 15 #define VINE_MAC_LEN 17 +#define VINE_MAX_NAN_SERVICE_TYPE_LEN 63 +#define VINE_MAX_NAN_SERVICE_NAME_LEN 63 + #endif /* __VINE_SERV__VINE_CONSTANTS_H__ICE_H__ */