From e209aff79d69b7ff882cf16ac37042fea8389e5a Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Mon, 9 Aug 2021 14:02:27 +0900 Subject: [PATCH 01/16] Fix build failure Change-Id: I27d0199562a30959074e7a66e5a9a405a7f6d234 --- src/vine-dp.cpp | 2 +- tests/vine-test/CMakeLists.txt | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vine-dp.cpp b/src/vine-dp.cpp index 0d31a63..e66715f 100755 --- a/src/vine-dp.cpp +++ b/src/vine-dp.cpp @@ -1174,7 +1174,7 @@ int DPPubSub::publish_service() // The maximum length of topic is 1024. // The length of value is at most (VINE_MAX_ATTRIBUTE_LEN(252) - key length(2) - 1 = 249) // Therefore, at most five attributes can be added for a topic. - VINE_LOGD("Topic[%s] is added as attributes", mTopic); + VINE_LOGD("Topic[%s] is added as attributes", mTopic.c_str()); while (pos < mTopic.size()) { std::string val = mTopic.substr(pos, VINE_MAX_ATTRIBUTE_LEN - 1 - 2); char key[3]; diff --git a/tests/vine-test/CMakeLists.txt b/tests/vine-test/CMakeLists.txt index 9398103..da8cb8f 100755 --- a/tests/vine-test/CMakeLists.txt +++ b/tests/vine-test/CMakeLists.txt @@ -27,7 +27,11 @@ INCLUDE_DIRECTORIES( FILE(GLOB VINE_TEST_SRCS *.cpp) FILE(GLOB VINE_TEST_UTILS_SRC *utils*.cpp) +FILE(GLOB VINE_TEST_BLE_SRC vine-ble-test.cpp) LIST(REMOVE_ITEM VINE_TEST_SRCS ${VINE_TEST_UTILS_SRC}) +IF(NOT BT_SUPPORT) +LIST(REMOVE_ITEM VINE_TEST_SRCS ${VINE_TEST_BLE_SRC}) +ENDIF() foreach(file ${VINE_TEST_SRCS}) GET_FILENAME_COMPONENT(name ${file} NAME_WE) -- 2.7.4 From 5d4c53f16c3a5423064ae700f37a3c96c96b88f7 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Thu, 29 Jul 2021 18:49:48 +0900 Subject: [PATCH 02/16] Modify the initiation logic for GATT connection - Manage connection state callbacks globally - Add the new characteristic used in initiation phase - Do not call bt_gatt_disconnect() Change-Id: Id5fbacd2f8e19ab46c901795e3c82d30bf597f39 --- plugins/ble-gatt/ble-gatt-plugin.cpp | 456 +++++++++++++++++++++++++++-------- 1 file changed, 356 insertions(+), 100 deletions(-) diff --git a/plugins/ble-gatt/ble-gatt-plugin.cpp b/plugins/ble-gatt/ble-gatt-plugin.cpp index af7dbc5..b3a0d5b 100755 --- a/plugins/ble-gatt/ble-gatt-plugin.cpp +++ b/plugins/ble-gatt/ble-gatt-plugin.cpp @@ -29,9 +29,15 @@ using namespace std; // TODO: change UUIDs #define VINE_GATT_SERVICE_UUID "000018f2-0000-1000-8000-00805f9b34fb" -#define VINE_GATT_CHAR_UUID "00002af6-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" +// 2-way handshake for VINE GATT connection +#define VINE_GATT_CONNECTION_SYN "VINE_GATT_CONNECTION_SYN" +#define VINE_GATT_CONNECTION_ACK "VINE_GATT_CONNECTION_ACK" +#define VINE_GATT_CONNECTION_FIN "VINE_GATT_CONNECTION_FIN" + #define BT_ADDRESS_LEN 17 #define BT_GATT_ATT_DATA_LEN_MAX 512 @@ -65,8 +71,10 @@ struct vine_gatt_s { int eventfd; bt_gatt_h service; - bt_gatt_h characteristic; - bt_gatt_h descriptor; + bt_gatt_h connection_char; + bt_gatt_h connection_desc; + bt_gatt_h read_write_char; + bt_gatt_h read_write_desc; vine_gatt_role_e type; union { @@ -93,9 +101,25 @@ static vine_dp_plugin_callbacks g_callbacks = { static map g_eventfds; +// Wrapper for bt_gatt_connection_state_changed_cb() +typedef void (*gatt_connection_state_cb)(vine_gatt_s *gatt, + bool connected, const char *remote_address, void *user_data); +typedef struct { + vine_gatt_s *gatt; + gatt_connection_state_cb func; + void *user_data; +} conn_state_cb_data; +static multimap g_conn_state_cbs; + static vine_gatt_s *_create_gatt(void); static int __write_to_client(vine_gatt_s *gatt); static int __write_to_server(vine_gatt_s *gatt); +static int __update_gatt_service_info(const char *remote_address, vine_gatt_s *gatt); +static void __handle_connected_client(vine_gatt_s *gatt, const char *address); +static void __handle_disconnected_client(vine_gatt_s *gatt, const char *address); +static void __send_conn_syn(vine_gatt_s *gatt, const char *remote_address); +static void __send_conn_ack(vine_gatt_s *gatt, const char *remote_address); +static void __send_conn_fin(vine_gatt_s *gatt, const char *remote_address); static vine_data_path_error __convert_bt_error_to_data_path_error(int error) { @@ -218,14 +242,53 @@ static void __invoke_terminated_cb(void *user_data) } // Server Callbacks +static void __gatt_server_read_connection_value_requested_cb( + const char *remote_address, int request_id, + bt_gatt_server_h server, bt_gatt_h gatt_handle, + int offset, void *user_data) +{ + // Do nothing. +} + +static void __gatt_server_write_connection_value_requested_cb(const char *remote_address, + int request_id, bt_gatt_server_h server, + bt_gatt_h gatt_handle, bool response_needed, int offset, + const char *value, int len, void *user_data) +{ + RET_IF(user_data == NULL, "user_data is NULL"); + VINE_LOGI("Got write init value[%s] request from %s.", value, remote_address); + + vine_gatt_s *gatt = (vine_gatt_s *)user_data; + + if (bt_gatt_server_send_response(request_id, BT_GATT_REQUEST_TYPE_WRITE, + offset, BT_ERROR_NONE, "", 0) != BT_ERROR_NONE) { + VINE_LOGE("Failed to send initiation message"); + return; + } + + if (strncmp(value, VINE_GATT_CONNECTION_SYN, len) == 0) { + VINE_LOGI("Got SYN mesage from %s", remote_address); + __send_conn_ack(gatt, remote_address); + __handle_connected_client(gatt, remote_address); + } else if (strncmp(value, VINE_GATT_CONNECTION_FIN, strlen(VINE_GATT_CONNECTION_FIN) == 0)) { + VINE_LOGI("Got FIN message from %s", remote_address); + __handle_disconnected_client(gatt, remote_address); + } +} + +void __gatt_server_noti_connection_state_changed_cb(bool notify, bt_gatt_server_h server, + bt_gatt_h gatt_handle, void *user_data) +{ + // Do nothing. + VINE_LOGI("+"); +} + static void __gatt_server_read_value_requested_cb( const char *remote_address, int request_id, bt_gatt_server_h server, bt_gatt_h gatt_handle, int offset, void *user_data) { - // TODO: Send response. - // TODO: Save data - // Is this function needed for VINE? + // Do nothing. } static void __gatt_server_write_value_requested_cb(const char *remote_address, @@ -318,6 +381,148 @@ void __gatt_server_noti_sent_cb(int result, } // Client Callbacks +void __gatt_client_read_write_char_changed_cb(bt_gatt_h characteristic, + char *value, int len, void *user_data) +{ + VINE_LOGD("+"); + RET_IF(user_data == NULL, "user_data is NULL"); + + vine_gatt_s *gatt = (vine_gatt_s *)user_data; + gatt_data_s *recv_data =__create_gatt_data(gatt, value, len, true); + RET_IF(recv_data == NULL, "recv_data is NULL"); + + gatt->recv_buffer->push(recv_data); + + VINE_LOGD("recv_data[%p] is pushed to recv_buffer. length[%zd]", recv_data, len); + if (g_callbacks.received_cb) + g_callbacks.received_cb(len, gatt->user); +} + +void __gatt_client_connection_char_changed_cb(bt_gatt_h characteristic, + char *value, int len, void *user_data) +{ + RET_IF(user_data == NULL, "user_data is NULL"); + + vine_gatt_s *gatt = (vine_gatt_s *)user_data; + if (strncmp(value, VINE_GATT_CONNECTION_ACK, strlen(VINE_GATT_CONNECTION_ACK)) == 0) { + VINE_LOGI("Got ACK message."); + if (bt_gatt_client_set_characteristic_value_changed_cb(gatt->read_write_char, + __gatt_client_read_write_char_changed_cb, gatt) != BT_ERROR_NONE) { + VINE_LOGE("Failed to set characteristic_value_changed_cb"); + // TODO: disconnect. + return; + } + gatt->ready_to_write = true; + __invoke_connected_cb(0, gatt->user); + } else if (strncmp(value, VINE_GATT_CONNECTION_FIN, strlen(VINE_GATT_CONNECTION_FIN) == 0)) { + VINE_LOGI("Got FIN message."); + __invoke_terminated_cb(gatt->user); + } else { + VINE_LOGI("Unknown message. [%s]", value); + } +} + +void __send_conn_syn_completed_cb(int result, bt_gatt_h gatt_handle, void *user_data) +{ + // Do nothing. +} + +static void __send_conn_syn(vine_gatt_s *gatt, const char *remote_address) +{ + // Only the client can send a SYN. + RET_IF(gatt->type != VINE_GATT_ROLE_CLIENT, "gatt isn't a client"); + RET_IF(remote_address == NULL, "remote_address is NULL"); + + bt_gatt_set_value(gatt->connection_char, + VINE_GATT_CONNECTION_SYN, strlen(VINE_GATT_CONNECTION_SYN)); + bt_gatt_client_write_value(gatt->connection_char, + __send_conn_syn_completed_cb, (void *)gatt); +} + +static void __send_conn_ack_completed_cb(int result, + const char *remote_address, bt_gatt_server_h server, bt_gatt_h characteristic, + bool completed, void *user_data) +{ + VINE_LOGD("+"); +} + +static void __send_conn_ack(vine_gatt_s *gatt, const char *remote_address) +{ + VINE_LOGI("+"); + // Only the server can send a ACK. + RET_IF(gatt->type != VINE_GATT_ROLE_SERVER, "gatt isn't a server"); + RET_IF(remote_address == NULL, "remote_address is NULL"); + + bt_gatt_set_value(gatt->connection_char, + VINE_GATT_CONNECTION_ACK, strlen(VINE_GATT_CONNECTION_ACK)); + bt_gatt_server_notify_characteristic_changed_value(gatt->connection_char, + __send_conn_ack_completed_cb, gatt->remote_address, (void *)gatt); +} + +void __send_conn_fin_to_server_completed_cb(int result, bt_gatt_h gatt_handle, void *user_data) +{ + VINE_LOGD("+"); +} + +static void __send_conn_fin_to_client_completed_cb(int result, + const char *remote_address, bt_gatt_server_h server, bt_gatt_h characteristic, + bool completed, void *user_data) +{ + VINE_LOGD("+"); +} + +static void __send_conn_fin(vine_gatt_s *gatt, const char *remote_address) +{ + VINE_LOGI("+"); + RET_IF(gatt->type == VINE_GATT_ROLE_UNKNOWN, "Unknown type"); + RET_IF(remote_address == NULL, "remote_address is NULL"); + + bt_gatt_set_value(gatt->connection_char, + VINE_GATT_CONNECTION_FIN, strlen(VINE_GATT_CONNECTION_FIN)); + + 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) { + bt_gatt_client_write_value(gatt->connection_char, + __send_conn_fin_to_server_completed_cb, (void *)gatt); + } +} + +static void __gatt_client_state_changed_cb(vine_gatt_s *gatt, + bool connected, const char *remote_address, void *user_data) +{ + RET_IF(gatt == NULL, "gatt is NULL"); + VINE_LOGI("gatt[%p] connected[%d] remote address[%s]", gatt, connected, remote_address); + + if (!connected) { + // TODO: unregister here? + __invoke_terminated_cb(gatt->user); + return; + } + + if (__update_gatt_service_info(remote_address, gatt) != VINE_DATA_PATH_ERROR_NONE) { + __send_conn_fin(gatt, remote_address); + return; + } + + __send_conn_syn(gatt, remote_address); +} + +static void __gatt_accepted_client_state_changed_cb(vine_gatt_s *gatt, + bool connected, const char *remote_address, void *user_data) +{ + RET_IF(gatt == NULL, "gatt is NULL"); + VINE_LOGI("gatt[%p] connected[%d] remote address[%s]", gatt, connected, remote_address); + + if (connected) { // Do nothing. + VINE_LOGI("[%p] is already connected.", user_data); + return; + } + + __handle_disconnected_client(gatt, remote_address); +} + static void __gatt_client_mtu_changed_cb(bt_gatt_client_h client, const bt_gatt_client_att_mtu_info_s *mtu_info, void *user_data) { @@ -358,23 +563,6 @@ void __gatt_client_write_complete_cb(int result, bt_gatt_h gatt_handle, void *us __notify_write_event(gatt); } -void __gatt_client_characteristic_value_changed_cb(bt_gatt_h characteristic, - char *value, int len, void *user_data) -{ - VINE_LOGD("+"); - RET_IF(user_data == NULL, "user_data is NULL"); - - vine_gatt_s *gatt = (vine_gatt_s *)user_data; - gatt_data_s *recv_data =__create_gatt_data(gatt, value, len, true); - RET_IF(recv_data == NULL, "recv_data is NULL"); - - gatt->recv_buffer->push(recv_data); - - VINE_LOGD("recv_data[%p] is pushed to recv_buffer. length[%zd]", recv_data, len); - if (g_callbacks.received_cb) - g_callbacks.received_cb(len, gatt->user); -} - static int __update_gatt_service_info(const char *remote_address, vine_gatt_s *gatt) { RET_VAL_IF(gatt == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "gatt is NULL"); @@ -383,6 +571,7 @@ static int __update_gatt_service_info(const char *remote_address, vine_gatt_s *g bt_gatt_client_h client = NULL; bt_gatt_h service = NULL; + bt_gatt_h connection_char = NULL; bt_gatt_h characteristic = NULL; int ret = BT_ERROR_OPERATION_FAILED; @@ -406,12 +595,20 @@ static int __update_gatt_service_info(const char *remote_address, vine_gatt_s *g if (ret != BT_ERROR_NONE) goto ERR; - ret = bt_gatt_service_get_characteristic(service, VINE_GATT_CHAR_UUID, &characteristic); + ret = bt_gatt_service_get_characteristic(service, + VINE_GATT_CONNECTION_CHAR_UUID, &connection_char); if (ret != BT_ERROR_NONE) goto ERR; - ret = bt_gatt_client_set_characteristic_value_changed_cb(characteristic, - __gatt_client_characteristic_value_changed_cb, gatt); + ret = bt_gatt_client_set_characteristic_value_changed_cb(connection_char, + __gatt_client_connection_char_changed_cb, gatt); + if (ret != BT_ERROR_NONE) { + VINE_LOGE("Failed to set characteristic_value_changed_cb"); + goto ERR; + } + + ret = bt_gatt_service_get_characteristic(service, + VINE_GATT_READ_WRITE_CHAR_UUID, &characteristic); if (ret != BT_ERROR_NONE) goto ERR; @@ -420,7 +617,8 @@ static int __update_gatt_service_info(const char *remote_address, vine_gatt_s *g goto ERR; gatt->service = service; - gatt->characteristic = characteristic; + gatt->connection_char = connection_char; + gatt->read_write_char = characteristic; gatt->remote_address = STRDUP(remote_address); VINE_LOGI("Succeeded to update GATT service info."); @@ -448,13 +646,65 @@ static vine_gatt_s *__create_accepted_gatt(const char *remote_address, vine_gatt accepted_gatt->remote_address = STRDUP(remote_address); // refer to server's gatt handles. accepted_gatt->service = gatt->service; - accepted_gatt->characteristic = gatt->characteristic; - accepted_gatt->descriptor = gatt->descriptor; + accepted_gatt->connection_char = gatt->connection_char; + accepted_gatt->connection_desc = gatt->connection_desc; + accepted_gatt->read_write_char = gatt->read_write_char; + accepted_gatt->read_write_desc = gatt->read_write_desc; accepted_gatt->user = user; return accepted_gatt; } +static void __gatt_connection_state_changed_cb(int result, bool connected, + const char *remote_address, void *user_data) +{ + VINE_LOGI("result[%d] connected[%d] remote address[%s]", result, connected, remote_address); + + typedef multimap::iterator iterator; + pair iter_pair = g_conn_state_cbs.equal_range(remote_address); + + for (iterator it = iter_pair.first; it != iter_pair.second; ++it) { + conn_state_cb_data *cb_data = it->second; + if (cb_data && cb_data->func) + cb_data->func(cb_data->gatt, connected, remote_address, cb_data->user_data); + } +} + +static int _register_conn_state_changed_cb(vine_gatt_s *gatt, + const char *addr, gatt_connection_state_cb func, void *user_data) +{ + conn_state_cb_data *cb_data = (conn_state_cb_data *)calloc(1, sizeof(conn_state_cb_data)); + RET_VAL_IF(cb_data == NULL, VINE_DATA_PATH_ERROR_OUT_OF_MEMORY, "cb_data is NULL"); + + cb_data->gatt = gatt; + cb_data->func = func; + cb_data->user_data = user_data; + g_conn_state_cbs.insert(pair(addr, cb_data)); + VINE_LOGD("cb_data[%p] is registered.", cb_data); + + return VINE_DATA_PATH_ERROR_NONE; +} + +static int _unregister_conn_state_changed_cb(vine_gatt_s *gatt, const char *addr, void *user_data) +{ + typedef multimap::iterator iterator; + pair iter_pair = g_conn_state_cbs.equal_range(addr); + + for (iterator it = iter_pair.first; it != iter_pair.second; ++it) { + conn_state_cb_data *cb_data = it->second; + if (cb_data && cb_data->gatt == gatt && cb_data->user_data == user_data) { + VINE_LOGD("cb_data[%p] is unregistered.", cb_data); + g_conn_state_cbs.erase(it); + cb_data->gatt = NULL; + cb_data->func = NULL; + cb_data->user_data = NULL; + free(cb_data); + break; + } + } + return VINE_DATA_PATH_ERROR_NONE; +} + static void __handle_connected_client(vine_gatt_s *gatt, const char *address) { RET_IF(gatt == NULL, "Invalid parameter."); @@ -465,6 +715,9 @@ static void __handle_connected_client(vine_gatt_s *gatt, const char *address) RET_IF(accepted_gatt == NULL, "Failed to create accepted gatt."); gatt->role.server->client_list->insert(std::make_pair(string(address), accepted_gatt)); + _register_conn_state_changed_cb(gatt, address, + __gatt_accepted_client_state_changed_cb, (void *)accepted_gatt); + VINE_LOGI("%s is connected.", address); __invoke_accepted_cb(accepted_gatt, accepted_gatt->user); } @@ -476,44 +729,16 @@ static void __handle_disconnected_client(vine_gatt_s *gatt, const char *address) RET_IF(gatt->role.server == NULL || gatt->role.server->client_list == NULL, "Invalid parameter."); + // TODO: Get client gatt from parameter. vine_gatt_s *client_gatt = __find_client_gatt(gatt, address); RET_IF(client_gatt == NULL, "Cannot find a client[%s].", address); gatt->role.server->client_list->erase(address); + _unregister_conn_state_changed_cb(gatt, address, (void *)client_gatt); __invoke_terminated_cb(client_gatt->user); VINE_LOGI("%s is disconnected.", address); } -static void __gatt_connection_state_changed_cb(int result, bool connected, - const char *remote_address, void *user_data) -{ - RET_IF(user_data == NULL, "user_data is NULL"); - - vine_gatt_s *gatt = (vine_gatt_s *)user_data; - - VINE_LOGI("gatt[%p] result[%d] connected[%d] remote address[%s] role[%d]", - gatt, result, connected, remote_address, gatt->type); - - if (!connected) { - if (gatt->type == VINE_GATT_ROLE_SERVER) - __handle_disconnected_client(gatt, remote_address); - else - __invoke_terminated_cb(gatt->user); - return; - } - - if (gatt->type == VINE_GATT_ROLE_SERVER && gatt->role.server) { - __handle_connected_client(gatt, remote_address); - } else if (gatt->type == VINE_GATT_ROLE_CLIENT) { - if (__update_gatt_service_info(remote_address, gatt) != VINE_DATA_PATH_ERROR_NONE) { - bt_gatt_disconnect(remote_address); - result = -1; - } - gatt->ready_to_write = true; - __invoke_connected_cb(result, gatt->user); - } -} - static vine_gatt_s *_create_gatt(void) { vine_gatt_s *gatt = (vine_gatt_s *)calloc(1, sizeof(vine_gatt_s)); @@ -526,13 +751,6 @@ static vine_gatt_s *_create_gatt(void) return NULL; } - if (bt_gatt_set_connection_state_changed_cb(__gatt_connection_state_changed_cb, - (void *)gatt) != BT_ERROR_NONE) { - VINE_LOGE("Failed to register GATT connection state changed callback"); - free(gatt); - return NULL; - } - gatt->eventfd = fd; g_eventfds[gatt->eventfd] = gatt; gatt->recv_buffer = new VineQueue; @@ -540,30 +758,33 @@ static vine_gatt_s *_create_gatt(void) return gatt; } -static bt_gatt_h _add_gatt_characteristic(bt_gatt_h service, vine_dp_plugin_h handle) +static bt_gatt_h _add_gatt_characteristic(bt_gatt_h service, + const char *uuid, + bt_gatt_server_read_value_requested_cb read_requested_cb, + bt_gatt_server_write_value_requested_cb write_requested_cb, + bt_gatt_server_characteristic_notification_state_changed_cb noti_changed_cb, + vine_dp_plugin_h handle) { bt_gatt_h characteristic = NULL; char initial_value[1] = {'0'}; // TODO: will be changed. int permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE; int properties = BT_GATT_PROPERTY_BROADCAST | BT_GATT_PROPERTY_READ | - BT_GATT_PROPERTY_WRITE - | BT_GATT_PROPERTY_INDICATE; + BT_GATT_PROPERTY_WRITE | BT_GATT_PROPERTY_INDICATE; - if (bt_gatt_characteristic_create(VINE_GATT_CHAR_UUID, - permissions, properties, + if (bt_gatt_characteristic_create(uuid, permissions, properties, initial_value, sizeof(initial_value), &characteristic) != BT_ERROR_NONE) return NULL; if (bt_gatt_server_set_read_value_requested_cb(characteristic, - __gatt_server_read_value_requested_cb, handle) != BT_ERROR_NONE) + read_requested_cb, handle) != BT_ERROR_NONE) goto ERR; if (bt_gatt_server_set_write_value_requested_cb(characteristic, - __gatt_server_write_value_requested_cb, handle) != BT_ERROR_NONE) + write_requested_cb, handle) != BT_ERROR_NONE) goto ERR; if (bt_gatt_server_set_characteristic_notification_state_change_cb(characteristic, - __gatt_server_noti_state_changed_cb, handle) != BT_ERROR_NONE) + noti_changed_cb, handle) != BT_ERROR_NONE) goto ERR; if (bt_gatt_service_add_characteristic(service, characteristic) != BT_ERROR_NONE) @@ -620,11 +841,11 @@ static int __write_to_server(vine_gatt_s *gatt) gatt_data_s *data = __get_pending_write_data(gatt); RET_VAL_IF(data == NULL, VINE_DATA_PATH_ERROR_NO_DATA, "There is no pending data."); - int ret = bt_gatt_set_value(gatt->characteristic, (const char *)data->buf, data->len); + int ret = bt_gatt_set_value(gatt->read_write_char, (const char *)data->buf, data->len); RET_VAL_IF(ret != BT_ERROR_NONE, __convert_bt_error_to_data_path_error(ret), "bt_gatt_set_value() failed."); - ret = bt_gatt_client_write_value(gatt->characteristic, + ret = bt_gatt_client_write_value(gatt->read_write_char, __gatt_client_write_complete_cb, (void *)data); RET_VAL_IF(ret != BT_ERROR_NONE, __convert_bt_error_to_data_path_error(ret), "bt_gatt_client_write_value() failed."); @@ -668,11 +889,11 @@ static int __write_to_client(vine_gatt_s *gatt) gatt_data_s *data = __get_pending_write_data(gatt); RET_VAL_IF(data == NULL, VINE_DATA_PATH_ERROR_NO_DATA, "There is no pending data."); - int ret = bt_gatt_set_value(gatt->characteristic, (const char *)data->buf, data->len); + int ret = bt_gatt_set_value(gatt->read_write_char, (const char *)data->buf, data->len); RET_VAL_IF(ret != BT_ERROR_NONE, __convert_bt_error_to_data_path_error(ret), "bt_gatt_set_value() failed."); - ret = bt_gatt_server_notify_characteristic_changed_value(gatt->characteristic, + ret = bt_gatt_server_notify_characteristic_changed_value(gatt->read_write_char, __gatt_server_noti_sent_cb, gatt->remote_address, (void *)data); RET_VAL_IF(ret != BT_ERROR_NONE, __convert_bt_error_to_data_path_error(ret), "bt_gatt_server_notify_characteristic_changed_value() failed."); @@ -721,7 +942,7 @@ void gatt_process_event(int fd, int events) return; } - // TODO: handle pending write events. + // Handle pending write events. vine_gatt_s *gatt = it->second; VINE_LOGI("found gatt[%p]", gatt); @@ -738,6 +959,13 @@ int gatt_create(vine_dp_plugin_h *handle, void *plugin_data, void *user) RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL"); RET_VAL_IF(user == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "user is NULL"); + // TODO: need to find proper point to register callback. + int ret = bt_gatt_set_connection_state_changed_cb(__gatt_connection_state_changed_cb, NULL); + if (ret != BT_ERROR_NONE) { + VINE_LOGE("Failed to register GATT connection state changed callback"); + return __convert_bt_error_to_data_path_error(ret); + } + vine_gatt_s *gatt = plugin_data ? (vine_gatt_s *)plugin_data :_create_gatt(); RET_VAL_IF(gatt == NULL, VINE_DATA_PATH_ERROR_OPERATION_FAILED, "Failed to create GATT handle"); @@ -757,8 +985,10 @@ int gatt_destroy(vine_dp_plugin_h handle) _destroy_gatt_server(gatt->role.server); gatt->role.server = NULL; bt_gatt_service_destroy(gatt->service); - bt_gatt_characteristic_destroy(gatt->characteristic); - bt_gatt_descriptor_destroy(gatt->descriptor); + bt_gatt_characteristic_destroy(gatt->connection_char); + bt_gatt_descriptor_destroy(gatt->connection_desc); + bt_gatt_characteristic_destroy(gatt->read_write_char); + bt_gatt_descriptor_destroy(gatt->read_write_desc); } else if (gatt->type == VINE_GATT_ROLE_CLIENT) { // bt_gatt_h handles will be freed during bt_gatt_client_destroy(). _destroy_gatt_client(gatt->role.client); @@ -767,8 +997,10 @@ int gatt_destroy(vine_dp_plugin_h handle) close(gatt->eventfd); gatt->service = NULL; - gatt->characteristic = NULL; - gatt->descriptor = NULL; + gatt->connection_char = NULL; + gatt->connection_desc = NULL; + gatt->read_write_char = NULL; + gatt->read_write_desc = NULL; free(gatt->remote_address); gatt->remote_address = NULL; free(gatt); @@ -785,8 +1017,10 @@ int gatt_open(vine_dp_plugin_h handle, int addr_family, vine_gatt_s *gatt = (vine_gatt_s *)handle; bt_gatt_server_h server = NULL; bt_gatt_h service = NULL; - bt_gatt_h characteristic = NULL; - bt_gatt_h descriptor = NULL; + bt_gatt_h connection_char = NULL; + bt_gatt_h connection_desc = NULL; + bt_gatt_h read_write_char = NULL; + bt_gatt_h read_write_desc = NULL; int ret = BT_ERROR_OPERATION_FAILED; // This returns OPERATION_FAILED when already initialized. ignore it. @@ -799,30 +1033,44 @@ int gatt_open(vine_dp_plugin_h handle, int addr_family, } ret = bt_gatt_service_create(VINE_GATT_SERVICE_UUID, BT_GATT_SERVICE_TYPE_PRIMARY, &service); - if (ret != BT_ERROR_NONE) { + if (ret != BT_ERROR_NONE) { VINE_LOGE("Failed to create service."); goto ERR; } - characteristic = _add_gatt_characteristic(service, handle); - if (!characteristic) { + connection_char = _add_gatt_characteristic(service, VINE_GATT_CONNECTION_CHAR_UUID, + __gatt_server_read_connection_value_requested_cb, + __gatt_server_write_connection_value_requested_cb, + __gatt_server_noti_connection_state_changed_cb, handle); + + connection_desc = _add_gatt_descriptor(connection_char); + if (!connection_desc) { + VINE_LOGE("Failed to add descriptor."); + goto ERR; + } + + read_write_char = _add_gatt_characteristic(service, VINE_GATT_READ_WRITE_CHAR_UUID, + __gatt_server_read_value_requested_cb, + __gatt_server_write_value_requested_cb, + __gatt_server_noti_state_changed_cb, handle); + if (!read_write_char) { VINE_LOGE("Failed to add characteristc."); goto ERR; } - descriptor = _add_gatt_descriptor(characteristic); - if (!descriptor) { + read_write_desc = _add_gatt_descriptor(read_write_char); + if (!read_write_desc) { VINE_LOGE("Failed to add descriptor."); goto ERR; } - ret = bt_gatt_server_register_service(server, service); + ret = bt_gatt_server_register_service(server, service); if (ret != BT_ERROR_NONE) { VINE_LOGE("Failed to register service."); goto ERR; } - ret = bt_gatt_server_start(); + ret = bt_gatt_server_start(); if (ret != BT_ERROR_NONE) { VINE_LOGE("Failed to start GATT server."); goto ERR; @@ -834,8 +1082,10 @@ int gatt_open(vine_dp_plugin_h handle, int addr_family, goto ERR; gatt->service = service; - gatt->characteristic = characteristic; - gatt->descriptor = descriptor; + gatt->connection_char = connection_char; + gatt->connection_desc = connection_desc; + gatt->read_write_char = read_write_char; + gatt->read_write_desc = read_write_desc; VINE_LOGI("Succeeded to start GATT server."); @@ -848,16 +1098,20 @@ ERR: bt_gatt_server_destroy(server); if (service) bt_gatt_service_destroy(service); - if (characteristic) - bt_gatt_characteristic_destroy(characteristic); - if (descriptor) - bt_gatt_descriptor_destroy(descriptor); + if (connection_char) + bt_gatt_characteristic_destroy(connection_char); + if (connection_desc) + bt_gatt_descriptor_destroy(connection_desc); + if (read_write_char) + bt_gatt_characteristic_destroy(read_write_char); + if (read_write_desc) + bt_gatt_descriptor_destroy(read_write_desc); return ret; } // All parameters except handle and addr are not used in BT GATT. int gatt_connect(vine_dp_plugin_h handle, int addr_family, - const char *addr, int gatt_port, const char *iface_name, vine_dp_ssl ssl) + const char *addr, int port, const char *iface_name, vine_dp_ssl ssl) { RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL"); RET_VAL_IF(addr == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "addr is NULL"); @@ -865,11 +1119,13 @@ int gatt_connect(vine_dp_plugin_h handle, int addr_family, vine_gatt_s *gatt = (vine_gatt_s *)handle; int ret; + _register_conn_state_changed_cb(gatt, addr, __gatt_client_state_changed_cb, NULL); gatt->type = VINE_GATT_ROLE_CLIENT; ret = bt_gatt_connect(addr, false); if (ret != BT_ERROR_NONE) { VINE_LOGE("Failed to connect remote LE based service."); gatt->type = VINE_GATT_ROLE_UNKNOWN; + _unregister_conn_state_changed_cb(gatt, addr, NULL); return __convert_bt_error_to_data_path_error(ret); } @@ -968,7 +1224,7 @@ int gatt_close(vine_dp_plugin_h handle) ret = bt_gatt_server_unregister_service(gatt->role.server->server, gatt->service); } else if (gatt->type == VINE_GATT_ROLE_CLIENT) { VINE_LOGI("Disconnect from %s", gatt->remote_address); - ret = bt_gatt_disconnect(gatt->remote_address); + // TODO: Send disconnect message. } return __convert_bt_error_to_data_path_error(ret); } -- 2.7.4 From 42fc50baeef6bf1cf6b4ed083440f7dc6bf0e47f Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Tue, 10 Aug 2021 14:00:30 +0900 Subject: [PATCH 03/16] Use long type for timeout_ms Change-Id: I019f58896cd02ba27dc317e79535f4f5f068ee5b Signed-off-by: Cheoleun Moon --- src/include/vine-timer.h | 2 +- src/vine-timer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/vine-timer.h b/src/include/vine-timer.h index ec4cac0..676324c 100644 --- a/src/include/vine-timer.h +++ b/src/include/vine-timer.h @@ -28,7 +28,7 @@ public: VineTimer(); ~VineTimer(); - void start(unsigned int timeout_ms, + void start(long timeout_ms, std::function callback, void *user_data); void stop(); void expired(); diff --git a/src/vine-timer.cpp b/src/vine-timer.cpp index 4877fd7..588de4d 100644 --- a/src/vine-timer.cpp +++ b/src/vine-timer.cpp @@ -38,7 +38,7 @@ VineTimer::~VineTimer() stop(); } -void VineTimer::start(unsigned int timeout_ms, +void VineTimer::start(long timeout_ms, std::function callback, void *user_data) { __timer_fd = timerfd_create(CLOCK_MONOTONIC, 0); -- 2.7.4 From e77aa104219957704808f2435a637de2216d34d4 Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Tue, 24 Aug 2021 13:29:27 +0900 Subject: [PATCH 04/16] Use gmock instead of gtest Change-Id: I7814d172cc944f32abed117c179be76ef58763af Signed-off-by: Cheoleun Moon --- packaging/capi-network-vine.spec | 4 ++-- tests/unittest/CMakeLists.txt | 44 ++++++++++++++++++++++++---------------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/packaging/capi-network-vine.spec b/packaging/capi-network-vine.spec index abef79b..7a1051a 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.6 +Version: 1.1.7 Release: 0 Group: Network & Connectivity/API License: Apache-2.0 @@ -31,7 +31,7 @@ BuildRequires: pkgconfig(capi-network-bluetooth) BuildRequires: pkgconfig(glib-2.0) %endif -BuildRequires: pkgconfig(gtest) +BuildRequires: pkgconfig(gmock) %if 0%{?gcov:1} BuildRequires: lcov diff --git a/tests/unittest/CMakeLists.txt b/tests/unittest/CMakeLists.txt index 0ed0eb5..06cbd4a 100755 --- a/tests/unittest/CMakeLists.txt +++ b/tests/unittest/CMakeLists.txt @@ -27,25 +27,35 @@ INCLUDE_DIRECTORIES( ${fw_name_deps_INCLUDE_DIRS} ) -IF(ANDROID) - SET(GOOGLETEST_ROOT ${ANDROID_NDK}/sources/third_party/googletest/) - ADD_LIBRARY(gtest STATIC ${GOOGLETEST_ROOT}/src/gtest_main.cc ${GOOGLETEST_ROOT}/src/gtest-all.cc) - TARGET_INCLUDE_DIRECTORIES(gtest PRIVATE ${GOOGLETEST_ROOT}) - TARGET_INCLUDE_DIRECTORIES(gtest PUBLIC ${GOOGLETEST_ROOT}/include) - SET(GTEST gtest) -ELSE(ANDROID) - SET(GTEST gtest) -ENDIF(ANDROID) - FILE(GLOB UNITTEST_SRCS *.cpp mocks/*.cpp ${CMAKE_SOURCE_DIR}/src/*.cpp) ADD_EXECUTABLE(${VINE_UNITTEST} ${UNITTEST_SRCS}) -TARGET_LINK_LIBRARIES(${VINE_UNITTEST} - ${VINE_LOGGER} - ${VINE_DEPS_LIB} - ${fw_name_deps_LIBRARIES} - ${GTEST} - dl -) + +IF(TIZEN_OS) + pkg_check_modules(unittest_deps REQUIRED gmock) + TARGET_LINK_LIBRARIES(${VINE_UNITTEST} + ${VINE_LOGGER} + ${VINE_DEPS_LIB} + ${fw_name_deps_LIBRARIES} + ${unittest_deps_LIBRARIES} + dl + ) +ELSE(TIZEN_OS) + IF(ANDROID) + SET(GOOGLETEST_ROOT ${ANDROID_NDK}/sources/third_party/googletest/) + ADD_LIBRARY(gtest STATIC ${GOOGLETEST_ROOT}/src/gtest_main.cc ${GOOGLETEST_ROOT}/src/gtest-all.cc) + TARGET_INCLUDE_DIRECTORIES(gtest PRIVATE ${GOOGLETEST_ROOT}) + TARGET_INCLUDE_DIRECTORIES(gtest PUBLIC ${GOOGLETEST_ROOT}/include) + ENDIF(ANDROID) + SET(GTEST gtest) + TARGET_LINK_LIBRARIES(${VINE_UNITTEST} + ${VINE_LOGGER} + ${VINE_DEPS_LIB} + ${fw_name_deps_LIBRARIES} + ${GTEST} + dl + ) +ENDIF(TIZEN_OS) + SET_TARGET_PROPERTIES(${VINE_UNITTEST} PROPERTIES COMPILE_FLAGS "-fPIE" -- 2.7.4 From b543f236889512e4b49dc5aaba598508f6ad4923 Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Fri, 23 Jul 2021 12:11:37 +0900 Subject: [PATCH 05/16] nan plugin: add publish and subscribe Change-Id: I891c5e17cd87909b6fabbffec45509610a20f69f Signed-off-by: Cheoleun Moon --- CMakeLists.txt | 12 ++ packaging/capi-network-vine.spec | 2 + plugins/nan/CMakeLists.txt | 51 ++++++ plugins/nan/nan-plugin.cpp | 380 +++++++++++++++++++++++++++++++++++++++ plugins/nan/nan-plugin.h | 20 +++ src/include/vine-constants.h | 3 + 6 files changed, 468 insertions(+) create mode 100755 plugins/nan/CMakeLists.txt create mode 100755 plugins/nan/nan-plugin.cpp create mode 100755 plugins/nan/nan-plugin.h 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__ */ -- 2.7.4 From 176f50b6bace73ba225011e4ce3f23bb0aedb989 Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Fri, 23 Jul 2021 13:08:35 +0900 Subject: [PATCH 06/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 07/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 08/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 09/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 10/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 11/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 12/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 13/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 14/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 15/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 16/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