From 811e338ec5801e2443c580caa55716c3ff11539d Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Tue, 29 Jun 2021 16:47:46 +0900 Subject: [PATCH 01/16] Change discoverd_cb for ble support Change-Id: Ie9750efb9662929d51f6660ac15bc25f5b9d08e8 Signed-off-by: Cheoleun Moon --- packaging/capi-network-vine.spec | 2 +- plugins/ble/ble-plugin.cpp | 20 ++++++++++++-------- src/include/vine-constants.h | 1 + src/include/vine-disc-plugin.h | 4 ++++ src/include/vine-disc.h | 2 +- src/include/vine-service.h | 3 +++ src/vine-disc.cpp | 29 +++++++++++++++++++++++++++++ src/vine-dp.cpp | 2 +- src/vine-service.cpp | 21 +++++++++++++++++++++ src/vine-session.cpp | 8 +++++--- 10 files changed, 78 insertions(+), 14 deletions(-) diff --git a/packaging/capi-network-vine.spec b/packaging/capi-network-vine.spec index 34cf751..8fcd8ba 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.1 +Version: 1.1.2 Release: 0 Group: Network & Connectivity/API License: Apache-2.0 diff --git a/plugins/ble/ble-plugin.cpp b/plugins/ble/ble-plugin.cpp index 97adf93..b289a61 100755 --- a/plugins/ble/ble-plugin.cpp +++ b/plugins/ble/ble-plugin.cpp @@ -246,16 +246,19 @@ static void __le_scan_result_cb(int result, bt_adapter_le_device_scan_result_inf vine_ble_s *ble_handle = (vine_ble_s *)user_data; int service_type_len = strlen(ble_handle->service_type); + if (manufacturer_len > service_type_len && strncmp(manufacturer_data, ble_handle->service_type, service_type_len) == 0) { char service_name[VINE_MAX_BLE_SERVICE_NAME_LEN + 1]; int service_name_len = manufacturer_len - 1 - service_type_len; strncpy(service_name, manufacturer_data + service_type_len + 1, service_name_len); - if (event_callbacks.discovered_cb) { + char mac[VINE_MAC_LEN + 1]; + strncpy(mac, info->remote_address, VINE_MAC_LEN); + + if (event_callbacks.ble_discovered_cb) { std::map empty_map; - event_callbacks.discovered_cb(ble_handle, true, - ble_handle->service_type, service_name, NULL, 0, empty_map, - NULL, 0, ble_handle->disc_handle); + event_callbacks.ble_discovered_cb(ble_handle, true, + ble_handle->service_type, service_name, mac, ble_handle->disc_handle); } } @@ -324,10 +327,11 @@ 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 = callbacks.discovered_cb; - event_callbacks.ip_resolved_cb = callbacks.ip_resolved_cb; - event_callbacks.fd_added_cb = callbacks.fd_added_cb; - event_callbacks.fd_removed_cb = callbacks.fd_removed_cb; + event_callbacks.discovered_cb = NULL; + 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/src/include/vine-constants.h b/src/include/vine-constants.h index 0082fab..0f570eb 100644 --- a/src/include/vine-constants.h +++ b/src/include/vine-constants.h @@ -33,5 +33,6 @@ // Even though the constraits is met, the operation can be failed. #define VINE_MAX_BLE_SERVICE_TYPE_LEN 15 #define VINE_MAX_BLE_SERVICE_NAME_LEN 15 +#define VINE_MAC_LEN 17 #endif /* __VINE_SERV__VINE_CONSTANTS_H__ICE_H__ */ diff --git a/src/include/vine-disc-plugin.h b/src/include/vine-disc-plugin.h index 79178b0..fd8330e 100755 --- a/src/include/vine-disc-plugin.h +++ b/src/include/vine-disc-plugin.h @@ -59,6 +59,10 @@ typedef struct { 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 { diff --git a/src/include/vine-disc.h b/src/include/vine-disc.h index c499cde..42faa43 100755 --- a/src/include/vine-disc.h +++ b/src/include/vine-disc.h @@ -32,7 +32,7 @@ typedef void (*vine_disc_published_cb)(vine_disc_h disc, 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, void *user_data); + const char *iface_name, int more_coming, const char *mac, 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/include/vine-service.h b/src/include/vine-service.h index 302a491..250be01 100755 --- a/src/include/vine-service.h +++ b/src/include/vine-service.h @@ -54,6 +54,9 @@ int _vine_service_get_attributes_as_arrays(vine_service_h service, int _vine_service_set_iface_name(vine_service_h service, const char *iface_name); const char *_vine_service_get_iface_name(vine_service_h service); +int _vine_service_set_mac(vine_service_h service, const char *mac); +const char *_vine_service_get_mac(vine_service_h service); + int _vine_service_get_disc_handle(vine_service_h service, vine_discovery_method_e disc_method, void **disc_handle); int _vine_service_set_ip_resolved_cb(vine_service_h service, vine_session_h session, diff --git a/src/vine-disc.cpp b/src/vine-disc.cpp index 0f983c7..f967c59 100755 --- a/src/vine-disc.cpp +++ b/src/vine-disc.cpp @@ -49,6 +49,7 @@ static struct { }; typedef struct { + vine_discovery_method_e method; vine_disc_plugin_fn *plugin_fn; vine_disc_published_cb published_cb; @@ -77,6 +78,7 @@ typedef struct { map attributes; char iface_name[IF_NAMESIZE + 1]; int more_coming; + char mac[VINE_MAC_LEN + 1]; } vine_discovered_event; typedef struct { @@ -141,6 +143,7 @@ static void __invoke_discovered_user_cb(void *event, void *user_data) discovered_event->attributes, discovered_event->iface_name, discovered_event->more_coming, + discovered_event->mac, disc_handle->discovered_cb_data); } @@ -237,6 +240,30 @@ static void __discovered_cb(void *plugin_handle, bool available, user_data); } +static void __ble_discovered_cb(void *plugin_handle, bool available, + const char *service_type, const char *service_name, const char *mac, + void *user_data) +{ + 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); + + VINE_LOGD("Create a discovered_event[%p]", discovered_event); + + vine_disc_s *disc_handle = (vine_disc_s *)user_data; + if (disc_handle) + vine_event_loop_add_event(disc_handle->event_queue, discovered_event, + __invoke_discovered_user_cb, __free_discovered_event, + user_data); +} + static void __ip_resolved_cb(void *plugin_handle, bool add, const char *ip, sa_family_t address_family, void *user_data) { @@ -330,6 +357,7 @@ 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); } } @@ -357,6 +385,7 @@ int vine_disc_create(vine_discovery_method_e disc_method, vine_disc_h *disc) RET_VAL_IF(disc_handle == NULL, VINE_ERROR_OUT_OF_MEMORY, "Out of Memory"); *disc = disc_handle; + disc_handle->method = disc_method; disc_handle->plugin_fn = &__vine_disc_plugins[disc_method].fn; VINE_LOGD("New Discovery handle[%p] disc_method[%d]", disc_handle, disc_method); diff --git a/src/vine-dp.cpp b/src/vine-dp.cpp index 2c435dc..29a640f 100644 --- a/src/vine-dp.cpp +++ b/src/vine-dp.cpp @@ -310,7 +310,7 @@ static void _ip_resolved_cb(vine_disc_h disc, vine_service_h service, bool add, 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, void *user_data) + const char *iface_name, int more_coming, const char *mac, void *user_data) { VINE_LOGD("%s is discovered. %s", service_name, available ? "available" : "not available"); diff --git a/src/vine-service.cpp b/src/vine-service.cpp index 7fa39ce..cf7832c 100755 --- a/src/vine-service.cpp +++ b/src/vine-service.cpp @@ -40,6 +40,7 @@ typedef struct { map attributes; char iface_name[IF_NAMESIZE + 1]; vine_service_state_e state; + char mac[VINE_MAC_LEN + 1]; // Only for ble discovery // For IP resolving void *disc_handle; // Used to resolve IP address @@ -78,6 +79,7 @@ int _vine_service_create(vine_service_h *service, bool published) memset(s->service_name, 0, VINE_MAX_SERVICE_NAME_LEN + 1); memset(s->host_name, 0, VINE_MAX_HOST_NAME_LEN + 1); memset(s->iface_name, 0, IF_NAMESIZE + 1); + memset(s->mac, 0, VINE_MAC_LEN + 1); s->port = -1; s->state = VINE_SERVICE_UNAVAILABLE; s->family = VINE_ADDRESS_FAMILY_DEFAULT; @@ -122,6 +124,7 @@ int _vine_service_clone(vine_service_h origin, vine_service_h *cloned) cloned_service->port = origin_service->port; cloned_service->attributes = origin_service->attributes; strncpy(cloned_service->iface_name, origin_service->iface_name, IF_NAMESIZE); + strncpy(cloned_service->mac, origin_service->mac, VINE_MAC_LEN); cloned_service->state = origin_service->state; cloned_service->disc_handle = NULL; @@ -303,6 +306,24 @@ const char *_vine_service_get_iface_name(vine_service_h service) return s->iface_name; } +int _vine_service_set_mac(vine_service_h service, const char *mac) +{ + RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL"); + + vine_service_s *s = (vine_service_s *)service; + strncpy(s->mac, mac, VINE_MAC_LEN); + + return VINE_ERROR_NONE; +} + +const char *_vine_service_get_mac(vine_service_h service) +{ + RET_VAL_IF(service == NULL, NULL, "service is NULL"); + + vine_service_s *s = (vine_service_s *)service; + return s->mac; +} + int _vine_service_get_disc_handle(vine_service_h service, vine_discovery_method_e disc_method, void **disc_handle) { diff --git a/src/vine-session.cpp b/src/vine-session.cpp index 817536b..6e91fc2 100755 --- a/src/vine-session.cpp +++ b/src/vine-session.cpp @@ -256,7 +256,7 @@ 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 *iface_name, const char *mac) { int ret = VINE_ERROR_NONE; ret = _vine_service_set_type(service, service_type); @@ -274,13 +274,15 @@ 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, void *user_data) + const char *iface_name, int more_coming, const char *mac, void *user_data) { VINE_LOGD("Service is discovered. Available[%d]", available); int ret = VINE_ERROR_NONE; @@ -294,7 +296,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); + service_type, service_name, host_name, port, attr, iface_name, mac); if (ret != VINE_ERROR_NONE) { VINE_LOGE("Fail to set a service. error(%d)", ret); _vine_service_destroy(discovered_service); -- 2.7.4 From 1d1a50174735e1d6788e9fdd67e830afd70bd805 Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Thu, 1 Jul 2021 15:02:14 +0900 Subject: [PATCH 02/16] vine-tool: Add ble discovery Change-Id: Iebc94f08af3e7525e53d08a2370d9f34dfa97118 Signed-off-by: Cheoleun Moon --- include/vine.h | 15 +++++ packaging/capi-network-vine.spec | 2 +- plugins/ble/ble-plugin.cpp | 132 ++++++++++++++++++++++++++++++++----- src/vine-event-loop.cpp | 4 +- src/vine-session.cpp | 10 ++- src/vine.cpp | 15 +++++ tests/vine-test/vine-test-glib.cpp | 10 --- tool/tool_config.cpp | 12 ++++ tool/tool_config.h | 2 + tool/tool_help.cpp | 1 + tool/tool_parse.cpp | 6 +- tool/tool_run.cpp | 88 +++++++++++++++++++++---- 12 files changed, 254 insertions(+), 43 deletions(-) mode change 100644 => 100755 tool/tool_run.cpp diff --git a/include/vine.h b/include/vine.h index 6511b19..aa9d10b 100755 --- a/include/vine.h +++ b/include/vine.h @@ -826,6 +826,21 @@ int vine_service_set_port(vine_service_h service, int port); int vine_service_get_port(vine_service_h service, int *port); /** + * @brief Gets the MAC address for the service. + * @remarks @a mac must be released using free(). + * @since_tizen 6.5 + * @param[in] service The service handle + * @param[out] mac The MAC address + * @return 0 on success, otherwise a negative error value + * @retval #VINE_ERROR_NONE Successful + * @retval #VINE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VINE_ERROR_OUT_OF_MEMORY Out of memory + * @retval #VINE_ERROR_NOT_SUPPORTED Not supported + * @see vine_service_create() + */ +int vine_service_get_mac(vine_service_h service, char **mac); + +/** * @brief Creates the data path handle. * @since_tizen 6.5 * @param[in] session The session handle diff --git a/packaging/capi-network-vine.spec b/packaging/capi-network-vine.spec index 8fcd8ba..2cfa80e 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.2 +Version: 1.1.3 Release: 0 Group: Network & Connectivity/API License: Apache-2.0 diff --git a/plugins/ble/ble-plugin.cpp b/plugins/ble/ble-plugin.cpp index b289a61..01de78c 100755 --- a/plugins/ble/ble-plugin.cpp +++ b/plugins/ble/ble-plugin.cpp @@ -44,6 +44,97 @@ typedef struct { static vine_disc_plugin_callbacks event_callbacks; +static const char *__convert_ble_erro_to_str(int error) +{ + const char *err_str = NULL; + + switch (error) { + case BT_ERROR_NONE: + err_str = "BT_ERROR_NONE"; + break; + case BT_ERROR_CANCELLED: + err_str = "BT_ERROR_CANCELLED"; + break; + case BT_ERROR_INVALID_PARAMETER: + err_str = "BT_ERROR_INVALID_PARAMETER"; + break; + case BT_ERROR_OUT_OF_MEMORY: + err_str = "BT_ERROR_OUT_OF_MEMORY"; + break; + case BT_ERROR_RESOURCE_BUSY: + err_str = "BT_ERROR_RESOURCE_BUSY"; + break; + case BT_ERROR_TIMED_OUT: + err_str = "BT_ERROR_TIMED_OUT"; + break; + case BT_ERROR_NOW_IN_PROGRESS: + err_str = "BT_ERROR_NOW_IN_PROGRESS"; + break; + case BT_ERROR_NOT_INITIALIZED: + err_str = "BT_ERROR_NOT_INITIALIZED"; + break; + case BT_ERROR_NOT_ENABLED: + err_str = "BT_ERROR_NOT_ENABLED"; + break; + case BT_ERROR_ALREADY_DONE: + err_str = "BT_ERROR_ALREADY_DONE"; + break; + case BT_ERROR_OPERATION_FAILED: + err_str = "BT_ERROR_OPERATION_FAILED"; + break; + case BT_ERROR_NOT_IN_PROGRESS: + err_str = "BT_ERROR_NOT_IN_PROGRESS"; + break; + case BT_ERROR_REMOTE_DEVICE_NOT_BONDED: + err_str = "BT_ERROR_REMOTE_DEVICE_NOT_BONDED"; + break; + case BT_ERROR_AUTH_REJECTED: + err_str = "BT_ERROR_AUTH_REJECTED"; + break; + case BT_ERROR_AUTH_FAILED: + err_str = "BT_ERROR_AUTH_FAILED"; + break; + case BT_ERROR_REMOTE_DEVICE_NOT_FOUND: + err_str = "BT_ERROR_REMOTE_DEVICE_NOT_FOUND"; + break; + case BT_ERROR_SERVICE_SEARCH_FAILED: + err_str = "BT_ERROR_SERVICE_SEARCH_FAILED"; + break; + case BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED: + err_str = "BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED"; + break; + case BT_ERROR_PERMISSION_DENIED: + err_str = "BT_ERROR_PERMISSION_DENIED"; + break; + case BT_ERROR_SERVICE_NOT_FOUND: + err_str = "BT_ERROR_SERVICE_NOT_FOUND"; + break; + case BT_ERROR_NO_DATA: + err_str = "BT_ERROR_NO_DATA"; + break; + case BT_ERROR_NOT_SUPPORTED: + err_str = "BT_ERROR_NOT_SUPPORTED"; + break; + case BT_ERROR_DEVICE_POLICY_RESTRICTION: + err_str = "DEVICE_POLICY_RESTRICTION"; + break; + case BT_ERROR_QUOTA_EXCEEDED: + err_str = "BT_ERROR_QUOTA_EXCEEDED"; + break; + case BT_ERROR_AGAIN: + err_str = "BT_ERROR_AGAIN"; + break; + case BT_ERROR_AUTHORIZATION_REJECTED: + err_str = "BT_ERROR_AUTHORIZATION_REJECTED"; + break; + default: + err_str = "NOT Defined"; + break; + } + + return err_str; +} + static vine_disc_error __convert_ble_error_to_vine_disc_error(int error) { switch (error) { @@ -112,6 +203,10 @@ static int __configure_advertiser(bt_advertiser_h adv, RET_VAL_IF(ret != BT_ERROR_NONE, ret, "bt_adapter_le_add_advertising_service_uuid() fails %d", ret); + ret = bt_adapter_le_add_advertising_service_uuid(adv, + BT_ADAPTER_LE_PACKET_ADVERTISING, VINE_UUID); + RET_VAL_IF(ret != BT_ERROR_NONE, ret, + "bt_adapter_le_add_advertising_service_uuid() fails %d", ret); // TODO: Determine which data should be set for service_data // It should be set mandatorily? // Or we don't have to set service_data if manufacturer data is set @@ -121,22 +216,26 @@ static int __configure_advertiser(bt_advertiser_h adv, BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, VINE_UUID, service_data, sizeof(service_data)); RET_VAL_IF(ret != BT_ERROR_NONE, ret, - "bt_adapter_le_add_advertising_service_data() fails %d", ret); + "bt_adapter_le_add_advertising_service_data() fails %s(%d)", + __convert_ble_erro_to_str(ret), ret); // TODO: Also set for BT_ADAPTER_LE_PACKET_ADVERTISING? ret = bt_adapter_le_set_advertising_device_name(adv, BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, true); RET_VAL_IF(ret != BT_ERROR_NONE, ret, - "bt_adapter_le_set_advertising_device_name() fails %d", ret); + "bt_adapter_le_set_advertising_device_name() fails %s(%d)", + __convert_ble_erro_to_str(ret), ret); ret = bt_adapter_le_set_advertising_connectable(adv, true); RET_VAL_IF(ret != BT_ERROR_NONE, ret, - "bt_adapter_le_set_advertising_connectable() fails %d", ret); + "bt_adapter_le_set_advertising_connectable() fails %s(%d)", + __convert_ble_erro_to_str(ret), ret); ret = bt_adapter_le_set_advertising_mode(adv, BT_ADAPTER_LE_ADVERTISING_MODE_BALANCED); RET_VAL_IF(ret != BT_ERROR_NONE, ret, - "bt_adapter_le_set_advertising_mode() fails %d", ret); + "bt_adapter_le_set_advertising_mode() fails %s(%d)", + __convert_ble_erro_to_str(ret), ret); char manufacturer_data[VINE_MAX_MANUFACTURER_DATA_LEN + 1]; int manufacturer_len = strlen(service_type) + strlen(service_name) + 1; @@ -150,8 +249,8 @@ static int __configure_advertiser(bt_advertiser_h adv, BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, VINE_MANUFACTURER_ID, manufacturer_data, manufacturer_len); RET_VAL_IF(ret != BT_ERROR_NONE, ret, - "bt_adapter_le_add_advertising_manufacturer_data() fails %d", ret); - + "bt_adapter_le_add_advertising_manufacturer_data() fails %s(%d)", + __convert_ble_erro_to_str(ret), ret); return BT_ERROR_NONE; } @@ -184,7 +283,8 @@ vine_disc_error ble_publish(void *plugin_handle, const char *service_type, ret = bt_adapter_le_start_advertising_new(ble_handle->adv, __ble_advertising_state_changed_cb, ble_handle); if (ret != BT_ERROR_NONE) { - VINE_LOGE("bt_adapter_le_start_advertising_new() fails %d", ret); + VINE_LOGE("bt_adapter_le_start_advertising_new() fails %s(%d)", + __convert_ble_erro_to_str(ret), ret); goto ERR; } @@ -212,7 +312,7 @@ vine_disc_error ble_stop_publish(void *plugin_handle) return __convert_ble_error_to_vine_disc_error(ret); } -static int __configure_scan_filter(bt_scan_filter_h filter, const char *service_type) +static int __configure_scan_filter(bt_scan_filter_h filter) { int ret = bt_adapter_le_scan_filter_set_service_uuid(filter, VINE_UUID); RET_VAL_IF(ret != BT_ERROR_NONE, ret, @@ -242,17 +342,18 @@ static void __le_scan_result_cb(int result, bt_adapter_le_device_scan_result_inf // TODO: For now, check only scan_data int ret = bt_adapter_le_get_scan_result_manufacturer_data(info, BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, &manufacturer_id, &manufacturer_data, &manufacturer_len); - RET_IF(ret != BT_ERROR_NONE, "Invalid Data"); + RET_IF(ret != BT_ERROR_NONE, "Invalid Data %s(%d)", + __convert_ble_erro_to_str(ret), ret); vine_ble_s *ble_handle = (vine_ble_s *)user_data; int service_type_len = strlen(ble_handle->service_type); if (manufacturer_len > service_type_len && strncmp(manufacturer_data, ble_handle->service_type, service_type_len) == 0) { - char service_name[VINE_MAX_BLE_SERVICE_NAME_LEN + 1]; + char service_name[VINE_MAX_BLE_SERVICE_NAME_LEN + 1] = {0, }; int service_name_len = manufacturer_len - 1 - service_type_len; - strncpy(service_name, manufacturer_data + service_type_len + 1, service_name_len); - char mac[VINE_MAC_LEN + 1]; + strncpy(service_name, manufacturer_data + service_type_len + 1, VINE_MAX_BLE_SERVICE_NAME_LEN); + char mac[VINE_MAC_LEN + 1] = {0, }; strncpy(mac, info->remote_address, VINE_MAC_LEN); if (event_callbacks.ble_discovered_cb) { @@ -280,13 +381,14 @@ vine_disc_error ble_subscribe(void *plugin_handle, RET_VAL_IF(ret != BT_ERROR_NONE, __convert_ble_error_to_vine_disc_error(ret), "bt_adapter_le_scan_filter_create() fails"); - ret = __configure_scan_filter(ble_handle->filter, service_type); + ret = __configure_scan_filter(ble_handle->filter); if (ret != BT_ERROR_NONE) { - VINE_LOGE("__configure_scan_filter() fails %d", ret); + VINE_LOGE("__configure_scan_filter() fails %s(%d)", + __convert_ble_erro_to_str(ret), ret); goto ERR; } - ret = bt_adapter_le_start_scan(__le_scan_result_cb, NULL); + ret = bt_adapter_le_start_scan(__le_scan_result_cb, ble_handle); if (ret != BT_ERROR_NONE) { VINE_LOGE("bt_adapter_le_start_scan() fails"); goto ERR; diff --git a/src/vine-event-loop.cpp b/src/vine-event-loop.cpp index b1dacf5..84dae68 100755 --- a/src/vine-event-loop.cpp +++ b/src/vine-event-loop.cpp @@ -48,11 +48,11 @@ int vine_event_loop_set(vine_event_loop_e loop) VINE_ERROR_INVALID_PARAMETER, "Invalid parameter"); #ifndef USE_VINE_EVENT_LOOP_EPOLL - RET_VAL_IF(loop == VINE_EVENT_LOOP_DEFAULT, VINE_ERROR_INVALID_PARAMETER, + RET_VAL_IF(loop == VINE_EVENT_LOOP_DEFAULT, VINE_ERROR_NOT_SUPPORTED, "External glib event loop is not supported"); #endif #ifndef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB - RET_VAL_IF(loop == VINE_EVENT_LOOP_EXTERNAL_GLIB, VINE_ERROR_INVALID_PARAMETER, + RET_VAL_IF(loop == VINE_EVENT_LOOP_EXTERNAL_GLIB, VINE_ERROR_NOT_SUPPORTED, "External glib event loop is not supported"); #endif diff --git a/src/vine-session.cpp b/src/vine-session.cpp index 6e91fc2..599a349 100755 --- a/src/vine-session.cpp +++ b/src/vine-session.cpp @@ -166,7 +166,8 @@ int _vine_session_unset_discovered_cb(vine_session_h session) static bool __check_disc_method(vine_discovery_method_e method) { - return method == VINE_DISCOVERY_METHOD_DNS_SD; + return method >= VINE_DISCOVERY_METHOD_DNS_SD + && method <= VINE_DISCOVERY_METHOD_BLE; } int _vine_session_set_discovery_method(vine_session_h session, vine_discovery_method_e method) @@ -265,8 +266,11 @@ 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_port(service, port); - RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to set port"); + + if (port >= 0) { + ret = _vine_service_set_port(service, port); + RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to set port"); + } for (const auto &kv : attr) _vine_service_add_attribute(service, kv.first.c_str(), kv.second.c_str()); diff --git a/src/vine.cpp b/src/vine.cpp index f5fb50a..6c2d95e 100755 --- a/src/vine.cpp +++ b/src/vine.cpp @@ -319,6 +319,21 @@ API int vine_service_get_port(vine_service_h service, int *port) return VINE_ERROR_NONE; } +API int vine_service_get_mac(vine_service_h service, char **mac) +{ + __VINE_FUNC_ENTER__; + CHECK_FEATURE_SUPPORTED; + + RET_VAL_IF(service == NULL, VINE_ERROR_INVALID_PARAMETER, "service is NULL"); + RET_VAL_IF(mac == NULL, VINE_ERROR_INVALID_PARAMETER, + "mac is NULL"); + + *mac = (char *)strndup(_vine_service_get_mac(service), + VINE_MAC_LEN); + RET_VAL_IF(*mac == NULL, VINE_ERROR_OUT_OF_MEMORY, "Out of memory"); + return VINE_ERROR_NONE; +} + API int vine_dp_create(vine_session_h session, vine_dp_type_e type, vine_dp_h *dp) { __VINE_FUNC_ENTER__; diff --git a/tests/vine-test/vine-test-glib.cpp b/tests/vine-test/vine-test-glib.cpp index af09216..bfb0deb 100755 --- a/tests/vine-test/vine-test-glib.cpp +++ b/tests/vine-test/vine-test-glib.cpp @@ -83,16 +83,6 @@ static void __quit() exit(1); } -static void __event_handler(vine_session_h session) -{ - printf("Vine Event\n"); - PRINT_IF_ERROR(vine_session_process_event(session), "vine_process_event"); -} - -static void __start_event_loop() -{ -} - static void __init() { PRINT_IF_ERROR(vine_initialize(), "vine_initialize()"); diff --git a/tool/tool_config.cpp b/tool/tool_config.cpp index e56e106..18e7de2 100644 --- a/tool/tool_config.cpp +++ b/tool/tool_config.cpp @@ -11,6 +11,7 @@ static struct { char *service_name; char *service_type; char *iface_name; + bool with_ble; char *remote_addr; int addr_family; int port; @@ -32,6 +33,7 @@ static struct { .service_name = NULL, .service_type = NULL, .iface_name = NULL, + .with_ble = false, .remote_addr = NULL, .addr_family = 0, .port = 0, @@ -99,6 +101,16 @@ const char *tool_config_get_iface_name() return (const char *)configs.iface_name; } +void tool_config_set_with_ble(bool val) +{ + configs.with_ble = val; +} + +bool tool_config_get_with_ble() +{ + return configs.with_ble; +} + void tool_config_set_remote_address(char *val) { configs.remote_addr = STRDUP(val); diff --git a/tool/tool_config.h b/tool/tool_config.h index 6e0a7da..531b225 100644 --- a/tool/tool_config.h +++ b/tool/tool_config.h @@ -21,6 +21,8 @@ void tool_config_set_service_type(char *val); const char *tool_config_get_service_type(); void tool_config_set_iface_name(char *val); const char *tool_config_get_iface_name(); +void tool_config_set_with_ble(bool val); +bool tool_config_get_with_ble(); void tool_config_set_remote_address(char *val); const char *tool_config_get_remote_address(); void tool_config_set_address_family(int val); diff --git a/tool/tool_help.cpp b/tool/tool_help.cpp index 01e8610..e7fc1f0 100644 --- a/tool/tool_help.cpp +++ b/tool/tool_help.cpp @@ -48,6 +48,7 @@ static const struct help_msg help_msgs[] = { {OPT_TYPE_SERVICE_DISCOVERY, "-n, --name ", "Service name"}, {OPT_TYPE_SERVICE_DISCOVERY, "-t, --type ", "Service type"}, {OPT_TYPE_SERVICE_DISCOVERY, "-i, --iface ", "Interface name"}, + {OPT_TYPE_SERVICE_DISCOVERY, "-b --ble", "Use BLE"}, {OPT_TYPE_DATA_PATH, "-a, --addr ", "Remote IP"}, {OPT_TYPE_DATA_PATH, "-4, --ipv4", "IPv4 only (optional)"}, {OPT_TYPE_DATA_PATH, "-6, --ipv6", "IPv6 (optional)"}, diff --git a/tool/tool_parse.cpp b/tool/tool_parse.cpp index b5d4e02..699dd15 100644 --- a/tool/tool_parse.cpp +++ b/tool/tool_parse.cpp @@ -12,6 +12,7 @@ static struct option options[] = { {"name", required_argument, 0, 'n'}, {"type", required_argument, 0, 't'}, {"iface", required_argument, 0, 'i'}, + {"ble", no_argument, 0, 'b'}, {"addr", required_argument, 0, 'a'}, {"ipv4", no_argument, 0, '4'}, {"ipv6", no_argument, 0, '6'}, @@ -39,7 +40,7 @@ int tool_parse_params(int argc, char **argv) while (!error) { int idx = 0; - c = getopt_long(argc, argv, "rdn:t:i:a:46p:D:T:C:m:f:I:vw:h", options, &idx); + c = getopt_long(argc, argv, "rdn:t:i:ba:46p:D:T:C:m:f:I:vw:h", options, &idx); if (c == -1) break; @@ -59,6 +60,9 @@ int tool_parse_params(int argc, char **argv) case 'i': tool_config_set_iface_name(optarg); break; + case 'b': + tool_config_set_with_ble(true); + break; case 'a': tool_config_set_remote_address(optarg); break; diff --git a/tool/tool_run.cpp b/tool/tool_run.cpp old mode 100644 new mode 100755 index 8b5a84c..db3952a --- a/tool/tool_run.cpp +++ b/tool/tool_run.cpp @@ -14,6 +14,10 @@ #include #include +#ifdef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB +#include +#endif + #define RESET_COLOR "\e[m" #define MAKE_RED "\e[31m" #define MAKE_GREEN "\e[32m" @@ -33,6 +37,7 @@ static struct { vine_security_h security; const char *type; const char *iface; + bool with_ble; vine_dp_type_e dp_type; int max_conn; const char *msg; @@ -49,6 +54,7 @@ static struct { .security = NULL, .type = NULL, .iface = NULL, + .with_ble = false, .dp_type = VINE_DP_TYPE_UNKNOWN, .max_conn = 0, .msg = NULL, @@ -250,12 +256,47 @@ static void __ip_resolved_cb(vine_session_h session, vine_service_h service, free(service_name); } +static void __ble_service_discovered(vine_session_h session, vine_service_h service, + vine_service_state_e state, void *user_data) +{ + printf("available[%d]\n", state); + vine_service_h s; + vine_service_clone(service, &s); + + printf("Service discovered.\n"); + + char *service_type; + char *service_name; + char *mac; + vine_service_get_type(service, &service_type); + vine_service_get_name(service, &service_name); + vine_service_get_mac(service, &mac); + + printf("\t > Service Type: %s\n", service_type); + printf("\t > Service Name: %s\n", service_name); + printf("\t > MAC Address: %s\n", mac); + printf("\n"); + fflush(stdout); + + free(service_type); + free(service_name); + free(mac); + + vine_session_stop_discovery(session); +} + static void __discovered_cb(vine_session_h session, vine_service_h service, vine_service_state_e state, void *user_data) { + if (vine_configs.with_ble) { + __ble_service_discovered(session, service, state, user_data); + return; + } + printf("available[%d]\n", state); vine_service_h s; vine_service_clone(service, &s); + vine_session_set_ip_resolved_cb(session, s, _convert_addr_family(tool_config_get_address_family()), __ip_resolved_cb, NULL); @@ -392,6 +433,11 @@ static int send_message(vine_dp_h dp) static int init() { + if(vine_configs.with_ble) { + if (vine_set_event_loop(VINE_EVENT_LOOP_EXTERNAL_GLIB) != VINE_ERROR_NONE) + return -1; + } + int ret = vine_initialize(); if (ret != VINE_ERROR_NONE) return -1; @@ -400,6 +446,9 @@ static int init() if (ret != VINE_ERROR_NONE) return -1; + if(vine_configs.with_ble) + vine_session_set_discovery_method(vine_configs.session, VINE_DISCOVERY_METHOD_BLE); + return 0; } @@ -545,23 +594,15 @@ static void _set_security_info(vine_security_type_e type) static void set_vine_configs() { + vine_configs.with_ble = tool_config_get_with_ble(); vine_configs.is_reg = tool_config_get_register(); - if (vine_configs.is_reg) - _set_register_info(); - vine_configs.is_disc = tool_config_get_discovery(); - if (vine_configs.is_disc) - _set_discovery_info(); vine_security_type_e sec_type = _convert_sec_type(tool_config_get_security_type()); vine_configs.is_sec = sec_type != VINE_SECURITY_TYPE_NONE ? true : false; - if (vine_configs.is_sec) - _set_security_info(sec_type); vine_configs.dp_type = _convert_dp_type(tool_config_get_dp_type()); vine_configs.is_dp = vine_configs.dp_type != VINE_DP_TYPE_UNKNOWN ? true : false; - if (vine_configs.is_dp) - _set_dp_info(vine_configs.dp_type); } static void _event_handler(vine_session_h session) @@ -569,7 +610,15 @@ static void _event_handler(vine_session_h session) vine_session_process_event(session); } -static void run_event_loop(vine_session_h session) +static void _run_glib_event_loop() +{ + GMainLoop *main_loop = g_main_loop_new(NULL, FALSE); + + g_main_loop_run(main_loop); + g_main_loop_unref(main_loop); +} + +static void _run_epoll_event_loop(vine_session_h session) { int fd; int ret = vine_session_get_event_fd(session, &fd); @@ -607,16 +656,33 @@ static void run_event_loop(vine_session_h session) close(epollfd); } +static void run_event_loop(vine_session_h session) +{ + if (vine_configs.with_ble) + _run_glib_event_loop(); + else + _run_epoll_event_loop(session); +} + int tool_run() { int ret = 0; debug_on(); + set_vine_configs(); + if (init() < 0) goto DONE; - set_vine_configs(); + if (vine_configs.is_reg) + _set_register_info(); + if (vine_configs.is_disc) + _set_discovery_info(); + if (vine_configs.is_sec) + _set_security_info(_convert_sec_type(tool_config_get_security_type())); + if (vine_configs.is_dp) + _set_dp_info(vine_configs.dp_type); if (vine_configs.is_reg) { ret = vine_session_register(vine_configs.session, -- 2.7.4 From b76d4a057b713de15f8ec3f881fdf653ace9c7e5 Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Fri, 2 Jul 2021 11:16:19 +0900 Subject: [PATCH 03/16] Handle unsupported functions Change-Id: I9ae35dd453129acd27dc5d6e0713724256fdad24 Signed-off-by: Cheoleun Moon --- CMakeLists.txt | 10 ++++++++-- packaging/capi-network-vine.spec | 6 +++--- plugins/ble/ble-plugin.cpp | 4 ++++ src/include/vine-event-loop.h | 4 ++-- src/vine-disc.cpp | 2 ++ src/vine-event-loop-epoll.cpp | 3 ++- src/vine-event-loop-glib.cpp | 3 ++- src/vine-event-loop.cpp | 4 ++-- src/vine-session.cpp | 16 ++++++++++++---- tool/tool_config.cpp | 0 tool/tool_run.cpp | 4 ++++ 11 files changed, 41 insertions(+), 15 deletions(-) mode change 100644 => 100755 tool/tool_config.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e0109b..eae5055 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,12 @@ IF(TIZEN_OS) ADD_DEFINITIONS("-DTIZEN_OS -DUSE_DLOG") ENDIF(TIZEN_OS) +SET(BT_SUPPORT OFF) +IF(TIZEN_OS AND USE_EVENT_LOOP_EXTERNAL_GLIB) + ADD_DEFINITIONS("-DBT_SUPPORT") + SET(BT_SUPPORT ON) +ENDIF(TIZEN_OS AND USE_EVENT_LOOP_EXTERNAL_GLIB) + 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") @@ -119,9 +125,9 @@ IF(USE_LIBWEBSOCKETS) ENDIF(USE_LIBWEBSOCKETS) ADD_SUBDIRECTORY(plugins/dns-sd) -IF(TIZEN_OS AND USE_EVENT_LOOP_EXTERNAL_GLIB) +IF(BT_SUPPORT) ADD_SUBDIRECTORY(plugins/ble) -ENDIF(TIZEN_OS AND USE_EVENT_LOOP_EXTERNAL_GLIB) +ENDIF(BT_SUPPORT) ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(src/logger) diff --git a/packaging/capi-network-vine.spec b/packaging/capi-network-vine.spec index 2cfa80e..1aa666a 100755 --- a/packaging/capi-network-vine.spec +++ b/packaging/capi-network-vine.spec @@ -104,12 +104,12 @@ export LDFLAGS+=" -lgcov" -DUSE_LIBWEBSOCKETS_STATIC=OFF \ %endif %if %{with lws_static_prebuilt} - -DUSE_LIBWEBSOCKETS_STATIC_PREBUILT=ON \ + -DUSE_LIBWEBSOCKETS_STATIC_PREBUILT=ON \ %else - -DUSE_LIBWEBSOCKETS_STATIC_PREBUILT=OFF \ + -DUSE_LIBWEBSOCKETS_STATIC_PREBUILT=OFF \ %endif -DWITH_UNITTEST=ON \ - -DENABLE_DATAPATH_PLUGIN_DEBUG=ON \ + -DENABLE_DATAPATH_PLUGIN_DEBUG=ON \ -DWITH_VINE_TEST=ON make %{?jobs:-j%jobs} diff --git a/plugins/ble/ble-plugin.cpp b/plugins/ble/ble-plugin.cpp index 01de78c..33f057b 100755 --- a/plugins/ble/ble-plugin.cpp +++ b/plugins/ble/ble-plugin.cpp @@ -270,6 +270,8 @@ vine_disc_error ble_publish(void *plugin_handle, const char *service_type, vine_ble_s *ble_handle = (vine_ble_s *)plugin_handle; RET_VAL_IF(ble_handle->adv != NULL, VINE_DISC_ERROR_INVALID_PARAMETER, "Already published"); + VINE_LOGD("Publish a service. plugin_handle[%p]\n", plugin_handle); + int ret = bt_adapter_le_create_advertiser(&ble_handle->adv); RET_VAL_IF(ret != BT_ERROR_NONE, __convert_ble_error_to_vine_disc_error(ret), "bt_adapter_le_create_advertiser() fails"); @@ -377,6 +379,8 @@ vine_disc_error ble_subscribe(void *plugin_handle, vine_ble_s *ble_handle = (vine_ble_s *)plugin_handle; RET_VAL_IF(ble_handle->filter != NULL, VINE_DISC_ERROR_INVALID_PARAMETER, "Already subscribed"); + VINE_LOGD("Subscribe a service. plugin_handle[%p]", plugin_handle); + int ret = bt_adapter_le_scan_filter_create(&ble_handle->filter); RET_VAL_IF(ret != BT_ERROR_NONE, __convert_ble_error_to_vine_disc_error(ret), "bt_adapter_le_scan_filter_create() fails"); diff --git a/src/include/vine-event-loop.h b/src/include/vine-event-loop.h index 48ab5b6..05379c4 100755 --- a/src/include/vine-event-loop.h +++ b/src/include/vine-event-loop.h @@ -47,7 +47,7 @@ void vine_event_loop_stop(); int vine_event_queue_create(vine_event_queue_h *event_queue); void vine_event_queue_destroy(vine_event_queue_h event_queue); -void vine_event_loop_get_eventfd(vine_event_queue_h event_queue, int *eventfd); +int vine_event_loop_get_eventfd(vine_event_queue_h event_queue, int *eventfd); int vine_event_loop_process(vine_event_queue_h event_queue); int vine_event_loop_add_io_handler(int fd, int events, @@ -68,7 +68,7 @@ typedef struct { void (*stop)(); int (*event_queue_create)(vine_event_queue_h *event_queue); void (*event_queue_destroy)(vine_event_queue_h event_queue); - void (*get_eventfd)(vine_event_queue_h event_queue, int *eventfd); + int (*get_eventfd)(vine_event_queue_h event_queue, int *eventfd); int (*process)(vine_event_queue_h event_queue); int (*add_io_handler)(int fd, int events, vine_poll_handler handler, void *user_data); int (*mod_io_handler)(int fd, int events, vine_poll_handler handler, void *user_data); diff --git a/src/vine-disc.cpp b/src/vine-disc.cpp index f967c59..01aa202 100755 --- a/src/vine-disc.cpp +++ b/src/vine-disc.cpp @@ -31,7 +31,9 @@ static struct { const char *path; } __vine_disc_plugins_info[] = { [VINE_DISCOVERY_METHOD_DNS_SD] = {"DNS-SD", DNS_SD_PLUGIN_PATH}, +#ifdef BT_SUPPORT [VINE_DISCOVERY_METHOD_BLE] = {"BLE", BLE_PLUGIN_PATH}, +#endif {NULL, NULL}, }; diff --git a/src/vine-event-loop-epoll.cpp b/src/vine-event-loop-epoll.cpp index c3beefd..e8815dd 100755 --- a/src/vine-event-loop-epoll.cpp +++ b/src/vine-event-loop-epoll.cpp @@ -179,10 +179,11 @@ void vine_event_queue_epoll_destroy(vine_event_queue_h event_queue) delete event_queue_handle; } -void vine_event_loop_epoll_get_eventfd(vine_event_queue_h event_queue, int *eventfd) +int vine_event_loop_epoll_get_eventfd(vine_event_queue_h event_queue, int *eventfd) { vine_epoll_event_queue_s *event_queue_handle = (vine_epoll_event_queue_s *)event_queue; *eventfd = event_queue_handle->fd; + return VINE_ERROR_NONE; } static void _add_io_event_handler(int fd, vine_epoll_io_event_handler *h) diff --git a/src/vine-event-loop-glib.cpp b/src/vine-event-loop-glib.cpp index eafea33..390eb51 100755 --- a/src/vine-event-loop-glib.cpp +++ b/src/vine-event-loop-glib.cpp @@ -69,8 +69,9 @@ void vine_event_queue_glib_destroy(vine_event_queue_h event_queue) { } -void vine_event_loop_glib_get_eventfd(vine_event_queue_h event_queue, int *eventfd) +int vine_event_loop_glib_get_eventfd(vine_event_queue_h event_queue, int *eventfd) { + return VINE_ERROR_NOT_SUPPORTED; } static void _add_io_event_handler(int fd, vine_glib_io_event_handler *h) diff --git a/src/vine-event-loop.cpp b/src/vine-event-loop.cpp index 84dae68..950edf0 100755 --- a/src/vine-event-loop.cpp +++ b/src/vine-event-loop.cpp @@ -90,9 +90,9 @@ void vine_event_queue_destroy(vine_event_queue_h event_queue) __event_loop[__event_loop_type].event_queue_destroy(event_queue); } -void vine_event_loop_get_eventfd(vine_event_queue_h event_queue, int *eventfd) +int vine_event_loop_get_eventfd(vine_event_queue_h event_queue, int *eventfd) { - __event_loop[__event_loop_type].get_eventfd(event_queue, eventfd); + return __event_loop[__event_loop_type].get_eventfd(event_queue, eventfd); } int vine_event_loop_add_io_handler( diff --git a/src/vine-session.cpp b/src/vine-session.cpp index 599a349..6ca5d53 100755 --- a/src/vine-session.cpp +++ b/src/vine-session.cpp @@ -166,8 +166,11 @@ int _vine_session_unset_discovered_cb(vine_session_h session) static bool __check_disc_method(vine_discovery_method_e method) { - return method >= VINE_DISCOVERY_METHOD_DNS_SD - && method <= VINE_DISCOVERY_METHOD_BLE; + bool ret = (method == VINE_DISCOVERY_METHOD_DNS_SD); +#ifdef BT_SUPPORT + ret = ret || (method == VINE_DISCOVERY_METHOD_BLE); +#endif + return ret; } int _vine_session_set_discovery_method(vine_session_h session, vine_discovery_method_e method) @@ -399,6 +402,8 @@ int _vine_session_set_ip_resolved_cb(vine_session_h session, int ret = VINE_ERROR_NONE; vine_session_s *s = (vine_session_s *)session; + RET_VAL_IF(s->disc_method == VINE_DISCOVERY_METHOD_BLE, VINE_ERROR_NOT_SUPPORTED, + "BLE discovery doesn't support vine_session_set_ip_resolved_cb()"); vine_disc_h disc_handle; ret = vine_disc_create(s->disc_method, &disc_handle); RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to vine_disc_create"); @@ -425,6 +430,10 @@ int _vine_session_unset_ip_resolved_cb(vine_session_h session, VINE_LOGD("Cancel resolving IP address for a service[%p]. session[%p]", service, session); + vine_session_s *s = (vine_session_s *)session; + RET_VAL_IF(s->disc_method == VINE_DISCOVERY_METHOD_BLE, VINE_ERROR_NOT_SUPPORTED, + "BLE discovery doesn't support vine_session_unset_ip_resolved_cb()"); + int ret = VINE_ERROR_NONE; vine_disc_h disc_handle = NULL; ret = _vine_service_get_disc_handle(service, VINE_DISCOVERY_METHOD_DNS_SD, &disc_handle); @@ -452,8 +461,7 @@ int _vine_session_get_event_fd(vine_session_h session, int *fd) RET_VAL_IF(session == NULL, VINE_ERROR_INVALID_PARAMETER, "session is NULL"); vine_session_s *s = (vine_session_s *)session; - vine_event_loop_get_eventfd(s->event_queue, fd); - return VINE_ERROR_NONE; + return vine_event_loop_get_eventfd(s->event_queue, fd); } int _vine_session_process_event(vine_session_h session) diff --git a/tool/tool_config.cpp b/tool/tool_config.cpp old mode 100644 new mode 100755 diff --git a/tool/tool_run.cpp b/tool/tool_run.cpp index db3952a..c76cadd 100755 --- a/tool/tool_run.cpp +++ b/tool/tool_run.cpp @@ -610,6 +610,7 @@ static void _event_handler(vine_session_h session) vine_session_process_event(session); } +#ifdef BT_SUPPORT static void _run_glib_event_loop() { GMainLoop *main_loop = g_main_loop_new(NULL, FALSE); @@ -618,6 +619,7 @@ static void _run_glib_event_loop() g_main_loop_unref(main_loop); } +#endif static void _run_epoll_event_loop(vine_session_h session) { int fd; @@ -658,9 +660,11 @@ static void _run_epoll_event_loop(vine_session_h session) static void run_event_loop(vine_session_h session) { +#ifdef BT_SUPPORT if (vine_configs.with_ble) _run_glib_event_loop(); else +#endif _run_epoll_event_loop(session); } -- 2.7.4 From 9c3b279bc48977de1c134da148aa2d1578a3bdae Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Fri, 2 Jul 2021 11:50:29 +0900 Subject: [PATCH 04/16] Add null check in discovered_cb Change-Id: I29a3e3044473ad3943131b91a4b2b896a0e15ace Signed-off-by: Cheoleun Moon --- src/vine-disc.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/vine-disc.cpp b/src/vine-disc.cpp index 01aa202..b0302b0 100755 --- a/src/vine-disc.cpp +++ b/src/vine-disc.cpp @@ -216,6 +216,9 @@ static void __discovered_cb(void *plugin_handle, bool available, const char *host_name, 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); @@ -246,6 +249,10 @@ 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); -- 2.7.4 From 733f2ff9c9feb90df21be4a2819fb99640e38835 Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Fri, 2 Jul 2021 14:38:32 +0900 Subject: [PATCH 05/16] vine-tool: Handle SIGINT for glib event loop Change-Id: I2c4d09f46595ee29a913b4954a5833bdebd8bbfe Signed-off-by: Cheoleun Moon --- tool/tool_main.cpp | 3 +-- tool/tool_run.cpp | 21 ++++++++++++++++++--- tool/tool_run.h | 1 + 3 files changed, 20 insertions(+), 5 deletions(-) mode change 100644 => 100755 tool/tool_main.cpp mode change 100644 => 100755 tool/tool_run.h diff --git a/tool/tool_main.cpp b/tool/tool_main.cpp old mode 100644 new mode 100755 index 72c47d6..87f055a --- a/tool/tool_main.cpp +++ b/tool/tool_main.cpp @@ -7,10 +7,9 @@ #include "tool_parse.h" #include "tool_run.h" -int interrupt_flag = 0; static void interrupt_handler(int signo) { - interrupt_flag = 1; + stop_event_loop(); } int main(int argc, char **argv) diff --git a/tool/tool_run.cpp b/tool/tool_run.cpp index c76cadd..384bcc1 100755 --- a/tool/tool_run.cpp +++ b/tool/tool_run.cpp @@ -25,7 +25,7 @@ #define MAX_EVENTS 10 #define MAX_READ_LEN 1024 -extern int interrupt_flag; +int interrupt_flag; static int epollfd = 0; static FILE *log_file = NULL; @@ -71,6 +71,10 @@ static int send_message(vine_dp_h dp); static void _stop_message_timer(vine_dp_h dp); static int joined_peer = 0; +#ifdef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB +static GMainLoop *main_loop = NULL; +#endif + static vine_dp_type_e _convert_dp_type(dp_type_t type) { switch (type) { @@ -610,16 +614,27 @@ static void _event_handler(vine_session_h session) vine_session_process_event(session); } -#ifdef BT_SUPPORT +#ifdef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB static void _run_glib_event_loop() { - GMainLoop *main_loop = g_main_loop_new(NULL, FALSE); + main_loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(main_loop); g_main_loop_unref(main_loop); } #endif + +void stop_event_loop() +{ +#ifdef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB + if (main_loop) + g_main_loop_quit(main_loop); +#else + interrupt_flag = 1; +#endif +} + static void _run_epoll_event_loop(vine_session_h session) { int fd; diff --git a/tool/tool_run.h b/tool/tool_run.h old mode 100644 new mode 100755 index a00b9e6..c038361 --- a/tool/tool_run.h +++ b/tool/tool_run.h @@ -1 +1,2 @@ int tool_run(); +void stop_event_loop(); -- 2.7.4 From 5076fd0b8a5250678534748b653d5f9522dbd030 Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Fri, 2 Jul 2021 15:40:53 +0900 Subject: [PATCH 06/16] Fix resource leak Change-Id: I29ed976a281773c75f8f1a5eaed108edcb09b4a3 Signed-off-by: Cheoleun Moon --- src/vine-disc.cpp | 20 ++++++++++++-------- tool/tool_run.cpp | 3 --- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/vine-disc.cpp b/src/vine-disc.cpp index b0302b0..9626153 100755 --- a/src/vine-disc.cpp +++ b/src/vine-disc.cpp @@ -239,10 +239,12 @@ static void __discovered_cb(void *plugin_handle, bool available, VINE_LOGD("Create a discovered_event[%p]", discovered_event); vine_disc_s *disc_handle = (vine_disc_s *)user_data; - if (disc_handle) - vine_event_loop_add_event(disc_handle->event_queue, discovered_event, - __invoke_discovered_user_cb, __free_discovered_event, - 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 __ble_discovered_cb(void *plugin_handle, bool available, @@ -267,10 +269,12 @@ static void __ble_discovered_cb(void *plugin_handle, bool available, VINE_LOGD("Create a discovered_event[%p]", discovered_event); vine_disc_s *disc_handle = (vine_disc_s *)user_data; - if (disc_handle) - vine_event_loop_add_event(disc_handle->event_queue, discovered_event, - __invoke_discovered_user_cb, __free_discovered_event, - 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, diff --git a/tool/tool_run.cpp b/tool/tool_run.cpp index 384bcc1..6c8445a 100755 --- a/tool/tool_run.cpp +++ b/tool/tool_run.cpp @@ -264,9 +264,6 @@ static void __ble_service_discovered(vine_session_h session, vine_service_h serv vine_service_state_e state, void *user_data) { printf("available[%d]\n", state); - vine_service_h s; - vine_service_clone(service, &s); - printf("Service discovered.\n"); char *service_type; -- 2.7.4 From 8199e3839bcb5aa386e18117e344236ecd6b49a1 Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Mon, 5 Jul 2021 17:02:17 +0900 Subject: [PATCH 07/16] ble disc: Do not set service_data Change-Id: I53ee0fc993a628c12a2028079641b3a588ec0271 Signed-off-by: Cheoleun Moon --- plugins/ble/ble-plugin.cpp | 12 +----------- src/vine-disc.cpp | 1 + 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/plugins/ble/ble-plugin.cpp b/plugins/ble/ble-plugin.cpp index 33f057b..4388042 100755 --- a/plugins/ble/ble-plugin.cpp +++ b/plugins/ble/ble-plugin.cpp @@ -207,17 +207,6 @@ static int __configure_advertiser(bt_advertiser_h adv, BT_ADAPTER_LE_PACKET_ADVERTISING, VINE_UUID); RET_VAL_IF(ret != BT_ERROR_NONE, ret, "bt_adapter_le_add_advertising_service_uuid() fails %d", ret); - // TODO: Determine which data should be set for service_data - // It should be set mandatorily? - // Or we don't have to set service_data if manufacturer data is set - char service_data[3] = {0x01, 0x02, 0x03}; - // TODO: ALso set for BT_ADAPTER_LE_PACKET_ADVERTISING? - ret = bt_adapter_le_add_advertising_service_data(adv, - BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, - VINE_UUID, service_data, sizeof(service_data)); - RET_VAL_IF(ret != BT_ERROR_NONE, ret, - "bt_adapter_le_add_advertising_service_data() fails %s(%d)", - __convert_ble_erro_to_str(ret), ret); // TODO: Also set for BT_ADAPTER_LE_PACKET_ADVERTISING? ret = bt_adapter_le_set_advertising_device_name(adv, @@ -355,6 +344,7 @@ static void __le_scan_result_cb(int result, bt_adapter_le_device_scan_result_inf char service_name[VINE_MAX_BLE_SERVICE_NAME_LEN + 1] = {0, }; int service_name_len = manufacturer_len - 1 - service_type_len; strncpy(service_name, manufacturer_data + service_type_len + 1, VINE_MAX_BLE_SERVICE_NAME_LEN); + service_name[service_name_len] = 0; char mac[VINE_MAC_LEN + 1] = {0, }; strncpy(mac, info->remote_address, VINE_MAC_LEN); diff --git a/src/vine-disc.cpp b/src/vine-disc.cpp index 9626153..b6ddf24 100755 --- a/src/vine-disc.cpp +++ b/src/vine-disc.cpp @@ -265,6 +265,7 @@ static void __ble_discovered_cb(void *plugin_handle, bool 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); -- 2.7.4 From 99a86f2a4eb517d71294f4e27328225bb01c24c6 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Fri, 2 Jul 2021 14:24:45 +0900 Subject: [PATCH 08/16] First draft for BLE GATT plugin Change-Id: I70065ea272a3fe63ca156188656112fce04333cc --- plugins/ble/gatt-plugin.cpp | 504 ++++++++++++++++++++++++++++++++++++ src/include/vine-data-path-plugin.h | 1 + 2 files changed, 505 insertions(+) create mode 100755 plugins/ble/gatt-plugin.cpp diff --git a/plugins/ble/gatt-plugin.cpp b/plugins/ble/gatt-plugin.cpp new file mode 100755 index 0000000..19898d0 --- /dev/null +++ b/plugins/ble/gatt-plugin.cpp @@ -0,0 +1,504 @@ +/* + * 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 "vine-data-path-plugin.h" +#include "vine-log.h" +#include "vine-utils.h" + +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_DESC_UUID "fa87c0d0-afac-11de-8a39-0800200c9a66" + +typedef enum { + VINE_GATT_ROLE_UNKNOWN = 0, + VINE_GATT_ROLE_SERVER, + VINE_GATT_ROLE_CLIENT, +} vine_gatt_role_e; + +typedef struct { + bt_gatt_h service; + bt_gatt_h characteristic; + bt_gatt_h descriptor; + + vine_gatt_role_e type; + union { + bt_gatt_server_h server; + bt_gatt_client_h client; + } role; + + char *remote_address; + bool is_accepted; + void *user; // vine_data_path_h +} vine_gatt_s; + +static vine_dp_plugin_callbacks g_callbacks = { + .pollfd_cb = NULL, + .opened_cb = NULL, + .accepted_cb = NULL, + .connected_cb = NULL, + .received_cb = NULL, + .written_cb = NULL, + .terminated_cb = NULL, +}; + +static vine_gatt_s *_create_gatt(void); + +static vine_data_path_error __convert_bt_error_to_data_path_error(int error) +{ + switch (error) { + case BT_ERROR_NONE: + return VINE_DATA_PATH_ERROR_NONE; + case BT_ERROR_OUT_OF_MEMORY: + return VINE_DATA_PATH_ERROR_OUT_OF_MEMORY; + case BT_ERROR_INVALID_PARAMETER: + return VINE_DATA_PATH_ERROR_INVALID_PARAMETER; + case BT_ERROR_OPERATION_FAILED: + default: + return VINE_DATA_PATH_ERROR_OPERATION_FAILED; + } +} + +static void __invoke_accepted_cb(const char *remote_address, vine_gatt_s *gatt, void *user_data) +{ + if (!g_callbacks.accepted_cb) + return; + + vine_gatt_s *accepted_gatt = _create_gatt(); + RET_IF(accepted_gatt == NULL, "Failed to create accepted_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->is_accepted = true; + accepted_gatt->user = user_data; + + g_callbacks.accepted_cb(VINE_DP_NOT_IP, accepted_gatt->remote_address, 0, accepted_gatt, user_data); +} + +static void __invoke_connected_cb(int result, void *user_data) +{ + if (!g_callbacks.connected_cb) + return; + g_callbacks.connected_cb(result, user_data); +} + +static void __invoke_terminated_cb(void *user_data) +{ + if (!g_callbacks.terminated_cb) + return; + g_callbacks.terminated_cb(user_data); +} + +// Server Callbacks +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. +} + +static void __gatt_server_write_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) +{ + VINE_LOGI("Got write value requestment from %s.", remote_address); + + // TODO: Send response. +} + +void __gatt_server_noti_state_changed_cb(bool notify, bt_gatt_server_h server, + bt_gatt_h gatt_handle, void *user_data) +{ + VINE_LOGI("Noti state changed. notify[%d] characteristic[%p]", notify, gatt_handle); +} + +// Client Callbacks +static void __gatt_client_service_changed_cb(bt_gatt_client_h client, + bt_gatt_client_service_change_type_e type, const char *uuid, void *user_data) +{ + VINE_LOGI("gatt[%p] service[%s] is %s", + type == BT_GATT_CLIENT_SERVICE_ADDED ? "added." : "removed." ); +} + +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"); + RET_VAL_IF(remote_address == NULL, + VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "remote_address is NULL"); + + bt_gatt_client_h client = NULL; + bt_gatt_h service = NULL; + bt_gatt_h characteristic = NULL; + int ret; + + ret = bt_gatt_client_create(remote_address, &client); + if (ret != BT_ERROR_NONE || !client) + return __convert_bt_error_to_data_path_error(ret); + + ret = bt_gatt_client_set_service_changed_cb(client, __gatt_client_service_changed_cb, gatt); + if (ret != BT_ERROR_NONE) + goto ERR; + + ret = bt_gatt_client_get_service(client, VINE_GATT_SERVICE_UUID, &service); + if (ret != BT_ERROR_NONE) + goto ERR; + + ret = bt_gatt_service_get_characteristic(service, VINE_GATT_CHAR_UUID, &characteristic); + if (ret != BT_ERROR_NONE) + goto ERR; + + gatt->role.client = client; + gatt->service = service; + gatt->characteristic = characteristic; + + VINE_LOGE("Succeeded to update GATT service info."); + return VINE_DATA_PATH_ERROR_NONE; + +ERR: + VINE_LOGE("Failed to update GATT service info."); + bt_gatt_client_destroy(client); + return __convert_bt_error_to_data_path_error(ret); +} + +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]", + gatt, result, connected, remote_address); + + if (!connected) { + __invoke_terminated_cb(gatt->user); + return; + } + + if (gatt->type == VINE_GATT_ROLE_SERVER) { + __invoke_accepted_cb(remote_address, gatt, gatt->user); + } 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; + } + __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)); + RET_VAL_IF(gatt == NULL, NULL, "Out of memory"); + + 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; + } + return gatt; +} + +static bt_gatt_h _add_gatt_characteristic(bt_gatt_h service, 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_NOTIFY; + + if (bt_gatt_characteristic_create(VINE_GATT_CHAR_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) + goto ERR; + + if (bt_gatt_server_set_write_value_requested_cb(characteristic, + __gatt_server_write_value_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) + goto ERR; + + if (bt_gatt_service_add_characteristic(service, characteristic) != BT_ERROR_NONE) + goto ERR; + + VINE_LOGI("Succeeded to add GATT characteristic."); + return characteristic; + +ERR: + bt_gatt_characteristic_destroy(characteristic); + return NULL; +} + +static bt_gatt_h _add_gatt_descriptor(bt_gatt_h characteristic) +{ + bt_gatt_h descriptor = NULL; + char initial_value[1] = {'0'}; // TODO: will be changed + int permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE; + + // TODO: Change UUID + if (bt_gatt_descriptor_create("2902", permissions, + initial_value, sizeof(initial_value), &descriptor) != BT_ERROR_NONE) + return NULL; + + if (bt_gatt_characteristic_add_descriptor(characteristic, descriptor) != BT_ERROR_NONE) { + bt_gatt_descriptor_destroy(descriptor); + return NULL; + } + return descriptor; +} + +int gatt_init(void) +{ + return VINE_DATA_PATH_ERROR_NONE; +} + +void gatt_deinit(void) +{ +} + +void gatt_register_callbacks(vine_dp_plugin_callbacks callbacks) +{ + g_callbacks = callbacks; +} + +void gatt_process_event(int gatt_fd, int events) +{ + // Do nothing. use g_main_loop. +} + +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"); + + vine_gatt_s *gatt = _create_gatt(); + RET_VAL_IF(gatt == NULL, VINE_DATA_PATH_ERROR_OUT_OF_MEMORY, "Out of memory"); + + gatt->user = user; + *handle = gatt; + + return VINE_DATA_PATH_ERROR_NONE; +} + +int gatt_destroy(vine_dp_plugin_h handle) +{ + RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL"); + + vine_gatt_s *gatt = (vine_gatt_s *)handle; + + if (gatt->type == VINE_GATT_ROLE_SERVER) { + bt_gatt_server_destroy(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); + } else if (gatt->type == VINE_GATT_ROLE_CLIENT) { + // bt_gatt_h handles will be freed during bt_gatt_client_destroy(). + bt_gatt_client_destroy(gatt->role.client); + gatt->role.client = NULL; + } + + gatt->service = NULL; + gatt->characteristic = NULL; + gatt->descriptor = NULL; + free(gatt->remote_address); + gatt->remote_address = NULL; + free(gatt); + + return VINE_DATA_PATH_ERROR_NONE; +} + +// All parameters except handle are not used in BT GATT. +int gatt_open(vine_dp_plugin_h handle, int addr_family, + int gatt_port, const char *iface_name, int max_conn, vine_dp_ssl ssl) // server only +{ + RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL"); + + 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; + int ret = BT_ERROR_OPERATION_FAILED; + + // This returns OPERATION_FAILED when already initialized. ignore it. + bt_gatt_server_initialize(); + + ret = bt_gatt_server_create(&server); + if (ret != BT_ERROR_NONE || !server) { + VINE_LOGE("Failed to create GATT server"); + goto ERR; + } + + ret = bt_gatt_service_create(VINE_GATT_SERVICE_UUID, BT_GATT_SERVICE_TYPE_PRIMARY, &service); + if (ret != BT_ERROR_NONE) { + VINE_LOGE("Failed to create service."); + goto ERR; + } + + characteristic = _add_gatt_characteristic(service, handle); + if (!characteristic) { + VINE_LOGE("Failed to add characteristc."); + goto ERR; + } + + descriptor = _add_gatt_descriptor(characteristic); + if (!characteristic) { + VINE_LOGE("Failed to add descriptor."); + goto ERR; + } + + 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(); + if (ret != BT_ERROR_NONE) { + VINE_LOGE("Failed to start GATT server."); + goto ERR; + } + + gatt->type = VINE_GATT_ROLE_SERVER; + gatt->role.server = server; + gatt->service = service; + gatt->characteristic = characteristic; + gatt->descriptor = descriptor; + + VINE_LOGI("Succeeded to start GATT server."); + return VINE_DATA_PATH_ERROR_NONE; + +ERR: + if (server) + 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); + 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) +{ + 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"); + + vine_gatt_s *gatt = (vine_gatt_s *)handle; + bt_gatt_client_h client = NULL; + int ret; + + ret = bt_gatt_connect(addr, false); + if (ret != BT_ERROR_NONE) { + VINE_LOGE("Failed to connect remote LE based service."); + return __convert_bt_error_to_data_path_error(ret); + } + + gatt->type = VINE_GATT_ROLE_CLIENT; + gatt->role.client = client; + gatt->remote_address = STRDUP(addr); + + VINE_LOGI("Succeed to request to GATT connect."); + return VINE_DATA_PATH_ERROR_NONE; +} + +int gatt_read(vine_dp_plugin_h handle, unsigned char *buf, size_t len) +{ + return VINE_DATA_PATH_ERROR_NONE; +} + +int gatt_write(vine_dp_plugin_h handle, unsigned char *buf, size_t len) +{ + RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL"); + RET_VAL_IF(buf == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "buf is NULL"); + RET_VAL_IF(len <= 0, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "len is less than 0"); + + // TODO + // vine_gatt_s *gatt = (vine_gatt_s *)handle; + + return VINE_DATA_PATH_ERROR_NONE; +} + +int gatt_close(vine_dp_plugin_h handle) +{ + return VINE_DATA_PATH_ERROR_NONE; +} + +int gatt_get_local_address_info(vine_dp_plugin_h handle, + int *addr_family, char local_ip[], int *port) +{ + return VINE_DATA_PATH_ERROR_NONE; +} + +int gatt_set_token(vine_dp_plugin_h handle, const char *token) +{ + return VINE_DATA_PATH_ERROR_NONE; +} + +int gatt_get_token(vine_dp_plugin_h handle, char **token) +{ + return VINE_DATA_PATH_ERROR_NONE; +} + +int gatt_set_host_name(vine_dp_plugin_h handle, const char *name) +{ + return VINE_DATA_PATH_ERROR_NONE; +} + +void vine_data_path_plugin_init(vine_dp_plugin_fn *fn) +{ + fn->init = gatt_init; + fn->deinit = gatt_deinit; + fn->register_callbacks = gatt_register_callbacks; + fn->process_event = gatt_process_event; + + fn->create = gatt_create; + fn->destroy = gatt_destroy; + fn->open = gatt_open; + fn->connect = gatt_connect; + fn->read = gatt_read; + fn->write = gatt_write; + fn->close = gatt_close; + + fn->get_local_address_info = gatt_get_local_address_info; + + fn->set_token = gatt_set_token; + fn->get_token = gatt_get_token; + fn->set_host_name = gatt_set_host_name; +} diff --git a/src/include/vine-data-path-plugin.h b/src/include/vine-data-path-plugin.h index 214d0d8..4a451d0 100755 --- a/src/include/vine-data-path-plugin.h +++ b/src/include/vine-data-path-plugin.h @@ -48,6 +48,7 @@ typedef enum { VINE_DP_IPV4_IPV6 = 0, // IPv6 has higer priority. VINE_DP_IPV4, VINE_DP_IPV6, + VINE_DP_NOT_IP } vine_dp_addr_family_e; typedef enum { -- 2.7.4 From 99174aea0dace47bcf4f4be517711c3976bfc5fc Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Mon, 5 Jul 2021 11:21:58 +0900 Subject: [PATCH 09/16] Seperate GATT from BLE plugin Change-Id: I341ad739a779a0d4659da478e6acf00d8c4a8d2c --- CMakeLists.txt | 1 + plugins/ble-gatt/CMakeLists.txt | 51 ++++++++++++++++++++++ .../ble-gatt-plugin.cpp} | 0 plugins/ble-gatt/ble-gatt-plugin.h | 18 ++++++++ 4 files changed, 70 insertions(+) create mode 100755 plugins/ble-gatt/CMakeLists.txt rename plugins/{ble/gatt-plugin.cpp => ble-gatt/ble-gatt-plugin.cpp} (100%) create mode 100755 plugins/ble-gatt/ble-gatt-plugin.h diff --git a/CMakeLists.txt b/CMakeLists.txt index eae5055..a6834a7 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,6 +127,7 @@ ENDIF(USE_LIBWEBSOCKETS) ADD_SUBDIRECTORY(plugins/dns-sd) IF(BT_SUPPORT) ADD_SUBDIRECTORY(plugins/ble) + ADD_SUBDIRECTORY(plugins/ble-gatt) ENDIF(BT_SUPPORT) ADD_SUBDIRECTORY(include) diff --git a/plugins/ble-gatt/CMakeLists.txt b/plugins/ble-gatt/CMakeLists.txt new file mode 100755 index 0000000..977029e --- /dev/null +++ b/plugins/ble-gatt/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 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. +# + +SET(BLE_GATT_PLUGIN "vine-plugin-ble-gatt") + +SET(BLE_GATT_PLUGIN_VERSION_MAJOR "1") +SET(BLE_GATT_PLUGIN_VERSION_MINOR "0") +SET(BLE_GATT_PLUGIN_VERSION_PATCH "0") +SET(BLE_GATT_PLUGIN_VERSION ${BLE_GATT_PLUGIN_VERSION_MAJOR}.${BLE_GATT_PLUGIN_VERSION_MINOR}.${BLE_GATT_PLUGIN_VERSION_PATCH}) + +PKG_CHECK_MODULES(BLE_DEPS REQUIRED "capi-network-bluetooth") + +INCLUDE_DIRECTORIES( + ${VINE_PATH}/include + ${VINE_LOGGER_PATH} + ${CMAKE_CURRENT_SOURCE_DIR} + ${${fw_name}_INCLUDE_DIRS} + ${BLE_DEPS_INCLUDE_DIRS} +) + +FILE(GLOB VINE_BLE_GATT_PLUGIN_SOURCES *.cpp) + +ADD_DEFINITIONS("-fvisibility=default") +ADD_LIBRARY(${BLE_GATT_PLUGIN} SHARED ${VINE_BLE_GATT_PLUGIN_SOURCES}) + +SET_TARGET_PROPERTIES( + ${BLE_GATT_PLUGIN} + PROPERTIES + SOVERSION ${BLE_GATT_PLUGIN_VERSION_MAJOR} +) + +TARGET_LINK_LIBRARIES(${BLE_GATT_PLUGIN} + ${VINE_LOGGER} + ${BLE_DEPS_LIBRARIES} + ${fw_name_deps_LIBRARIES} + dl +) + +INSTALL(TARGETS ${BLE_GATT_PLUGIN} DESTINATION "${LIB_DIR}") diff --git a/plugins/ble/gatt-plugin.cpp b/plugins/ble-gatt/ble-gatt-plugin.cpp similarity index 100% rename from plugins/ble/gatt-plugin.cpp rename to plugins/ble-gatt/ble-gatt-plugin.cpp diff --git a/plugins/ble-gatt/ble-gatt-plugin.h b/plugins/ble-gatt/ble-gatt-plugin.h new file mode 100755 index 0000000..d1766f0 --- /dev/null +++ b/plugins/ble-gatt/ble-gatt-plugin.h @@ -0,0 +1,18 @@ +/* + * 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 -- 2.7.4 From 0c41ab9a379dc3269b628794a477228153b0198a Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Tue, 6 Jul 2021 19:11:22 +0900 Subject: [PATCH 10/16] Add new API to set DP method Change-Id: I92440476858e246d859bb31958e65e0bacff7330 --- include/vine.h | 28 ++++- plugins/ble-gatt/ble-gatt-plugin.cpp | 2 +- src/include/vine-data-path-plugin.h | 8 +- src/include/vine-data-path-state.h | 29 +++-- src/include/vine-data-path.h | 12 +- src/include/vine-dp.h | 7 ++ src/vine-data-path-state.cpp | 99 ++++++++-------- src/vine-data-path.cpp | 213 +++++++++++++++++++++++------------ src/vine-dp.cpp | 74 +++++++++++- src/vine.cpp | 8 ++ tests/unittest/vine-unittest-dp.cpp | 14 +++ tool/tool_run.cpp | 3 + 12 files changed, 350 insertions(+), 147 deletions(-) diff --git a/include/vine.h b/include/vine.h index aa9d10b..c9a663f 100755 --- a/include/vine.h +++ b/include/vine.h @@ -271,6 +271,16 @@ typedef enum { } vine_discovery_method_e; /** + * @brief Enumeration for data path method + * @since_tizen 6.5 + */ +typedef enum { + VINE_DP_METHOD_DEFAULT = 0, + VINE_DP_METHOD_BLE_GATT, + VINE_DP_METHOD_UNKNOWN +} vine_dp_method_e; + +/** * @brief Enumeration for address family * @since_tizen 6.5 */ @@ -868,6 +878,20 @@ int vine_dp_create(vine_session_h session, vine_dp_type_e type, vine_dp_h *dp); int vine_dp_destroy(vine_dp_h dp); /** + * @brief Sets the data path method + * @remarks Default method is websocket + * @since_tizen 6.5 + * @param[in] dp The data path handle + * @param[in] method The data path method + * @return 0 on success, otherwise a negative error value + * @retval #VINE_ERROR_NONE Successful + * @retval #VINE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #VINE_ERROR_NOT_SUPPORTED Not supported + * @see vine_dp_create() + */ +int vine_dp_set_method(vine_dp_h dp, vine_dp_method_e method); + +/** * @brief Gets the Id for DP_TYPE_PUBSUB. * @remarks This should be called after completing vine_dp_open() * @since_tizen 6.5 @@ -1153,7 +1177,9 @@ typedef void (*vine_dp_opened_cb)(vine_dp_h dp, vine_error_e result, void *user_ /** * @brief Opens a datapath. - * @remarks This works depending on the type of datapath differently. + * @remarks This works depending on the type of datapath differently. \ + * If you want to open VINE_DP_SERVER with BLE GATT, \ + * BLE service should be registered before. * If @a dp is a server, a listen port is opened. * If @a dp is a client, it tries to connect to a server. * If @a dp is for Publish-Subscribe, it joins to a service which has the same topic. diff --git a/plugins/ble-gatt/ble-gatt-plugin.cpp b/plugins/ble-gatt/ble-gatt-plugin.cpp index 19898d0..dccb252 100755 --- a/plugins/ble-gatt/ble-gatt-plugin.cpp +++ b/plugins/ble-gatt/ble-gatt-plugin.cpp @@ -304,7 +304,7 @@ int gatt_create(vine_dp_plugin_h *handle, void *plugin_data, void *user) RET_VAL_IF(user == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "user is NULL"); vine_gatt_s *gatt = _create_gatt(); - RET_VAL_IF(gatt == NULL, VINE_DATA_PATH_ERROR_OUT_OF_MEMORY, "Out of memory"); + RET_VAL_IF(gatt == NULL, VINE_DATA_PATH_ERROR_OPERATION_FAILED, "Failed to create GATT handle"); gatt->user = user; *handle = gatt; diff --git a/src/include/vine-data-path-plugin.h b/src/include/vine-data-path-plugin.h index 4a451d0..e74ad5c 100755 --- a/src/include/vine-data-path-plugin.h +++ b/src/include/vine-data-path-plugin.h @@ -17,12 +17,8 @@ #ifndef __VINE_DATA_PATH_PLUGIN_H__ #define __VINE_DATA_PATH_PLUGIN_H__ -#ifdef USE_LIBWEBSOCKETS -#define LIBWEBSOCKETS_PLUGIN_PATH "libvine-plugin-libwebsockets.so" -#define DATA_PATH_PLUGIN_PATH LIBWEBSOCKETS_PLUGIN_PATH -#else -#define DATA_PATH_PLUGIN_PATH "" -#endif +#define LWS_PLUGIN_PATH "libvine-plugin-libwebsockets.so" +#define BLE_GATT_PLUGIN_PATH "libvine-plugin-ble-gatt.so" #define VINE_DATA_PATH_MAX_BUFFER_SIZE 131072 // 128 * 1024 bytes diff --git a/src/include/vine-data-path-state.h b/src/include/vine-data-path-state.h index 4147ecb..7ac17ba 100644 --- a/src/include/vine-data-path-state.h +++ b/src/include/vine-data-path-state.h @@ -34,7 +34,7 @@ typedef void *vine_data_path_h; class VineDataPathState { public: - VineDataPathState(vine_data_path_h dp, vine_dp_plugin_h plugin); + VineDataPathState(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn); virtual ~VineDataPathState(); virtual void enter() = 0; @@ -51,13 +51,14 @@ public: protected: vine_data_path_h __dp; vine_dp_plugin_h __plugin; + vine_dp_plugin_fn __fn; }; // Vine Datapath is in the VineDefaultState when initialized class VineDefaultState : public VineDataPathState { public: - VineDefaultState(vine_data_path_h dp, vine_dp_plugin_h plugin); + VineDefaultState(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn); ~VineDefaultState(); void enter(); @@ -78,7 +79,7 @@ public: class VineAcceptedState : public VineDataPathState { public: - VineAcceptedState(vine_data_path_h dp, vine_dp_plugin_h plugin); + VineAcceptedState(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn); ~VineAcceptedState(); void enter(); @@ -107,7 +108,7 @@ private: class VineConnectedState : public VineDataPathState { public: - VineConnectedState(vine_data_path_h dp, vine_dp_plugin_h plugin); + VineConnectedState(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn); ~VineConnectedState(); void enter(); @@ -143,7 +144,7 @@ private: class VineAuthRequestedState : public VineDataPathState { public: - VineAuthRequestedState(vine_data_path_h dp, vine_dp_plugin_h plugin); + VineAuthRequestedState(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn); ~VineAuthRequestedState(); void enter(); @@ -178,7 +179,7 @@ private: class VineAuthRespondedState : public VineDataPathState { public: - VineAuthRespondedState(vine_data_path_h dp, vine_dp_plugin_h plugin); + VineAuthRespondedState(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn); ~VineAuthRespondedState(); void enter(); @@ -207,7 +208,7 @@ private: class VineAuthFailedState : public VineDataPathState { public: - VineAuthFailedState(vine_data_path_h dp, vine_dp_plugin_h plugin); + VineAuthFailedState(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn); ~VineAuthFailedState(); void enter(); @@ -226,7 +227,7 @@ public: class VineEstablishedState : public VineDataPathState { public: - VineEstablishedState(vine_data_path_h dp, vine_dp_plugin_h plugin); + VineEstablishedState(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn); ~VineEstablishedState(); void enter(); @@ -248,7 +249,11 @@ void vine_dp_state_set_state_changed_notifier(state_changed_notifier notifier); void vine_dp_state_set_established_notifier(established_notifier notifier); void vine_dp_state_set_data_received_notifier(data_received_notifier notifier); -VineDataPathState *vine_get_default_state(vine_data_path_h dp, vine_dp_plugin_h plugin); -void start_default_state(vine_data_path_h dp, vine_dp_plugin_h plugin, VineDataPathState *state); -void start_connected_state(vine_data_path_h dp, vine_dp_plugin_h plugin, VineDataPathState *state); -void start_accepted_state(vine_data_path_h dp, vine_dp_plugin_h plugin, VineDataPathState *state); +VineDataPathState *vine_get_default_state(vine_data_path_h dp, + vine_dp_plugin_h plugin, vine_dp_plugin_fn fn); +void start_default_state(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn, + VineDataPathState *state); +void start_connected_state(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn, + VineDataPathState *state); +void start_accepted_state(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn, + VineDataPathState *state); diff --git a/src/include/vine-data-path.h b/src/include/vine-data-path.h index 8a64d34..775cb21 100755 --- a/src/include/vine-data-path.h +++ b/src/include/vine-data-path.h @@ -18,6 +18,7 @@ #define __VINE_DATA_PATH_H__ #include "vine.h" +#include "vine-data-path.h" #include "vine-data-path-state.h" #include "vine-event-loop.h" @@ -31,18 +32,25 @@ typedef void (*vine_data_path_accepted_cb)(vine_data_path_h datapath, void *user typedef void (*vine_data_path_connected_cb)(vine_data_path_h datapath, int result, void *user_data); typedef void (*vine_data_path_terminated_cb)(vine_data_path_h datapath, void *user_data); +typedef enum { + VINE_DATA_PATH_METHOD_LWS = 0, // default + VINE_DATA_PATH_METHOD_BLE_GATT, + VINE_DATA_PATH_METHOD_UNKNOWN +} vine_data_path_method_e; int vine_data_path_init(void); int vine_data_path_deinit(void); -int vine_data_path_open(vine_address_family_e addr_family, int port, +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_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, vine_event_queue_h event_queue); -int vine_data_path_connect(vine_address_family_e addr_family, +int vine_data_path_connect(vine_data_path_method_e method, + vine_address_family_e addr_family, const char *ip, int port, const char *iface_name, vine_security_h security, const char *host_name, const char *token, vine_data_path_connected_cb callback, void *user_data, diff --git a/src/include/vine-dp.h b/src/include/vine-dp.h index eb7eb43..498aefd 100644 --- a/src/include/vine-dp.h +++ b/src/include/vine-dp.h @@ -47,6 +47,7 @@ public: virtual int send(unsigned char *buf, size_t len) = 0; virtual int recv(unsigned char *buf, size_t buf_len, size_t *read_len) = 0; + virtual int set_method(vine_dp_method_e method) = 0; virtual int get_id(char **id) = 0; virtual int set_addr_family(vine_address_family_e addr_family) = 0; virtual int set_remote_ip(vine_address_family_e, const std::string &ip) = 0; @@ -80,6 +81,8 @@ public: void invoke_received_cb(size_t received_len); protected: + vine_data_path_method_e mMethod; + void *mEventQueue; void *mSecurity; std::string mIfaceName; @@ -105,6 +108,7 @@ public: virtual int send(unsigned char *buf, size_t len); virtual int recv(unsigned char *buf, size_t buf_len, size_t *read_len); + virtual int set_method(vine_dp_method_e method); virtual int get_id(char **id); virtual int set_addr_family(vine_address_family_e addr_family); virtual int set_remote_ip(vine_address_family_e, const std::string &ip); @@ -149,6 +153,7 @@ public: virtual int send(unsigned char *buf, size_t len); virtual int recv(unsigned char *buf, size_t buf_len, size_t *read_len); + virtual int set_method(vine_dp_method_e method); virtual int get_id(char **id); virtual int set_addr_family(vine_address_family_e addr_family); virtual int set_remote_ip(vine_address_family_e, const std::string &ip); @@ -203,6 +208,7 @@ public: virtual int send(unsigned char *buf, size_t len); virtual int recv(unsigned char *buf, size_t buf_len, size_t *read_len); + virtual int set_method(vine_dp_method_e method); virtual int get_id(char **id); virtual int set_addr_family(vine_address_family_e addr_family); virtual int set_remote_ip(vine_address_family_e, const std::string &ip); @@ -277,6 +283,7 @@ private: int _vine_dp_create(vine_session_h session, vine_dp_type_e type, vine_dp_h *dp); int _vine_dp_destroy(vine_dp_h dp); +int _vine_dp_set_method(vine_dp_h dp, vine_dp_method_e method); int _vine_dp_get_id(vine_dp_h dp, char **id); int _vine_dp_set_iface_name(vine_dp_h dp, const char *iface_name); int _vine_dp_set_addr_family(vine_dp_h dp, vine_address_family_e addr_family); diff --git a/src/vine-data-path-state.cpp b/src/vine-data-path-state.cpp index 2c62af2..c7f1bf7 100644 --- a/src/vine-data-path-state.cpp +++ b/src/vine-data-path-state.cpp @@ -22,8 +22,6 @@ #include "vine-log.h" #include "vine-utils.h" -extern vine_dp_plugin_fn g_dp_plugin_fn; - static state_changed_notifier __set_state; static established_notifier __established; static data_received_notifier __data_received; @@ -37,15 +35,17 @@ static void state_transition(vine_data_path_h dp, new_state->enter(); } -VineDataPathState::VineDataPathState(vine_data_path_h dp, vine_dp_plugin_h plugin) - : __dp(dp), __plugin(plugin) +VineDataPathState::VineDataPathState(vine_data_path_h dp, + vine_dp_plugin_h plugin, vine_dp_plugin_fn fn) + : __dp(dp), __plugin(plugin), __fn(fn) {} VineDataPathState::~VineDataPathState() {} -VineDefaultState::VineDefaultState(vine_data_path_h dp, vine_dp_plugin_h plugin) - : VineDataPathState(dp, plugin) +VineDefaultState::VineDefaultState(vine_data_path_h dp, + vine_dp_plugin_h plugin, vine_dp_plugin_fn fn) + : VineDataPathState(dp, plugin, fn) { } @@ -78,8 +78,9 @@ void VineDefaultState::received_cb(size_t bytes) void VineDefaultState::written_cb(size_t bytes) {} -VineAcceptedState::VineAcceptedState(vine_data_path_h dp, vine_dp_plugin_h plugin) - : VineDataPathState(dp, plugin), __sent_frame(0), __accept(0) +VineAcceptedState::VineAcceptedState(vine_data_path_h dp, + vine_dp_plugin_h plugin, vine_dp_plugin_fn fn) + : VineDataPathState(dp, plugin, fn), __sent_frame(0), __accept(0) { } @@ -142,13 +143,13 @@ void VineAcceptedState::written_cb(size_t bytes) VINE_LOGD("+"); switch (__sent_frame) { case AUTH_OP_REQUEST: - state_transition(__dp, this, new VineAuthRequestedState(__dp, __plugin)); + state_transition(__dp, this, new VineAuthRequestedState(__dp, __plugin, __fn)); break; case AUTH_OP_CONFIRM: if (__accept == 1) - state_transition(__dp, this, new VineEstablishedState(__dp, __plugin)); + state_transition(__dp, this, new VineEstablishedState(__dp, __plugin, __fn)); else - state_transition(__dp, this, new VineAuthFailedState(__dp, __plugin)); + state_transition(__dp, this, new VineAuthFailedState(__dp, __plugin, __fn)); break; default: VINE_LOGE("Invalid Frame %d", __sent_frame); @@ -158,7 +159,7 @@ void VineAcceptedState::written_cb(size_t bytes) void VineAcceptedState::handle_failure(std::string msg) { VINE_LOGE("Failure %s", msg.c_str()); - state_transition(__dp, this, new VineAuthFailedState(__dp, __plugin)); + state_transition(__dp, this, new VineAuthFailedState(__dp, __plugin, __fn)); } void VineAcceptedState::send_auth_request() @@ -175,7 +176,7 @@ void VineAcceptedState::send_auth_request() return; } - g_dp_plugin_fn.write(__plugin, frame, size); + __fn.write(__plugin, frame, size); release_auth_frame(frame); } @@ -195,12 +196,13 @@ void VineAcceptedState::send_auth_confirm(int accept) return; } - g_dp_plugin_fn.write(__plugin, frame, size); + __fn.write(__plugin, frame, size); release_auth_frame(frame); } -VineConnectedState::VineConnectedState(vine_data_path_h dp, vine_dp_plugin_h plugin) - : VineDataPathState(dp, plugin), __sent_frame(0) +VineConnectedState::VineConnectedState(vine_data_path_h dp, + vine_dp_plugin_h plugin, vine_dp_plugin_fn fn) + : VineDataPathState(dp, plugin, fn), __sent_frame(0) { } @@ -248,7 +250,7 @@ void VineConnectedState::written_cb(size_t bytes) VINE_LOGD("+"); switch (__sent_frame) { case AUTH_OP_RESPONSE: - state_transition(__dp, this, new VineAuthRespondedState(__dp, __plugin)); + state_transition(__dp, this, new VineAuthRespondedState(__dp, __plugin, __fn)); break; default: VINE_LOGE("Invalid Frame %d", __sent_frame); @@ -258,13 +260,13 @@ void VineConnectedState::written_cb(size_t bytes) void VineConnectedState::handle_failure(std::string msg) { VINE_LOGE("Failure %s", msg.c_str()); - state_transition(__dp, this, new VineAuthFailedState(__dp, __plugin)); + state_transition(__dp, this, new VineAuthFailedState(__dp, __plugin, __fn)); } void VineConnectedState::read_data(size_t bytes) { unsigned char *buf = (unsigned char *)malloc(bytes); - size_t read_size = g_dp_plugin_fn.read(__plugin, buf, bytes); + size_t read_size = __fn.read(__plugin, buf, bytes); if (bytes != read_size) { // TODO: Check it handle_failure("Wrong size"); @@ -345,7 +347,7 @@ void VineConnectedState::recv_auth_confirm(unsigned char ver, return; } - state_transition(__dp, this, new VineEstablishedState(__dp, __plugin)); + state_transition(__dp, this, new VineEstablishedState(__dp, __plugin, __fn)); } void VineConnectedState::send_auth_response() @@ -369,15 +371,16 @@ void VineConnectedState::send_auth_response() return; } - g_dp_plugin_fn.write(__plugin, frame, size); + __fn.write(__plugin, frame, size); release_auth_frame(frame); free(psk); __sent_frame = AUTH_OP_RESPONSE; } -VineAuthRequestedState::VineAuthRequestedState(vine_data_path_h dp, vine_dp_plugin_h plugin) - : VineDataPathState(dp, plugin), __sent_frame(0), __accept(0) +VineAuthRequestedState::VineAuthRequestedState(vine_data_path_h dp, + vine_dp_plugin_h plugin, vine_dp_plugin_fn fn) + : VineDataPathState(dp, plugin, fn), __sent_frame(0), __accept(0) { } @@ -423,7 +426,7 @@ void VineAuthRequestedState::written_cb(size_t bytes) switch (__sent_frame) { case AUTH_OP_CONFIRM: if (__accept == 1) - state_transition(__dp, this, new VineEstablishedState(__dp, __plugin)); + state_transition(__dp, this, new VineEstablishedState(__dp, __plugin, __fn)); else handle_failure("Not Accepted"); break; @@ -435,13 +438,13 @@ void VineAuthRequestedState::written_cb(size_t bytes) void VineAuthRequestedState::handle_failure(std::string msg) { VINE_LOGE("Failure %s", msg.c_str()); - state_transition(__dp, this, new VineAuthFailedState(__dp, __plugin)); + state_transition(__dp, this, new VineAuthFailedState(__dp, __plugin, __fn)); } void VineAuthRequestedState::read_data(size_t bytes) { unsigned char *buf = (unsigned char *)malloc(bytes); - size_t read_size = g_dp_plugin_fn.read(__plugin, buf, bytes); + size_t read_size = __fn.read(__plugin, buf, bytes); if (bytes != read_size) { // TODO: Check it @@ -533,15 +536,16 @@ void VineAuthRequestedState::send_auth_confirm(int accept) return; } - g_dp_plugin_fn.write(__plugin, frame, size); + __fn.write(__plugin, frame, size); release_auth_frame(frame); __sent_frame = AUTH_OP_CONFIRM; __accept = accept; } -VineAuthRespondedState::VineAuthRespondedState(vine_data_path_h dp, vine_dp_plugin_h plugin) - : VineDataPathState(dp, plugin) +VineAuthRespondedState::VineAuthRespondedState(vine_data_path_h dp, + vine_dp_plugin_h plugin, vine_dp_plugin_fn fn) + : VineDataPathState(dp, plugin, fn) { } @@ -589,13 +593,13 @@ void VineAuthRespondedState::written_cb(size_t bytes) void VineAuthRespondedState::handle_failure(std::string msg) { VINE_LOGE("Failure %s", msg.c_str()); - state_transition(__dp, this, new VineAuthFailedState(__dp, __plugin)); + state_transition(__dp, this, new VineAuthFailedState(__dp, __plugin, __fn)); } void VineAuthRespondedState::read_data(size_t bytes) { unsigned char *buf = (unsigned char *)malloc(bytes); - size_t read_size = g_dp_plugin_fn.read(__plugin, buf, bytes); + size_t read_size = __fn.read(__plugin, buf, bytes); if (bytes != read_size) { // TODO: Check it @@ -646,11 +650,12 @@ void VineAuthRespondedState::recv_auth_confirm(unsigned char ver, } __timer.stop(); - state_transition(__dp, this, new VineEstablishedState(__dp, __plugin)); + state_transition(__dp, this, new VineEstablishedState(__dp, __plugin, __fn)); } -VineAuthFailedState::VineAuthFailedState(vine_data_path_h dp, vine_dp_plugin_h plugin) - : VineDataPathState(dp, plugin) +VineAuthFailedState::VineAuthFailedState(vine_data_path_h dp, + vine_dp_plugin_h plugin, vine_dp_plugin_fn fn) + : VineDataPathState(dp, plugin, fn) { } @@ -687,8 +692,9 @@ void VineAuthFailedState::written_cb(size_t bytes) VINE_LOGD("+"); } -VineEstablishedState::VineEstablishedState(vine_data_path_h dp, vine_dp_plugin_h plugin) - : VineDataPathState(dp, plugin) +VineEstablishedState::VineEstablishedState(vine_data_path_h dp, + vine_dp_plugin_h plugin, vine_dp_plugin_fn fn) + : VineDataPathState(dp, plugin, fn) { } @@ -708,14 +714,14 @@ void VineEstablishedState::exit() int VineEstablishedState::read(unsigned char *buf, size_t buf_len, size_t *read_len) { - size_t bytes = g_dp_plugin_fn.read(__plugin, buf, buf_len); + size_t bytes = __fn.read(__plugin, buf, buf_len); *read_len = bytes; return VINE_ERROR_NONE; } int VineEstablishedState::write(unsigned char *buf, size_t len) { - g_dp_plugin_fn.write(__plugin, buf, len); + __fn.write(__plugin, buf, len); return VINE_ERROR_NONE; } @@ -748,28 +754,29 @@ void vine_dp_state_set_data_received_notifier(data_received_notifier notifier) __data_received = notifier; } -VineDataPathState *vine_get_default_state(vine_data_path_h dp, vine_dp_plugin_h plugin) +VineDataPathState *vine_get_default_state(vine_data_path_h dp, + vine_dp_plugin_h plugin, vine_dp_plugin_fn fn) { - return new VineDefaultState(dp, plugin); + return new VineDefaultState(dp, plugin, fn); } -void start_default_state(vine_data_path_h dp, vine_dp_plugin_h plugin, +void start_default_state(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn, VineDataPathState *state) { VINE_LOGD("Default"); - state_transition(dp, state, new VineDefaultState(dp, plugin)); + state_transition(dp, state, new VineDefaultState(dp, plugin, fn)); } -void start_connected_state(vine_data_path_h dp, vine_dp_plugin_h plugin, +void start_connected_state(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn, VineDataPathState *state) { VINE_LOGD("Connected"); - state_transition(dp, state, new VineConnectedState(dp, plugin)); + state_transition(dp, state, new VineConnectedState(dp, plugin, fn)); } -void start_accepted_state(vine_data_path_h dp, vine_dp_plugin_h plugin, +void start_accepted_state(vine_data_path_h dp, vine_dp_plugin_h plugin, vine_dp_plugin_fn fn, VineDataPathState *state) { VINE_LOGD("Accepted"); - state_transition(dp, state, new VineAcceptedState(dp, plugin)); + state_transition(dp, state, new VineAcceptedState(dp, plugin, fn)); } diff --git a/src/vine-data-path.cpp b/src/vine-data-path.cpp index 6360779..e2fa7f5 100755 --- a/src/vine-data-path.cpp +++ b/src/vine-data-path.cpp @@ -25,7 +25,34 @@ #include "vine-log.h" #include "vine-utils.h" +static struct { + const char *name; + const char *path; +} __vine_data_path_plugins_info[] = { + [VINE_DATA_PATH_METHOD_LWS] = {"Websocket", LWS_PLUGIN_PATH}, +#ifdef BT_SUPPORT + [VINE_DATA_PATH_METHOD_BLE_GATT] = {"BLE GATT", BLE_GATT_PLUGIN_PATH}, +#endif + {NULL, NULL}, +}; + +struct { + vine_dp_plugin_fn fn; + vine_dp_plugin_callbacks callbacks; + void (*init)(vine_dp_plugin_fn *fn); +} __vine_data_path_plugins[] = { + {{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}, + {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 { + vine_data_path_method_e method; + vine_dp_plugin_fn *plugin_fn; + vine_address_family_e addr_family; char *addr; int port; @@ -68,31 +95,8 @@ typedef struct { vine_data_path_s *connected_dp; } vine_dp_accepted_event; -vine_dp_plugin_fn g_dp_plugin_fn = { - .init = NULL, - .deinit = NULL, - .register_callbacks = NULL, - .process_event = NULL, - .create = NULL, - .destroy = NULL, - .open = NULL, - .connect = NULL, - .read = NULL, - .write = NULL -}; - -static vine_dp_plugin_callbacks g_dp_plugin_cbs = { - .pollfd_cb = NULL, - .opened_cb = NULL, - .accepted_cb = NULL, - .connected_cb = NULL, - .received_cb = NULL, - .written_cb = NULL, - .terminated_cb = NULL, -}; - -static void (*__init_plugin)(vine_dp_plugin_fn *fn); -static vine_data_path_s *_vine_data_path_create(vine_address_family_e addr_family, +static vine_data_path_s *_vine_data_path_create(vine_data_path_method_e method, + vine_address_family_e addr_family, const char *addr, int port, vine_security_h security, void *plugin_data, vine_event_queue_h event_queue); @@ -136,7 +140,10 @@ static vine_error_e __convert_address_family(vine_address_family_e addr_family, void __vine_dp_poll_handler(int fd, int events, void *user_data) { - g_dp_plugin_fn.process_event(fd, events); + // TODO: Only LWS plugin supports polling functions. + // But, we need to modify pollfd_cb to pass datapath handle as the user_data + if (__vine_data_path_plugins[VINE_DATA_PATH_METHOD_LWS].fn.process_event) + __vine_data_path_plugins[VINE_DATA_PATH_METHOD_LWS].fn.process_event(fd, events); } void __vine_dp_op_handler(int fd, int events, void *user_data) @@ -148,7 +155,10 @@ void __vine_dp_op_handler(int fd, int events, void *user_data) VINE_LOGE("Read error(%d)", errno); return; } - g_dp_plugin_fn.process_event(fd, events); + // TODO: Only LWS plugin supports polling functions. + // But, we need to modify pollfd_cb to pass datapath handle as the user_data + if (__vine_data_path_plugins[VINE_DATA_PATH_METHOD_LWS].fn.process_event) + __vine_data_path_plugins[VINE_DATA_PATH_METHOD_LWS].fn.process_event(fd, events); } static void __pollfd_cb(vine_data_path_pollfd_op_e op, int fd, int events) @@ -261,8 +271,10 @@ static vine_address_family_e __convert_addr_family(vine_dp_addr_family_e addr_fa return VINE_ADDRESS_FAMILY_IPV4; case VINE_DP_IPV6: return VINE_ADDRESS_FAMILY_IPV6; + case VINE_DP_NOT_IP: + default: + return VINE_ADDRESS_FAMILY_DEFAULT; } - return VINE_ADDRESS_FAMILY_DEFAULT; } static void __accepted_cb(vine_dp_addr_family_e addr_family, char *addr, @@ -273,7 +285,8 @@ static void __accepted_cb(vine_dp_addr_family_e addr_family, char *addr, vine_data_path_s *listen_dp = (vine_data_path_s *)user_data; VINE_LOGE("listen_dp[%p], security[%p]", listen_dp, listen_dp->security); - vine_data_path_s *connected_dp = _vine_data_path_create(__convert_addr_family(addr_family), + vine_data_path_s *connected_dp = _vine_data_path_create(listen_dp->method, + __convert_addr_family(addr_family), addr, port, listen_dp->security, plugin_data, listen_dp->event_queue); RET_IF(connected_dp == NULL, "Out of memory"); @@ -282,7 +295,8 @@ static void __accepted_cb(vine_dp_addr_family_e addr_family, char *addr, VINE_LOGD("Start Authentication"); connected_dp->established = notify_accepted; - start_accepted_state(connected_dp, connected_dp->plugin_handle, connected_dp->state); + start_accepted_state(connected_dp, connected_dp->plugin_handle, *connected_dp->plugin_fn, + connected_dp->state); } static void __invoke_connected_user_cb(void *event, void *user_data) @@ -328,7 +342,7 @@ static void __connected_cb(int result, void *user_data) VINE_LOGD("Start Authentication"); dp->established = notify_connected; - start_connected_state(dp, dp->plugin_handle, dp->state); + start_connected_state(dp, dp->plugin_handle, *dp->plugin_fn, dp->state); } static void __invoke_received_user_cb(void *event, void *user_data) @@ -385,7 +399,7 @@ static void __invoke_terminated_user_cb(void *event, void *user_data) VINE_LOGD("user callback is invoked by event queue."); - start_default_state(dp, dp->plugin_handle, dp->state); + start_default_state(dp, dp->plugin_handle, *dp->plugin_fn, dp->state); if (dp->terminated_cb) dp->terminated_cb(dp, dp->terminated_cb_data); } @@ -400,17 +414,23 @@ static void __terminated_cb(void *user_data) static int _load_data_path_plugins(void) { - void *handle = dlopen(DATA_PATH_PLUGIN_PATH, RTLD_LAZY | RTLD_NODELETE); - if (handle) { - __init_plugin = (void (*)(vine_dp_plugin_fn *))dlsym(handle, "vine_data_path_plugin_init"); - dlclose(handle); - VINE_LOGI("Loaded %s", DATA_PATH_PLUGIN_PATH); - } else { - VINE_LOGE("%s doesn't exist", DATA_PATH_PLUGIN_PATH); - return VINE_ERROR_OPERATION_FAILED; + int loaded = 0; + + for (int i = 0; __vine_data_path_plugins_info[i].path; ++i) { + void *handle = dlopen(__vine_data_path_plugins_info[i].path, RTLD_LAZY | RTLD_NODELETE); + if (handle) { + __vine_data_path_plugins[i].init = + (void (*)(vine_dp_plugin_fn *))dlsym(handle, "vine_data_path_plugin_init"); + dlclose(handle); + ++loaded; + VINE_LOGI("Loaded %s", __vine_data_path_plugins_info[i].path); + } else { + VINE_LOGE("%s doesn't exist", __vine_data_path_plugins_info[i].path); + } } - return VINE_ERROR_NONE; + VINE_LOGI("%d plugins are loaded.", loaded); + return (loaded > 0 ? VINE_ERROR_NONE : VINE_ERROR_OPERATION_FAILED); } int vine_data_path_set_received_cb( @@ -464,15 +484,20 @@ int vine_data_path_close(vine_data_path_h datapath) RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL"); vine_data_path_s *dp = (vine_data_path_s *)datapath; - g_dp_plugin_fn.close(dp->plugin_handle); + RET_VAL_IF(!dp->plugin_fn || dp->plugin_fn->close, + VINE_ERROR_INVALID_PARAMETER, "plugin_fn is NULL"); + dp->plugin_fn->close(dp->plugin_handle); return VINE_ERROR_NONE; } -static vine_data_path_s *_vine_data_path_create(vine_address_family_e addr_family, +static vine_data_path_s *_vine_data_path_create(vine_data_path_method_e method, + vine_address_family_e addr_family, const char *addr, int port, vine_security_h security, void *plugin_data, vine_event_queue_h event_queue) { + RET_VAL_IF(method < VINE_DATA_PATH_METHOD_LWS || method >= VINE_DATA_PATH_METHOD_UNKNOWN, + NULL, "Unknown method."); RET_VAL_IF(addr == NULL, NULL, "addr is NULL"); int ret = VINE_ERROR_NONE; @@ -481,6 +506,13 @@ static vine_data_path_s *_vine_data_path_create(vine_address_family_e addr_famil dp = (vine_data_path_s *)calloc(1, sizeof(vine_data_path_s)); RET_VAL_IF(dp == NULL, NULL, "Out of memory"); + dp->method = method; + dp->plugin_fn = &__vine_data_path_plugins[method].fn; + if (!dp->plugin_fn || !dp->plugin_fn->create) { + free(dp); + return NULL; + } + dp->addr_family = addr_family; dp->addr = STRDUP(addr); if (dp->addr == NULL) { @@ -505,7 +537,7 @@ static vine_data_path_s *_vine_data_path_create(vine_address_family_e addr_famil dp->security = NULL; } - ret = g_dp_plugin_fn.create(&dp->plugin_handle, plugin_data, dp); + ret = dp->plugin_fn->create(&dp->plugin_handle, plugin_data, dp); if (ret != VINE_DATA_PATH_ERROR_NONE) { free(dp->addr); _vine_security_destroy(dp->security); @@ -514,8 +546,8 @@ static vine_data_path_s *_vine_data_path_create(vine_address_family_e addr_famil return NULL; } - dp->state = vine_get_default_state(dp, dp->plugin_handle); - VINE_LOGD("datapath[%p] is created.", dp); + dp->state = vine_get_default_state(dp, dp->plugin_handle, *dp->plugin_fn); + VINE_LOGD("datapath[%p] is created. method[%d]", dp, method); return dp; } @@ -524,7 +556,9 @@ int vine_data_path_destroy(vine_data_path_h datapath) RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL"); vine_data_path_s *dp = (vine_data_path_s *)datapath; - g_dp_plugin_fn.destroy(dp->plugin_handle); + if (dp->plugin_fn && dp->plugin_fn->destroy) + dp->plugin_fn->destroy(dp->plugin_handle); + dp->plugin_handle = NULL; free(dp->addr); dp->addr = NULL; @@ -582,26 +616,46 @@ static void __data_received(vine_data_path_h dp, size_t bytes) notify_data_received(dp, bytes); } +static int __init_plugins(void) +{ + vine_dp_plugin_callbacks callbacks = { + .pollfd_cb = __pollfd_cb, + .opened_cb = __opened_cb, + .accepted_cb = __accepted_cb, + .connected_cb = __connected_cb, + .received_cb = __received_cb, + .written_cb = __written_cb, + .terminated_cb = __terminated_cb, + }; + + for (int i = 0; __vine_data_path_plugins[i].init; ++i) { + __vine_data_path_plugins[i].init(&__vine_data_path_plugins[i].fn); + if (__vine_data_path_plugins[i].fn.init() != VINE_ERROR_NONE) + continue; + + __vine_data_path_plugins[i].callbacks = callbacks; + __vine_data_path_plugins[i].fn.register_callbacks(__vine_data_path_plugins[i].callbacks); + } + + return VINE_ERROR_NONE; +} + +static void __deinit_plugins(void) +{ + for (int i = 0; __vine_data_path_plugins[i].fn.deinit; ++i) + __vine_data_path_plugins[i].fn.deinit(); +} + int vine_data_path_init(void) { int ret = _load_data_path_plugins(); RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to load plugins"); - __init_plugin(&g_dp_plugin_fn); - ret = g_dp_plugin_fn.init(); + ret = __init_plugins(); RET_VAL_IF(ret != VINE_DATA_PATH_ERROR_NONE, __convert_data_path_error_to_vine_error((vine_data_path_error)ret), "Filed to init dp-plugin"); - g_dp_plugin_cbs.pollfd_cb = __pollfd_cb; - g_dp_plugin_cbs.opened_cb = __opened_cb; - g_dp_plugin_cbs.accepted_cb = __accepted_cb; - g_dp_plugin_cbs.connected_cb = __connected_cb; - g_dp_plugin_cbs.received_cb = __received_cb; - g_dp_plugin_cbs.written_cb = __written_cb; - g_dp_plugin_cbs.terminated_cb = __terminated_cb; - g_dp_plugin_fn.register_callbacks(g_dp_plugin_cbs); - vine_dp_state_set_state_changed_notifier(__set_state); vine_dp_state_set_established_notifier(__established); vine_dp_state_set_data_received_notifier(__data_received); @@ -610,8 +664,7 @@ int vine_data_path_init(void) int vine_data_path_deinit(void) { - g_dp_plugin_fn.deinit(); - + __deinit_plugins(); return VINE_ERROR_NONE; } @@ -671,7 +724,8 @@ static void _destroy_security_info(vine_dp_ssl *dest) free(dest->key_path); } -int vine_data_path_open(vine_address_family_e addr_family, int port, const char *iface_name, +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_data_path_opened_cb opened_cb, void *opened_cb_data, vine_data_path_accepted_cb accepted_cb, void *accepted_cb_data, @@ -686,8 +740,10 @@ int vine_data_path_open(vine_address_family_e addr_family, int port, const char } vine_data_path_s *dp = - _vine_data_path_create(addr_family, "", port, security, NULL, event_queue); + _vine_data_path_create(method, addr_family, "", port, security, NULL, event_queue); RET_VAL_IF(dp == NULL, VINE_ERROR_OUT_OF_MEMORY, "Out of memory"); + RET_VAL_IF(dp->plugin_fn == NULL, VINE_ERROR_INVALID_PARAMETER, "Invalid parameter"); + RET_VAL_IF(dp->plugin_fn->open == NULL, VINE_ERROR_INVALID_PARAMETER, "Invalid parameter"); vine_dp_ssl ssl = {false, VINE_DP_TLS_VERSION_DEFAULT, 0, NULL, NULL, NULL}; _extract_security_info(security, &ssl); @@ -698,15 +754,15 @@ int vine_data_path_open(vine_address_family_e addr_family, int port, const char dp->accepted_cb_data = accepted_cb_data; // optional - if (host_name) { - ret = g_dp_plugin_fn.set_host_name(dp->plugin_handle, host_name); + if (host_name && dp->plugin_fn->set_host_name) { + ret = dp->plugin_fn->set_host_name(dp->plugin_handle, host_name); if (ret != VINE_DATA_PATH_ERROR_NONE) { vine_data_path_destroy(dp); return __convert_data_path_error_to_vine_error((vine_data_path_error)ret); } } - ret = g_dp_plugin_fn.open(dp->plugin_handle, dp_addr_family, port, iface_name, max_conn, ssl); + ret = dp->plugin_fn->open(dp->plugin_handle, dp_addr_family, port, iface_name, max_conn, ssl); _destroy_security_info(&ssl); if (ret != VINE_DATA_PATH_ERROR_NONE) { @@ -723,15 +779,18 @@ int vine_data_path_open(vine_address_family_e addr_family, int port, const char return VINE_ERROR_NONE; } -int vine_data_path_connect(vine_address_family_e addr_family, +int vine_data_path_connect(vine_data_path_method_e method, + vine_address_family_e addr_family, const char *ip, int port, const char *iface_name, vine_security_h security, const char *host_name, const char *token, vine_data_path_connected_cb callback, void *user_data, vine_data_path_h *connected_datapath, vine_event_queue_h event_queue) { vine_data_path_s *dp = - _vine_data_path_create(addr_family, ip, port, security, NULL, event_queue); + _vine_data_path_create(method, addr_family, ip, port, security, NULL, event_queue); RET_VAL_IF(dp == NULL, VINE_ERROR_OUT_OF_MEMORY, "Out of memory"); + RET_VAL_IF(dp->plugin_fn == NULL, VINE_ERROR_INVALID_PARAMETER, "Invalid parameter"); + RET_VAL_IF(dp->plugin_fn->connect == NULL, VINE_ERROR_INVALID_PARAMETER, "Invalid parameter"); RET_VAL_IF(connected_datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "connected_datapath is NULL"); @@ -744,16 +803,16 @@ int vine_data_path_connect(vine_address_family_e addr_family, int ret; // optional - if (host_name) { - ret = g_dp_plugin_fn.set_host_name(dp->plugin_handle, host_name); + if (host_name && dp->plugin_fn->set_host_name) { + ret = dp->plugin_fn->set_host_name(dp->plugin_handle, host_name); if (ret != VINE_DATA_PATH_ERROR_NONE) { vine_data_path_destroy(dp); return __convert_data_path_error_to_vine_error((vine_data_path_error)ret); } } - if (token) { - ret = g_dp_plugin_fn.set_token(dp->plugin_handle, token); + 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); @@ -761,7 +820,7 @@ int vine_data_path_connect(vine_address_family_e addr_family, } } - ret = g_dp_plugin_fn.connect(dp->plugin_handle, + ret = dp->plugin_fn->connect(dp->plugin_handle, addr_family == VINE_ADDRESS_FAMILY_IPV4 ? VINE_DP_IPV4 : VINE_DP_IPV6, ip, port, iface_name, ssl); _destroy_security_info(&ssl); @@ -795,7 +854,10 @@ int vine_data_path_get_token(vine_data_path_h datapath, char **token) RET_VAL_IF(token == NULL, VINE_ERROR_INVALID_PARAMETER, "token is NULL"); vine_data_path_s *dp = (vine_data_path_s *)datapath; - int ret = g_dp_plugin_fn.get_token(dp->plugin_handle, token); + if (!dp->plugin_fn || !dp->plugin_fn->get_token) + return VINE_ERROR_INVALID_PARAMETER; + + int ret = dp->plugin_fn->get_token(dp->plugin_handle, token); return __convert_data_path_error_to_vine_error((vine_data_path_error)ret); } @@ -816,10 +878,13 @@ int vine_data_path_get_local_address_info(vine_data_path_h datapath, int *addres RET_VAL_IF(port == NULL, VINE_ERROR_INVALID_PARAMETER, "port is NULL"); vine_data_path_s *dp = (vine_data_path_s *)datapath; + RET_VAL_IF(!dp->plugin_fn || !dp->plugin_fn->get_local_address_info, + VINE_ERROR_INVALID_PARAMETER, "plugin_fn is NULL"); + vine_error_e error; int addr_family, local_port; char local_ip[VINE_MAX_IP_LEN + 1] = {0, }; - int ret = g_dp_plugin_fn.get_local_address_info(dp->plugin_handle, + int ret = dp->plugin_fn->get_local_address_info(dp->plugin_handle, &addr_family, local_ip, &local_port); error = __convert_data_path_error_to_vine_error((vine_data_path_error)ret); diff --git a/src/vine-dp.cpp b/src/vine-dp.cpp index 29a640f..5fb28ca 100644 --- a/src/vine-dp.cpp +++ b/src/vine-dp.cpp @@ -449,6 +449,7 @@ void DataPath::invoke_terminated_cb() DPServer::DPServer(void *event_queue) { VINE_LOGD("DPServer[%p] is created.", this); + mMethod = VINE_DATA_PATH_METHOD_LWS; mEventQueue = event_queue; mSecurity = NULL; mAddrFamily = VINE_ADDRESS_FAMILY_DEFAULT; @@ -474,6 +475,24 @@ DPServer::~DPServer() vine_data_path_destroy(mDataPath); } +int DPServer::set_method(vine_dp_method_e method) +{ + if (method < VINE_DP_METHOD_DEFAULT || method >= VINE_DP_METHOD_UNKNOWN) + return VINE_ERROR_INVALID_PARAMETER; + + switch (method) { + case VINE_DP_METHOD_DEFAULT: + mMethod = VINE_DATA_PATH_METHOD_LWS; + break; + case VINE_DP_METHOD_BLE_GATT: + mMethod = VINE_DATA_PATH_METHOD_BLE_GATT; + break; + default: + mMethod = VINE_DATA_PATH_METHOD_LWS; + } + return VINE_ERROR_NONE; +} + int DPServer::get_id(char **id) { return VINE_ERROR_INVALID_OPERATION; @@ -599,7 +618,8 @@ int DPServer::open(vine_dp_opened_cb callback, void *user_data) mOpenedCbData = user_data; mOpenState = VINE_DP_OPEN_STATE_WAIT; - int ret = vine_data_path_open(mAddrFamily, mListenPort, + int ret = vine_data_path_open(mMethod, + mAddrFamily, mListenPort, mIfaceName.size() > 0 ? mIfaceName.c_str() : NULL, mMaxConnNum, mSecurity, NULL, _opened_cb, static_cast(this), @@ -630,6 +650,7 @@ int DPServer::recv(unsigned char *buf, size_t buf_len, size_t *read_len) DPClient::DPClient(void *event_queue) { VINE_LOGD("DPClient[%p] is created.", this); + mMethod = VINE_DATA_PATH_METHOD_LWS; mEventQueue = event_queue; mSecurity = NULL; mAddrFamily = VINE_ADDRESS_FAMILY_DEFAULT; @@ -676,6 +697,24 @@ DPClient::~DPClient() vine_data_path_destroy(mDataPath); } +int DPClient::set_method(vine_dp_method_e method) +{ + if (method < VINE_DP_METHOD_DEFAULT || method >= VINE_DP_METHOD_UNKNOWN) + return VINE_ERROR_INVALID_PARAMETER; + + switch (method) { + case VINE_DP_METHOD_DEFAULT: + mMethod = VINE_DATA_PATH_METHOD_LWS; + break; + case VINE_DP_METHOD_BLE_GATT: + mMethod = VINE_DATA_PATH_METHOD_BLE_GATT; + break; + default: + mMethod = VINE_DATA_PATH_METHOD_LWS; + } + return VINE_ERROR_NONE; +} + int DPClient::get_id(char **id) { return VINE_ERROR_INVALID_OPERATION; @@ -789,7 +828,8 @@ int DPClient::open(vine_dp_opened_cb callback, void *user_data) mOpenedCbData = user_data; mOpenState = VINE_DP_OPEN_STATE_WAIT; - int ret = vine_data_path_connect(mAddrFamily, mPeerIp.c_str(), mPeerPort, + int ret = vine_data_path_connect(mMethod, + mAddrFamily, mPeerIp.c_str(), mPeerPort, mIfaceName.size() > 0 ? mIfaceName.c_str() : NULL, mSecurity, NULL, NULL, _connected_cb, static_cast(this), &mDataPath, mEventQueue); @@ -817,6 +857,7 @@ int DPClient::recv(unsigned char *buf, size_t buf_len, size_t *read_len) DPPubSub::DPPubSub(void *event_queue) { VINE_LOGD("DPPubSub[%p] is created.", this); + mMethod = VINE_DATA_PATH_METHOD_LWS; mEventQueue = event_queue; mSecurity = NULL; mIfaceName = ""; @@ -853,6 +894,18 @@ DPPubSub::~DPPubSub() close(); } +int DPPubSub::set_method(vine_dp_method_e method) +{ + if (method < VINE_DP_METHOD_DEFAULT || method >= VINE_DP_METHOD_UNKNOWN) + return VINE_ERROR_INVALID_PARAMETER; + + if (method == VINE_DP_METHOD_BLE_GATT) + return VINE_ERROR_INVALID_OPERATION; + + mMethod = VINE_DATA_PATH_METHOD_LWS; + return VINE_ERROR_NONE; +} + void DPPubSub::set_id(const char *id) { if (id == NULL || mId.compare(id) == 0) @@ -1003,7 +1056,8 @@ int DPPubSub::connect(const char *service_name, const char *ip, int port) conn_data->dp = static_cast(this); conn_data->service_name = STRDUP(service_name); - int ret = vine_data_path_connect(mAddrFamily, ip, port, iface_name, + int ret = vine_data_path_connect(mMethod, + mAddrFamily, ip, port, iface_name, mSecurity, service_name, mId.c_str(), _pubsub_connected_cb, (void *)conn_data, &datapath, mEventQueue); @@ -1113,7 +1167,8 @@ int DPPubSub::open(vine_dp_opened_cb callback, void *user_data) create_id(service_name); set_id(service_name); - int ret = vine_data_path_open(mAddrFamily, mListenPort, + int ret = vine_data_path_open(mMethod, + mAddrFamily, mListenPort, mIfaceName.size() > 0 ? mIfaceName.c_str() : NULL, mMaxConnNum, mSecurity, mId.c_str(), _pubsub_opened_cb, static_cast(this), @@ -1361,7 +1416,8 @@ int _vine_dp_create(vine_session_h session, vine_dp_type_e type, vine_dp_h *dp) vine_event_queue_h eq = NULL; int ret = _vine_session_get_event_queue(session, &eq); - if (ret != VINE_ERROR_NONE || !eq) + // eq can be NULL if glib is used as the eventloop. + if (ret != VINE_ERROR_NONE) return VINE_ERROR_INVALID_PARAMETER; if (type == VINE_DP_TYPE_SERVER) { @@ -1385,6 +1441,14 @@ int _vine_dp_destroy(vine_dp_h dp) return VINE_ERROR_NONE; } +int _vine_dp_set_method(vine_dp_h dp, vine_dp_method_e method) +{ + RET_VAL_IF(dp == NULL, VINE_ERROR_INVALID_PARAMETER, "dp is null."); + + DataPath *_dp = static_cast(dp); + return _dp->set_method(method);; +} + int _vine_dp_get_id(vine_dp_h dp, char **id) { RET_VAL_IF(dp == NULL, VINE_ERROR_INVALID_PARAMETER, "dp is null."); diff --git a/src/vine.cpp b/src/vine.cpp index 6c2d95e..2931ecb 100755 --- a/src/vine.cpp +++ b/src/vine.cpp @@ -350,6 +350,14 @@ API int vine_dp_destroy(vine_dp_h dp) return _vine_dp_destroy(dp); } +API int vine_dp_set_method(vine_dp_h dp, vine_dp_method_e method) +{ + __VINE_FUNC_ENTER__; + CHECK_FEATURE_SUPPORTED; + + return _vine_dp_set_method(dp, method); +} + API int vine_dp_get_id(vine_dp_h dp, char **id) { __VINE_FUNC_ENTER__; diff --git a/tests/unittest/vine-unittest-dp.cpp b/tests/unittest/vine-unittest-dp.cpp index 26fcfac..a6daf59 100755 --- a/tests/unittest/vine-unittest-dp.cpp +++ b/tests/unittest/vine-unittest-dp.cpp @@ -110,6 +110,20 @@ TEST_F(VineDpTest, DestroyP) vine_dp_destroy(dp)); } +TEST_F(VineDpTest, SetMethodN) +{ + EXPECT_EQ(VINE_ERROR_INVALID_PARAMETER, vine_dp_set_method(server_dp, VINE_DP_METHOD_UNKNOWN)); + EXPECT_EQ(VINE_ERROR_INVALID_PARAMETER, vine_dp_set_method(client_dp, VINE_DP_METHOD_UNKNOWN)); + EXPECT_EQ(VINE_ERROR_INVALID_OPERATION, vine_dp_set_method(pubsub_dp, VINE_DP_METHOD_BLE_GATT)); +} + +TEST_F(VineDpTest, SetMethodP) +{ + EXPECT_EQ(VINE_ERROR_NONE, vine_dp_set_method(server_dp, VINE_DP_METHOD_BLE_GATT)); + EXPECT_EQ(VINE_ERROR_NONE, vine_dp_set_method(client_dp, VINE_DP_METHOD_BLE_GATT)); + EXPECT_EQ(VINE_ERROR_NONE, vine_dp_set_method(pubsub_dp, VINE_DP_METHOD_DEFAULT)); +} + TEST_F(VineDpTest, GetIdN) { char *id = NULL; diff --git a/tool/tool_run.cpp b/tool/tool_run.cpp index 6c8445a..9bfd677 100755 --- a/tool/tool_run.cpp +++ b/tool/tool_run.cpp @@ -554,6 +554,9 @@ static void _set_dp_info(vine_dp_type_e type) vine_dp_set_address_family(vine_configs.dp, addr_family); vine_dp_set_max_connections(vine_configs.dp, tool_config_get_max_conn()); + if (vine_configs.with_ble) + vine_dp_set_method(vine_configs.dp, VINE_DP_METHOD_BLE_GATT); + if (type == VINE_DP_TYPE_CLIENT) { vine_dp_set_remote_port(vine_configs.dp, tool_config_get_port()); vine_dp_set_remote_ip(vine_configs.dp, addr_family, -- 2.7.4 From 7f88964069bf91904a0c074d71515917cad1c353 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Wed, 7 Jul 2021 18:45:58 +0900 Subject: [PATCH 11/16] Add new API to set/get remote address(GATT) Change-Id: I2e6523b01af33aa7d7bfd99a4f7720f484adb4ab --- include/vine.h | 30 ++++++++++++++++++ plugins/ble-gatt/ble-gatt-plugin.cpp | 15 +++++++++ src/include/vine-dp.h | 11 +++++++ src/vine-dp.cpp | 60 +++++++++++++++++++++++++++++++++++- src/vine.cpp | 16 ++++++++++ tests/unittest/vine-unittest-dp.cpp | 25 +++++++++++++++ tool/tool_run.cpp | 4 ++- 7 files changed, 159 insertions(+), 2 deletions(-) diff --git a/include/vine.h b/include/vine.h index c9a663f..0931fd1 100755 --- a/include/vine.h +++ b/include/vine.h @@ -921,6 +921,36 @@ int vine_dp_get_id(vine_dp_h dp, char **id); int vine_dp_set_iface_name(vine_dp_h dp, const char *iface_or_ip); /** + * @brief Sets the remote address. + * @remarks This is used with VINE_DP_METHOD_BLE_GATT. + * @since_tizen 6.5 + * @param[in] dp The data path handle + * @param[in] address The remote address + * @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() + */ +int vine_dp_set_remote_address(vine_dp_h dp, const char *address); + +/** + * @brief Gets the remote address. + * @remarks This is used with VINE_DP_METHOD_BLE_GATT. + * @since_tizen 6.5 + * @param[in] dp The data path handle + * @param[out] address The remote address + * @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() + */ +int vine_dp_get_remote_address(vine_dp_h dp, char **address); + +/** * @brief Sets the address family. * @remarks This is ignored when dp type is VINE_DP_TYPE_CLIENT. * @since_tizen 6.5 diff --git a/plugins/ble-gatt/ble-gatt-plugin.cpp b/plugins/ble-gatt/ble-gatt-plugin.cpp index dccb252..c8a3292 100755 --- a/plugins/ble-gatt/ble-gatt-plugin.cpp +++ b/plugins/ble-gatt/ble-gatt-plugin.cpp @@ -28,6 +28,8 @@ using namespace std; #define VINE_GATT_CHAR_UUID "00002af6-0000-1000-8000-00805f9b34fb" #define VINE_GATT_DESC_UUID "fa87c0d0-afac-11de-8a39-0800200c9a66" +#define BT_ADDRESS_LEN 17 + typedef enum { VINE_GATT_ROLE_UNKNOWN = 0, VINE_GATT_ROLE_SERVER, @@ -399,6 +401,9 @@ int gatt_open(vine_dp_plugin_h handle, int addr_family, gatt->descriptor = descriptor; VINE_LOGI("Succeeded to start GATT server."); + + //if (g_callbacks.opened_cb) + // g_callbacks.opened_cb(VINE_DATA_PATH_ERROR_NONE, -1, gatt->user); return VINE_DATA_PATH_ERROR_NONE; ERR: @@ -463,6 +468,16 @@ int gatt_close(vine_dp_plugin_h handle) int gatt_get_local_address_info(vine_dp_plugin_h handle, int *addr_family, char local_ip[], int *port) { + char *addr = NULL; + int ret = bt_adapter_get_address(&addr); + if (ret != BT_ERROR_NONE) { + VINE_LOGE("Failed to get local address."); + free(addr); + return __convert_bt_error_to_data_path_error(ret); + } + + strncpy(local_ip, addr, BT_ADDRESS_LEN); + free(addr); return VINE_DATA_PATH_ERROR_NONE; } diff --git a/src/include/vine-dp.h b/src/include/vine-dp.h index 498aefd..b389085 100644 --- a/src/include/vine-dp.h +++ b/src/include/vine-dp.h @@ -49,6 +49,8 @@ public: virtual int set_method(vine_dp_method_e method) = 0; virtual int get_id(char **id) = 0; + virtual int set_remote_address(const char *address) = 0; + virtual int get_remote_address(char **address) = 0; virtual int set_addr_family(vine_address_family_e addr_family) = 0; virtual int set_remote_ip(vine_address_family_e, const std::string &ip) = 0; virtual int get_remote_ip(vine_address_family_e *addr_family, char **ip) = 0; @@ -110,6 +112,8 @@ public: virtual int set_method(vine_dp_method_e method); virtual int get_id(char **id); + virtual int set_remote_address(const char *address); + virtual int get_remote_address(char **address); virtual int set_addr_family(vine_address_family_e addr_family); virtual int set_remote_ip(vine_address_family_e, const std::string &ip); virtual int get_remote_ip(vine_address_family_e *addr_family, char **ip); @@ -155,6 +159,8 @@ public: virtual int set_method(vine_dp_method_e method); virtual int get_id(char **id); + virtual int set_remote_address(const char *address); + virtual int get_remote_address(char **address); virtual int set_addr_family(vine_address_family_e addr_family); virtual int set_remote_ip(vine_address_family_e, const std::string &ip); virtual int get_remote_ip(vine_address_family_e *addr_family, char **ip); @@ -175,6 +181,7 @@ public: private: vine_data_path_h mDataPath; + std::string mPeerAddr; vine_address_family_e mAddrFamily; std::string mPeerIp; int mPeerPort; @@ -210,6 +217,8 @@ public: virtual int set_method(vine_dp_method_e method); virtual int get_id(char **id); + virtual int set_remote_address(const char *address); + virtual int get_remote_address(char **address); virtual int set_addr_family(vine_address_family_e addr_family); virtual int set_remote_ip(vine_address_family_e, const std::string &ip); virtual int get_remote_ip(vine_address_family_e *addr_family, char **ip); @@ -285,6 +294,8 @@ int _vine_dp_create(vine_session_h session, vine_dp_type_e type, vine_dp_h *dp); int _vine_dp_destroy(vine_dp_h dp); int _vine_dp_set_method(vine_dp_h dp, vine_dp_method_e method); int _vine_dp_get_id(vine_dp_h dp, char **id); +int _vine_dp_set_remote_address(vine_dp_h dp, const char *address); +int _vine_dp_get_remote_address(vine_dp_h dp, char **address); int _vine_dp_set_iface_name(vine_dp_h dp, const char *iface_name); int _vine_dp_set_addr_family(vine_dp_h dp, vine_address_family_e addr_family); int _vine_dp_set_remote_ip(vine_dp_h dp, vine_address_family_e addr_family, const char *ip); diff --git a/src/vine-dp.cpp b/src/vine-dp.cpp index 5fb28ca..6ab8e65 100644 --- a/src/vine-dp.cpp +++ b/src/vine-dp.cpp @@ -498,6 +498,16 @@ int DPServer::get_id(char **id) return VINE_ERROR_INVALID_OPERATION; } +int DPServer::set_remote_address(const char *address) +{ + return VINE_ERROR_INVALID_OPERATION; +} + +int DPServer::get_remote_address(char **address) +{ + return VINE_ERROR_INVALID_OPERATION; +} + int DPServer::set_addr_family(vine_address_family_e addr_family) { mAddrFamily = addr_family; @@ -720,6 +730,24 @@ int DPClient::get_id(char **id) return VINE_ERROR_INVALID_OPERATION; } +int DPClient::set_remote_address(const char *address) +{ + RET_VAL_IF(isCreatedByServerDp, VINE_ERROR_INVALID_OPERATION, "cannot set remote address"); + RET_VAL_IF(mMethod == VINE_DATA_PATH_METHOD_LWS, VINE_ERROR_INVALID_OPERATION, + "cannot set remote address"); + + mPeerAddr = address; + return VINE_ERROR_NONE; +} + +int DPClient::get_remote_address(char **address) +{ + if (mPeerAddr.size() == 0) + return VINE_ERROR_OPERATION_FAILED; + *address = STRDUP(mPeerAddr.c_str()); + return VINE_ERROR_NONE; +} + int DPClient::set_addr_family(vine_address_family_e addr_family) { return VINE_ERROR_INVALID_OPERATION; @@ -829,7 +857,9 @@ int DPClient::open(vine_dp_opened_cb callback, void *user_data) mOpenState = VINE_DP_OPEN_STATE_WAIT; int ret = vine_data_path_connect(mMethod, - mAddrFamily, mPeerIp.c_str(), mPeerPort, + 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, _connected_cb, static_cast(this), &mDataPath, mEventQueue); @@ -921,6 +951,16 @@ int DPPubSub::get_id(char **id) return VINE_ERROR_NONE; } +int DPPubSub::set_remote_address(const char *address) +{ + return VINE_ERROR_INVALID_OPERATION; +} + +int DPPubSub::get_remote_address(char **address) +{ + return VINE_ERROR_INVALID_OPERATION; +} + int DPPubSub::set_addr_family(vine_address_family_e addr_family) { mAddrFamily = addr_family; @@ -1458,6 +1498,24 @@ int _vine_dp_get_id(vine_dp_h dp, char **id) return _dp->get_id(id); } +int _vine_dp_set_remote_address(vine_dp_h dp, const char *address) +{ + RET_VAL_IF(dp == NULL, VINE_ERROR_INVALID_PARAMETER, "dp is null."); + RET_VAL_IF(address == NULL, VINE_ERROR_INVALID_PARAMETER, "address is null."); + + DataPath *_dp = static_cast(dp); + return _dp->set_remote_address(address); +} + +int _vine_dp_get_remote_address(vine_dp_h dp, char **address) +{ + RET_VAL_IF(dp == NULL, VINE_ERROR_INVALID_PARAMETER, "dp is null."); + RET_VAL_IF(address == NULL, VINE_ERROR_INVALID_PARAMETER, "address is null."); + + DataPath *_dp = static_cast(dp); + return _dp->get_remote_address(address); +} + int _vine_dp_set_iface_name(vine_dp_h dp, const char *iface_name) { RET_VAL_IF(dp == NULL, VINE_ERROR_INVALID_PARAMETER, "dp is null."); diff --git a/src/vine.cpp b/src/vine.cpp index 2931ecb..8290152 100755 --- a/src/vine.cpp +++ b/src/vine.cpp @@ -366,6 +366,22 @@ API int vine_dp_get_id(vine_dp_h dp, char **id) return _vine_dp_get_id(dp, id); } +API int vine_dp_set_remote_address(vine_dp_h dp, const char *address) +{ + __VINE_FUNC_ENTER__; + CHECK_FEATURE_SUPPORTED; + + return _vine_dp_set_remote_address(dp, address); +} + +API int vine_dp_get_remote_address(vine_dp_h dp, char **address) +{ + __VINE_FUNC_ENTER__; + CHECK_FEATURE_SUPPORTED; + + return _vine_dp_get_remote_address(dp, address); +} + API int vine_dp_set_iface_name(vine_dp_h dp, const char *iface_name) { __VINE_FUNC_ENTER__; diff --git a/tests/unittest/vine-unittest-dp.cpp b/tests/unittest/vine-unittest-dp.cpp index a6daf59..8dd6838 100755 --- a/tests/unittest/vine-unittest-dp.cpp +++ b/tests/unittest/vine-unittest-dp.cpp @@ -20,6 +20,7 @@ #include "mocks/vine-mock-memory.h" +#define TEST_MAC "ab:cd:ef:ab:cd:ef" #define TEST_IP "192.168.1.123" class VineDpTest : public ::testing::Test { @@ -138,6 +139,30 @@ TEST_F(VineDpTest, GetIdP) EXPECT_EQ(VINE_ERROR_NONE, vine_dp_get_id(pubsub_dp, &id)); } +TEST_F(VineDpTest, SetRemoteAddressN) +{ + EXPECT_EQ(VINE_ERROR_INVALID_PARAMETER, vine_dp_set_remote_address(client_dp, NULL)); + EXPECT_EQ(VINE_ERROR_INVALID_PARAMETER, vine_dp_set_remote_address(NULL, TEST_MAC)); + EXPECT_EQ(VINE_ERROR_INVALID_OPERATION, vine_dp_set_remote_address(client_dp, TEST_MAC)); + EXPECT_EQ(VINE_ERROR_INVALID_OPERATION, vine_dp_set_remote_address(server_dp, TEST_MAC)); + EXPECT_EQ(VINE_ERROR_INVALID_OPERATION, vine_dp_set_remote_address(pubsub_dp, TEST_MAC)); +} + +TEST_F(VineDpTest, SetRemoteAddressP) +{ + vine_dp_set_method(client_dp, VINE_DP_METHOD_BLE_GATT); + EXPECT_EQ(VINE_ERROR_NONE, vine_dp_set_remote_address(client_dp, TEST_MAC)); +} + +TEST_F(VineDpTest, GetRemoteAddressP) +{ + char *addr; + EXPECT_EQ(VINE_ERROR_INVALID_PARAMETER, vine_dp_get_remote_address(client_dp, NULL)); + EXPECT_EQ(VINE_ERROR_INVALID_PARAMETER, vine_dp_get_remote_address(NULL, &addr)); + EXPECT_EQ(VINE_ERROR_INVALID_OPERATION, vine_dp_get_remote_address(server_dp, &addr)); + EXPECT_EQ(VINE_ERROR_INVALID_OPERATION, vine_dp_get_remote_address(pubsub_dp, &addr)); +} + TEST_F(VineDpTest, SetRemoteIpN) { EXPECT_EQ(VINE_ERROR_INVALID_PARAMETER, diff --git a/tool/tool_run.cpp b/tool/tool_run.cpp index 9bfd677..d5e7e84 100755 --- a/tool/tool_run.cpp +++ b/tool/tool_run.cpp @@ -554,8 +554,10 @@ static void _set_dp_info(vine_dp_type_e type) vine_dp_set_address_family(vine_configs.dp, addr_family); vine_dp_set_max_connections(vine_configs.dp, tool_config_get_max_conn()); - if (vine_configs.with_ble) + 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_dp_set_remote_port(vine_configs.dp, tool_config_get_port()); -- 2.7.4 From f5c94753e4180d6f4ef473492b9aa66ee122a368 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Thu, 8 Jul 2021 17:47:04 +0900 Subject: [PATCH 12/16] Implement read/write for BLE GATT Change-Id: Id018c74de7bac482d3d9bd59fca6ab61598a9cb2 --- plugins/ble-gatt/ble-gatt-plugin.cpp | 211 +++++++++++++++++++++++++++++++++-- src/include/vine-data-path-state.h | 2 +- src/vine-data-path.cpp | 2 +- 3 files changed, 206 insertions(+), 9 deletions(-) diff --git a/plugins/ble-gatt/ble-gatt-plugin.cpp b/plugins/ble-gatt/ble-gatt-plugin.cpp index c8a3292..e428706 100755 --- a/plugins/ble-gatt/ble-gatt-plugin.cpp +++ b/plugins/ble-gatt/ble-gatt-plugin.cpp @@ -20,6 +20,7 @@ #include "vine-data-path-plugin.h" #include "vine-log.h" #include "vine-utils.h" +#include "vine-queue.h" using namespace std; @@ -37,6 +38,13 @@ typedef enum { } vine_gatt_role_e; typedef struct { + char *buf; + size_t len; + //size_t accumulating; + bool last; // true, single message or last fragment of a message. +} gatt_data_s; + +typedef struct { bt_gatt_h service; bt_gatt_h characteristic; bt_gatt_h descriptor; @@ -47,7 +55,9 @@ typedef struct { bt_gatt_client_h client; } role; - char *remote_address; + VineQueue *recv_buffer; + + char *remote_address; // this is used for VINE_GATT_ROLE_CLIENT only. bool is_accepted; void *user; // vine_data_path_h } vine_gatt_s; @@ -79,6 +89,34 @@ static vine_data_path_error __convert_bt_error_to_data_path_error(int error) } } +static gatt_data_s *__create_gatt_data(const char *buf, size_t len, bool last) +{ + gatt_data_s *gd = (gatt_data_s *)calloc(1, sizeof(gatt_data_s)); + RET_VAL_IF(!gd, NULL, "Out of memory."); + + char *data = (char *)calloc(len, sizeof(char)); + if (!data) { + VINE_LOGE("Out of memory."); + free(gd); + return NULL; + } + + memcpy(data, buf, len); + gd->buf = data; + gd->len = len; + gd->last = last; + return gd; +} + +static void __destroy_gatt_data(gatt_data_s *data) +{ + RET_IF(!data, "data is NULL"); + + if (data->buf) + free(data->buf); + free(data); +} + static void __invoke_accepted_cb(const char *remote_address, vine_gatt_s *gatt, void *user_data) { if (!g_callbacks.accepted_cb) @@ -87,6 +125,7 @@ static void __invoke_accepted_cb(const char *remote_address, vine_gatt_s *gatt, vine_gatt_s *accepted_gatt = _create_gatt(); RET_IF(accepted_gatt == NULL, "Failed to create accepted_gatt."); + accepted_gatt->type = VINE_GATT_ROLE_CLIENT; accepted_gatt->remote_address = STRDUP(remote_address); // refer to server's gatt handles. @@ -121,6 +160,8 @@ static void __gatt_server_read_value_requested_cb( int offset, void *user_data) { // TODO: Send response. + // TODO: Save data + // Is this function needed for VINE? } static void __gatt_server_write_value_requested_cb(const char *remote_address, @@ -128,9 +169,27 @@ static void __gatt_server_write_value_requested_cb(const char *remote_address, 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 value requestment from %s.", remote_address); - // TODO: Send response. + vine_gatt_s *gatt = (vine_gatt_s *)user_data; + + // TODO: Need to handle splited data using offset. + gatt_data_s *recv_data = __create_gatt_data(value, len, true); + RET_IF(recv_data == NULL, "recv_data is NULL"); + + gatt->recv_buffer->push(recv_data); + + VINE_LOGI("Write value requested. offset[%d] len[%d] reponse_needed[%d]", + offset, len, response_needed); + + if (bt_gatt_server_send_response(request_id, + BT_GATT_REQUEST_TYPE_WRITE, offset, BT_ERROR_NONE, NULL, 0) < 0) + VINE_LOGE("bt_gatt_server_send_response() is failed."); + + if (g_callbacks.received_cb) + g_callbacks.received_cb(len, gatt->user); } void __gatt_server_noti_state_changed_cb(bool notify, bt_gatt_server_h server, @@ -139,6 +198,20 @@ void __gatt_server_noti_state_changed_cb(bool notify, bt_gatt_server_h server, VINE_LOGI("Noti state changed. notify[%d] characteristic[%p]", notify, gatt_handle); } +void __gatt_server_noti_sent_cb(int result, + const char *remote_address, bt_gatt_server_h server, bt_gatt_h characteristic, + bool completed, void *user_data) +{ + RET_IF(user_data == NULL, "user_data is NULL"); + RET_IF(g_callbacks.written_cb == NULL, "written_cb() is NULL"); + + VINE_LOGI("Send data to %s is %s. server[%p] completed[%d]", + remote_address, result == 0 ? "success" : "failed", server, completed); + + vine_gatt_s *gatt = (vine_gatt_s *)user_data; + g_callbacks.written_cb(1, gatt->user); // bytes will be ignored. +} + // Client Callbacks static void __gatt_client_service_changed_cb(bt_gatt_client_h client, bt_gatt_client_service_change_type_e type, const char *uuid, void *user_data) @@ -147,6 +220,33 @@ static void __gatt_client_service_changed_cb(bt_gatt_client_h client, type == BT_GATT_CLIENT_SERVICE_ADDED ? "added." : "removed." ); } +void __gatt_client_write_complete_cb(int result, bt_gatt_h gatt_handle, void *user_data) +{ + RET_IF(user_data == NULL, "user_data is NULL"); + RET_IF(g_callbacks.written_cb == NULL, "written_cb() is NULL"); + + VINE_LOGI("gatt[%p] completed to send data. result[%d]", gatt_handle, result); + + vine_gatt_s *gatt = (vine_gatt_s *)user_data; + g_callbacks.written_cb(1, gatt->user); // bytes will be ignored. +} + +void __gatt_client_characteristic_value_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; + gatt_data_s *recv_data = __create_gatt_data(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"); @@ -174,6 +274,11 @@ 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_set_characteristic_value_changed_cb(characteristic, + __gatt_client_characteristic_value_changed_cb, gatt); + if (ret != BT_ERROR_NONE) + goto ERR; + gatt->role.client = client; gatt->service = service; gatt->characteristic = characteristic; @@ -224,6 +329,8 @@ static vine_gatt_s *_create_gatt(void) free(gatt); return NULL; } + + gatt->recv_buffer = new VineQueue; return gatt; } @@ -281,6 +388,38 @@ static bt_gatt_h _add_gatt_descriptor(bt_gatt_h characteristic) return descriptor; } +static int _gatt_write_to_server(vine_gatt_s *gatt, unsigned char *buf, size_t len) +{ + int ret = bt_gatt_set_value(gatt->characteristic, (const char *)buf, 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, + __gatt_client_write_complete_cb, (void *)gatt); + RET_VAL_IF(ret != BT_ERROR_NONE, __convert_bt_error_to_data_path_error(ret), + "bt_gatt_client_write_value() failed."); + + VINE_LOGI("Succeed to send data to server"); + + return VINE_DATA_PATH_ERROR_NONE; +} + +static int _gatt_write_to_client(vine_gatt_s *gatt, unsigned char *buf, size_t len) +{ + int ret = bt_gatt_set_value(gatt->characteristic, (const char *)buf, 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, + __gatt_server_noti_sent_cb, gatt->remote_address, (void *)gatt); + RET_VAL_IF(ret != BT_ERROR_NONE, __convert_bt_error_to_data_path_error(ret), + "bt_gatt_server_notify_characteristic_changed_value() failed."); + + VINE_LOGI("Succeed to send data to %s", gatt->remote_address ? gatt->remote_address : "all"); + + return VINE_DATA_PATH_ERROR_NONE; +} + int gatt_init(void) { return VINE_DATA_PATH_ERROR_NONE; @@ -305,7 +444,7 @@ 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"); - vine_gatt_s *gatt = _create_gatt(); + 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"); gatt->user = user; @@ -402,6 +541,7 @@ int gatt_open(vine_dp_plugin_h handle, int addr_family, VINE_LOGI("Succeeded to start GATT server."); + // TODO //if (g_callbacks.opened_cb) // g_callbacks.opened_cb(VINE_DATA_PATH_ERROR_NONE, -1, gatt->user); return VINE_DATA_PATH_ERROR_NONE; @@ -445,7 +585,50 @@ int gatt_connect(vine_dp_plugin_h handle, int addr_family, int gatt_read(vine_dp_plugin_h handle, unsigned char *buf, size_t len) { - return VINE_DATA_PATH_ERROR_NONE; + RET_VAL_IF(handle == NULL, 0, "plugin handle is NULL"); + RET_VAL_IF(buf == NULL, 0, "buf is NULL"); + RET_VAL_IF(len == 0, 0, "len is 0"); + + vine_gatt_s *gatt = (vine_gatt_s *)handle; + gatt_data_s *gd = NULL; + size_t bytes = 0; + + if (!gatt->recv_buffer) + return bytes; + + unsigned char *ptr = buf; + size_t read_len = 0; + while (!gatt->recv_buffer->empty() && len > 0) { + gd = gatt->recv_buffer->front(); + if (gd == nullptr) { + gatt->recv_buffer->pop(); + return bytes; + } + + ptr += read_len; + read_len = gd->len > len ? len : gd->len; + memcpy(ptr, gd->buf, read_len); + len -= read_len; + bytes += read_len; + + if (read_len >= gd->len) { + gatt->recv_buffer->pop(); + bool last = gd->last; + __destroy_gatt_data(gd); + gd = NULL; + if (last) + break; + } else if (read_len < gd->len) { // requeue + size_t remained_len = gd->len - read_len; + char *remained_data = (char *)calloc(remained_len, sizeof(char)); + memcpy(remained_data, gd->buf + read_len, remained_len); + free(gd->buf); + gd->buf = remained_data; + gd->len = remained_len; + return bytes; + } + } + return bytes; } int gatt_write(vine_dp_plugin_h handle, unsigned char *buf, size_t len) @@ -454,10 +637,24 @@ int gatt_write(vine_dp_plugin_h handle, unsigned char *buf, size_t len) RET_VAL_IF(buf == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "buf is NULL"); RET_VAL_IF(len <= 0, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "len is less than 0"); - // TODO - // vine_gatt_s *gatt = (vine_gatt_s *)handle; + vine_gatt_s *gatt = (vine_gatt_s *)handle; + int ret; - return VINE_DATA_PATH_ERROR_NONE; + switch (gatt->type) { + case VINE_GATT_ROLE_SERVER: + ret =_gatt_write_to_client(gatt, buf, len); + break; + case VINE_GATT_ROLE_CLIENT: + ret = gatt->is_accepted ? _gatt_write_to_client(gatt, buf, len) + : _gatt_write_to_server(gatt, buf, len); + break; + case VINE_GATT_ROLE_UNKNOWN: + default: + ret = VINE_DATA_PATH_ERROR_INVALID_OPERATION; + break; + } + + return ret; } int gatt_close(vine_dp_plugin_h handle) diff --git a/src/include/vine-data-path-state.h b/src/include/vine-data-path-state.h index 7ac17ba..c20b1a5 100644 --- a/src/include/vine-data-path-state.h +++ b/src/include/vine-data-path-state.h @@ -27,7 +27,7 @@ // It will be removed when vine-data-path-state is changed. typedef void *vine_data_path_h; -#define AUTH_CONNECTED_TIMEOUT_MS 5000 +#define AUTH_CONNECTED_TIMEOUT_MS 15000 #define AUTH_REQUEST_TIMEOUT_MS 5000 #define AUTH_RESPONSE_TIMEOUT_MS 5000 diff --git a/src/vine-data-path.cpp b/src/vine-data-path.cpp index e2fa7f5..c0aac6e 100755 --- a/src/vine-data-path.cpp +++ b/src/vine-data-path.cpp @@ -284,7 +284,7 @@ static void __accepted_cb(vine_dp_addr_family_e addr_family, char *addr, vine_data_path_s *listen_dp = (vine_data_path_s *)user_data; - VINE_LOGE("listen_dp[%p], security[%p]", listen_dp, listen_dp->security); + VINE_LOGI("listen_dp[%p], security[%p]", listen_dp, listen_dp->security); vine_data_path_s *connected_dp = _vine_data_path_create(listen_dp->method, __convert_addr_family(addr_family), addr, port, listen_dp->security, plugin_data, listen_dp->event_queue); -- 2.7.4 From 165d2cc9a8c4f0e991cdf8bb06b2a15335f03c6f Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Fri, 9 Jul 2021 15:10:24 +0900 Subject: [PATCH 13/16] Keep client list in GATT server handle BT GATT server api doens't create a new handle each connection. But DataPath is designed that new handle is created whenever connected with a peer. In this patch, to compatibility, GATT server will manage a client list. Change-Id: Ica3971031ae2e348ad1726057336de830b0ced0b --- plugins/ble-gatt/ble-gatt-plugin.cpp | 191 ++++++++++++++++++++++++++++------- 1 file changed, 152 insertions(+), 39 deletions(-) diff --git a/plugins/ble-gatt/ble-gatt-plugin.cpp b/plugins/ble-gatt/ble-gatt-plugin.cpp index e428706..45a1793 100755 --- a/plugins/ble-gatt/ble-gatt-plugin.cpp +++ b/plugins/ble-gatt/ble-gatt-plugin.cpp @@ -16,6 +16,7 @@ */ #include +#include #include "vine-data-path-plugin.h" #include "vine-log.h" @@ -37,6 +38,8 @@ typedef enum { VINE_GATT_ROLE_CLIENT, } vine_gatt_role_e; +typedef struct vine_gatt_s vine_gatt_s; + typedef struct { char *buf; size_t len; @@ -45,22 +48,30 @@ typedef struct { } gatt_data_s; typedef struct { + bt_gatt_server_h server; + std::map *client_list; +} gatt_server_s; + +typedef struct { + bt_gatt_client_h client; + bool is_accepted; +} gatt_client_s; + +struct vine_gatt_s { bt_gatt_h service; bt_gatt_h characteristic; bt_gatt_h descriptor; vine_gatt_role_e type; union { - bt_gatt_server_h server; - bt_gatt_client_h client; + gatt_server_s *server; + gatt_client_s *client; } role; VineQueue *recv_buffer; - - char *remote_address; // this is used for VINE_GATT_ROLE_CLIENT only. - bool is_accepted; + char *remote_address; void *user; // vine_data_path_h -} vine_gatt_s; +}; static vine_dp_plugin_callbacks g_callbacks = { .pollfd_cb = NULL, @@ -117,26 +128,64 @@ static void __destroy_gatt_data(gatt_data_s *data) free(data); } -static void __invoke_accepted_cb(const char *remote_address, vine_gatt_s *gatt, void *user_data) +static gatt_server_s *_create_gatt_server(bt_gatt_server_h gatt_server) { - if (!g_callbacks.accepted_cb) - return; + RET_VAL_IF(gatt_server == NULL, NULL, "Invalid parameter."); - vine_gatt_s *accepted_gatt = _create_gatt(); - RET_IF(accepted_gatt == NULL, "Failed to create accepted_gatt."); + gatt_server_s *server = (gatt_server_s *)calloc(1, sizeof(gatt_server_s)); + RET_VAL_IF(server == NULL, NULL, "Out of memory."); - accepted_gatt->type = VINE_GATT_ROLE_CLIENT; - accepted_gatt->remote_address = STRDUP(remote_address); + server->server = gatt_server; + server->client_list = new std::map; + return server; +} - // refer to server's gatt handles. - accepted_gatt->service = gatt->service; - accepted_gatt->characteristic = gatt->characteristic; - accepted_gatt->descriptor = gatt->descriptor; +static void _destroy_gatt_server(gatt_server_s *server) +{ + RET_IF(server == NULL, "Invalid parameter."); + bt_gatt_server_destroy(server->server); + server->server = NULL; + delete server->client_list; +} - accepted_gatt->is_accepted = true; - accepted_gatt->user = user_data; +static gatt_client_s *_create_gatt_client(bt_gatt_client_h gatt_client, bool is_accepted) +{ + gatt_client_s *client = (gatt_client_s *)calloc(1, sizeof(gatt_client_s)); + RET_VAL_IF(client == NULL, NULL, "Out of memory."); - g_callbacks.accepted_cb(VINE_DP_NOT_IP, accepted_gatt->remote_address, 0, accepted_gatt, user_data); + client->client = gatt_client; // gatt_client can be NULL. + client->is_accepted = is_accepted; + return client; +} + +static void _destroy_gatt_client(gatt_client_s *client) +{ + RET_IF(client == NULL, "Invalid parameter."); + bt_gatt_client_destroy(client->client); + client->client = NULL; +} + +static vine_gatt_s *__find_client_gatt(vine_gatt_s *gatt, const char *address) +{ + RET_VAL_IF(gatt == NULL, NULL, "Invalid parameter."); + RET_VAL_IF(address == NULL, NULL, "Invalid parameter."); + RET_VAL_IF(gatt->role.server == NULL, NULL, "Invalid parameter."); + RET_VAL_IF(gatt->role.server->client_list == NULL, NULL, "Invalid parameter."); + + std::map::iterator it; + + it = gatt->role.server->client_list->find(address); + if (it == gatt->role.server->client_list->end()) + return NULL; + + return (vine_gatt_s *)it->second; +} + +static void __invoke_accepted_cb(vine_gatt_s *gatt, void *user_data) +{ + if (!g_callbacks.accepted_cb) + return; + g_callbacks.accepted_cb(VINE_DP_NOT_IP, gatt->remote_address, 0, gatt, user_data); } static void __invoke_connected_cb(int result, void *user_data) @@ -174,12 +223,14 @@ static void __gatt_server_write_value_requested_cb(const char *remote_address, VINE_LOGI("Got write value requestment from %s.", remote_address); vine_gatt_s *gatt = (vine_gatt_s *)user_data; + vine_gatt_s *client_gatt = __find_client_gatt(gatt, remote_address); + RET_IF(client_gatt == NULL, "Cannot find a client[%s].", remote_address); // TODO: Need to handle splited data using offset. gatt_data_s *recv_data = __create_gatt_data(value, len, true); RET_IF(recv_data == NULL, "recv_data is NULL"); - gatt->recv_buffer->push(recv_data); + client_gatt->recv_buffer->push(recv_data); VINE_LOGI("Write value requested. offset[%d] len[%d] reponse_needed[%d]", offset, len, response_needed); @@ -189,7 +240,7 @@ static void __gatt_server_write_value_requested_cb(const char *remote_address, VINE_LOGE("bt_gatt_server_send_response() is failed."); if (g_callbacks.received_cb) - g_callbacks.received_cb(len, gatt->user); + g_callbacks.received_cb(len, client_gatt->user); } void __gatt_server_noti_state_changed_cb(bool notify, bt_gatt_server_h server, @@ -256,7 +307,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 characteristic = NULL; - int ret; + int ret = BT_ERROR_OPERATION_FAILED; ret = bt_gatt_client_create(remote_address, &client); if (ret != BT_ERROR_NONE || !client) @@ -279,11 +330,15 @@ static int __update_gatt_service_info(const char *remote_address, vine_gatt_s *g if (ret != BT_ERROR_NONE) goto ERR; - gatt->role.client = client; + gatt->role.client = _create_gatt_client(client, false); + if (!gatt->role.client) + goto ERR; + gatt->service = service; gatt->characteristic = characteristic; + gatt->remote_address = STRDUP(remote_address); - VINE_LOGE("Succeeded to update GATT service info."); + VINE_LOGI("Succeeded to update GATT service info."); return VINE_DATA_PATH_ERROR_NONE; ERR: @@ -292,6 +347,57 @@ ERR: return __convert_bt_error_to_data_path_error(ret); } +static vine_gatt_s *__create_accepted_gatt(const char *remote_address, vine_gatt_s *gatt, void *user) +{ + vine_gatt_s *accepted_gatt = _create_gatt(); + RET_VAL_IF(accepted_gatt == NULL, NULL, "Failed to create accepted_gatt."); + + accepted_gatt->type = VINE_GATT_ROLE_CLIENT; + accepted_gatt->role.client = _create_gatt_client(NULL, true); + if (!accepted_gatt->role.client) { + VINE_LOGE("Failed to create accepted_gatt."); + free(accepted_gatt); + return NULL; + } + + 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->user = user; + return accepted_gatt; +} + +static void __handle_connected_client(vine_gatt_s *gatt, const char *address) +{ + RET_IF(gatt == NULL, "Invalid parameter."); + RET_IF(address == NULL, "Invalid parameter."); + RET_IF(gatt->role.server == NULL || gatt->role.server->client_list == NULL, "Invalid parameter."); + + vine_gatt_s *accepted_gatt = __create_accepted_gatt(address, gatt, gatt->user); + RET_IF(accepted_gatt == NULL, "Failed to create accepted gatt."); + + gatt->role.server->client_list->insert(std::make_pair(string(address), accepted_gatt)); + __invoke_accepted_cb(accepted_gatt, accepted_gatt->user); + VINE_LOGI("%s is connected.", address); +} + +static void __handle_disconnected_client(vine_gatt_s *gatt, const char *address) +{ + RET_IF(gatt == NULL, "Invalid parameter."); + RET_IF(address == NULL, "Invalid parameter."); + RET_IF(gatt->role.server == NULL || gatt->role.server->client_list, "Invalid 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); + __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) { @@ -299,16 +405,19 @@ static void __gatt_connection_state_changed_cb(int result, bool connected, vine_gatt_s *gatt = (vine_gatt_s *)user_data; - VINE_LOGI("gatt[%p] result[%d] connected[%d] remote address[%s]", - gatt, result, connected, remote_address); + VINE_LOGI("gatt[%p] result[%d] connected[%d] remote address[%s] role[%d]", + gatt, result, connected, remote_address, gatt->type); if (!connected) { - __invoke_terminated_cb(gatt->user); + 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) { - __invoke_accepted_cb(remote_address, gatt, gatt->user); + 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); @@ -460,14 +569,14 @@ int gatt_destroy(vine_dp_plugin_h handle) vine_gatt_s *gatt = (vine_gatt_s *)handle; if (gatt->type == VINE_GATT_ROLE_SERVER) { - bt_gatt_server_destroy(gatt->role.server); + _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); } else if (gatt->type == VINE_GATT_ROLE_CLIENT) { // bt_gatt_h handles will be freed during bt_gatt_client_destroy(). - bt_gatt_client_destroy(gatt->role.client); + _destroy_gatt_client(gatt->role.client); gatt->role.client = NULL; } @@ -534,7 +643,10 @@ int gatt_open(vine_dp_plugin_h handle, int addr_family, } gatt->type = VINE_GATT_ROLE_SERVER; - gatt->role.server = server; + gatt->role.server = _create_gatt_server(server); + if (gatt->role.server == NULL) + goto ERR; + gatt->service = service; gatt->characteristic = characteristic; gatt->descriptor = descriptor; @@ -566,19 +678,16 @@ int gatt_connect(vine_dp_plugin_h handle, int addr_family, RET_VAL_IF(addr == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "addr is NULL"); vine_gatt_s *gatt = (vine_gatt_s *)handle; - bt_gatt_client_h client = NULL; int ret; + 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; return __convert_bt_error_to_data_path_error(ret); } - gatt->type = VINE_GATT_ROLE_CLIENT; - gatt->role.client = client; - gatt->remote_address = STRDUP(addr); - VINE_LOGI("Succeed to request to GATT connect."); return VINE_DATA_PATH_ERROR_NONE; } @@ -645,7 +754,11 @@ int gatt_write(vine_dp_plugin_h handle, unsigned char *buf, size_t len) ret =_gatt_write_to_client(gatt, buf, len); break; case VINE_GATT_ROLE_CLIENT: - ret = gatt->is_accepted ? _gatt_write_to_client(gatt, buf, len) + if (!gatt->role.client) { + ret = VINE_DATA_PATH_ERROR_OPERATION_FAILED; + break; + } + ret = gatt->role.client->is_accepted ? _gatt_write_to_client(gatt, buf, len) : _gatt_write_to_server(gatt, buf, len); break; case VINE_GATT_ROLE_UNKNOWN: -- 2.7.4 From 1671247e392df287e3130cbef465461555e93303 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Mon, 12 Jul 2021 18:34:51 +0900 Subject: [PATCH 14/16] vine-tool: terminate a tool when receiving interrupt signal - fix vine-tool bug - increase the version number for BLE GATT Change-Id: I42841ceb7ef72bfa8d17c19da16d30444e0740a0 --- packaging/capi-network-vine.spec | 2 +- tool/tool_run.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packaging/capi-network-vine.spec b/packaging/capi-network-vine.spec index 1aa666a..71a4b99 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.3 +Version: 1.1.4 Release: 0 Group: Network & Connectivity/API License: Apache-2.0 diff --git a/tool/tool_run.cpp b/tool/tool_run.cpp index d5e7e84..c74933b 100755 --- a/tool/tool_run.cpp +++ b/tool/tool_run.cpp @@ -632,9 +632,8 @@ void stop_event_loop() #ifdef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB if (main_loop) g_main_loop_quit(main_loop); -#else - interrupt_flag = 1; #endif + interrupt_flag = 1; } static void _run_epoll_event_loop(vine_session_h session) -- 2.7.4 From 80fa6fd4d3bb625f27e3cc6dbe97e023716d1449 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Mon, 12 Jul 2021 19:38:11 +0900 Subject: [PATCH 15/16] Implement close function for GATT plugin Change-Id: I87a9ba031d8e02166b22eb4aebdd1c6b7f31f92f --- plugins/ble-gatt/ble-gatt-plugin.cpp | 25 ++++++++++++++++++++++--- src/vine-data-path.cpp | 2 +- tool/tool_run.cpp | 2 +- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/plugins/ble-gatt/ble-gatt-plugin.cpp b/plugins/ble-gatt/ble-gatt-plugin.cpp index 45a1793..09f5792 100755 --- a/plugins/ble-gatt/ble-gatt-plugin.cpp +++ b/plugins/ble-gatt/ble-gatt-plugin.cpp @@ -267,8 +267,15 @@ void __gatt_server_noti_sent_cb(int result, static void __gatt_client_service_changed_cb(bt_gatt_client_h client, bt_gatt_client_service_change_type_e type, const char *uuid, void *user_data) { - VINE_LOGI("gatt[%p] service[%s] is %s", - type == BT_GATT_CLIENT_SERVICE_ADDED ? "added." : "removed." ); + VINE_LOGI("gatt[%p] service uuid[%s] is %s", + user_data, uuid, type == BT_GATT_CLIENT_SERVICE_ADDED ? "added." : "removed." ); + + RET_IF(user_data == NULL, "user_data is NULL"); + // Should added state be handled? + RET_IF(type == BT_GATT_CLIENT_SERVICE_ADDED, "service is added."); + + vine_gatt_s *gatt = (vine_gatt_s *)user_data; + __invoke_terminated_cb(gatt->user); } void __gatt_client_write_complete_cb(int result, bt_gatt_h gatt_handle, void *user_data) @@ -772,7 +779,19 @@ int gatt_write(vine_dp_plugin_h handle, unsigned char *buf, size_t len) int gatt_close(vine_dp_plugin_h handle) { - return VINE_DATA_PATH_ERROR_NONE; + RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL"); + + vine_gatt_s *gatt = (vine_gatt_s *)handle; + int ret; + + if (gatt->type == VINE_GATT_ROLE_SERVER && gatt->role.server) { + ret = bt_gatt_server_unregister_service(gatt->role.server->server, gatt->service); + VINE_LOGI("Unregister service[%p]", gatt->service); + } else if (gatt->type == VINE_GATT_ROLE_CLIENT) { + ret = bt_gatt_disconnect(gatt->remote_address); + VINE_LOGI("Disconnect from %s", gatt->remote_address); + } + return __convert_bt_error_to_data_path_error(ret); } int gatt_get_local_address_info(vine_dp_plugin_h handle, diff --git a/src/vine-data-path.cpp b/src/vine-data-path.cpp index c0aac6e..5dce302 100755 --- a/src/vine-data-path.cpp +++ b/src/vine-data-path.cpp @@ -484,7 +484,7 @@ int vine_data_path_close(vine_data_path_h datapath) RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL"); vine_data_path_s *dp = (vine_data_path_s *)datapath; - RET_VAL_IF(!dp->plugin_fn || dp->plugin_fn->close, + RET_VAL_IF(!dp->plugin_fn || !dp->plugin_fn->close, VINE_ERROR_INVALID_PARAMETER, "plugin_fn is NULL"); dp->plugin_fn->close(dp->plugin_handle); diff --git a/tool/tool_run.cpp b/tool/tool_run.cpp index c74933b..12df100 100755 --- a/tool/tool_run.cpp +++ b/tool/tool_run.cpp @@ -141,7 +141,7 @@ static void __received_cb(vine_dp_h dp, size_t received_len, void *user_data) static void __terminated_cb(vine_dp_h dp, void *user_data) { - printf("peer is terminated.\n"); + printf("peer[%p] is terminated.\n", dp); _stop_message_timer(dp); } -- 2.7.4 From 8c0434722cab97005072106ca598edc423ca9ac7 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Wed, 14 Jul 2021 14:18:44 +0900 Subject: [PATCH 16/16] Fix svace issues Change-Id: I3ba728610e840d98d1b9ed50864589708c37c105 --- plugins/ble-gatt/ble-gatt-plugin.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/ble-gatt/ble-gatt-plugin.cpp b/plugins/ble-gatt/ble-gatt-plugin.cpp index 09f5792..56802c4 100755 --- a/plugins/ble-gatt/ble-gatt-plugin.cpp +++ b/plugins/ble-gatt/ble-gatt-plugin.cpp @@ -395,7 +395,8 @@ static void __handle_disconnected_client(vine_gatt_s *gatt, const char *address) { RET_IF(gatt == NULL, "Invalid parameter."); RET_IF(address == NULL, "Invalid parameter."); - RET_IF(gatt->role.server == NULL || gatt->role.server->client_list, "Invalid parameter."); + RET_IF(gatt->role.server == NULL + || gatt->role.server->client_list == NULL, "Invalid parameter."); vine_gatt_s *client_gatt = __find_client_gatt(gatt, address); RET_IF(client_gatt == NULL, "Cannot find a client[%s].", address); @@ -632,7 +633,7 @@ int gatt_open(vine_dp_plugin_h handle, int addr_family, } descriptor = _add_gatt_descriptor(characteristic); - if (!characteristic) { + if (!descriptor) { VINE_LOGE("Failed to add descriptor."); goto ERR; } @@ -782,7 +783,7 @@ int gatt_close(vine_dp_plugin_h handle) RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL"); vine_gatt_s *gatt = (vine_gatt_s *)handle; - int ret; + int ret = BT_ERROR_NONE; if (gatt->type == VINE_GATT_ROLE_SERVER && gatt->role.server) { ret = bt_gatt_server_unregister_service(gatt->role.server->server, gatt->service); -- 2.7.4