PROPERTIES
SOVERSION ${BLE_GATT_PLUGIN_VERSION_MAJOR}
)
+find_library(
+ LIBCRYPTO
+ NAMES libcrypto.so
+ HINTS /usr/local/lib /usr/lib /usr/lib64 /usr/lib/x86_64-linux-gnu
+ REQUIRED
+)
+
+find_library(
+ LIBSSL
+ NAMES libssl.so
+ HINTS /usr/local/lib /usr/lib /usr/lib64 /usr/lib/x86_64-linux-gnu
+ REQUIRED
+)
TARGET_LINK_LIBRARIES(${BLE_GATT_PLUGIN}
${VINE_LOGGER}
${BLE_DEPS_LIBRARIES}
+ ${LIBCRYPTO}
+ ${LIBSSL}
${fw_name_deps_LIBRARIES}
dl
)
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * RFC 4122 - A Universally Unique IDentifier (UUID) URN Namespace
+ * uuid_create_sha1_from_name and format_uuid_v3or5 are adapted to get UUID.
+ * These are copyrighted by following licenses.
+ *
+ * Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
+ * Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. &
+ * Digital Equipment Corporation, Maynard, Mass.
+ * Copyright (c) 1998 Microsoft.
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty: permission to use, copy,
+ * modify, and distribute this file for any purpose is hereby
+ * granted without fee, provided that the above copyright notices and
+ * this notice appears in all source code copies, and that none of
+ * the names of Open Software Foundation, Inc., Hewlett-Packard
+ * Company, Microsoft, or Digital Equipment Corporation be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Neither Open Software
+ * Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital
+ * Equipment Corporation makes any representations about the
+ * suitability of this software for any purpose.
+ *
+*/
+
+#include <arpa/inet.h>
+#include <openssl/sha.h>
+#include <string>
+
+#include "ble-gatt-plugin-utils.h"
+#include "vine-data-path-plugin.h"
+#include "vine-utils.h"
+
+using namespace std;
+
+// Hexadecimal representation
+// [time_low]-[time_mid]-[time_hi_and_version]-[clock_seq_hi_and_reserved clock_seq_low]-[node]
+// 8-4-4-4-12
+typedef struct {
+ unsigned int time_low; // 32bits
+ unsigned short time_mid; // 16 bits
+ unsigned short time_hi_and_version; // 16bits
+ unsigned char clock_seq_hi_and_reserved; // 8bits
+ unsigned char clock_seq_low; // 8bits
+ unsigned char node[6]; // 48bits
+} uuid_t;
+
+// Name space for Vine
+// 931da289-042b-4372-9fb9-299640817a15
+uuid_t NameSpace_Vine = {
+ 0x931da289,
+ 0x042b,
+ 0x4372,
+ 0x9f, 0xb9,
+ 0x29, 0x96, 0x40, 0x81, 0x7a, 0x15
+};
+
+static void format_uuid_v5(uuid_t *uuid, unsigned char hash[16])
+{
+ int version = 5;
+ /* convert UUID to local byte order */
+ memcpy(uuid, hash, sizeof *uuid);
+ uuid->time_low = ntohl(uuid->time_low);
+ uuid->time_mid = ntohs(uuid->time_mid);
+ uuid->time_hi_and_version = ntohs(uuid->time_hi_and_version);
+
+ /* put in the variant and version bits */
+ uuid->time_hi_and_version &= 0x0FFF;
+ uuid->time_hi_and_version |= (version << 12);
+ uuid->clock_seq_hi_and_reserved &= 0x3F;
+ uuid->clock_seq_hi_and_reserved |= 0x80;
+}
+
+static void uuid_create_sha1_from_name(uuid_t *uuid, uuid_t nsid, const void *name, int name_len)
+{
+ SHA_CTX c;
+ unsigned char hash[20];
+ uuid_t net_nsid;
+
+ /* put name space ID in network byte order so it hashes the same
+ no matter what endian machine we're on */
+ net_nsid = nsid;
+ net_nsid.time_low = htonl(net_nsid.time_low);
+ net_nsid.time_mid = htons(net_nsid.time_mid);
+ net_nsid.time_hi_and_version = htons(net_nsid.time_hi_and_version);
+
+ SHA1_Init(&c);
+ SHA1_Update(&c, &net_nsid, sizeof net_nsid);
+ SHA1_Update(&c, name, name_len);
+ SHA1_Final(hash, &c);
+
+ /* the hash is in network byte order at this point */
+ format_uuid_v5(uuid, hash);
+}
+
+int gatt_utils_get_uuid(const char *token, const char *extra, char uuid_str[])
+{
+ RET_VAL_IF(token == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "token is NULL");
+ RET_VAL_IF(uuid_str == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "uuid_str is NULL");
+
+ VINE_LOGD("token: %s, extra: %s", token, extra);
+
+ uuid_t uuid;
+ string name = token;
+
+ if (extra)
+ name += extra;
+ uuid_create_sha1_from_name(&uuid, NameSpace_Vine, name.c_str(), name.size());
+
+ snprintf(uuid_str, GATT_UUID_STR_LEN + 1, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
+ uuid.clock_seq_hi_and_reserved,
+ uuid.clock_seq_low,
+ uuid.node[0], uuid.node[1], uuid.node[2],
+ uuid.node[3], uuid.node[4], uuid.node[5]);
+
+ VINE_LOGI("UUID: %s", uuid_str);
+
+ return VINE_DATA_PATH_ERROR_NONE;
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#pragma once
+
+#define GATT_UUID_STR_LEN 36
+int gatt_utils_get_uuid(const char *token, const char *extra, char uuid_str[]);
#include <sys/eventfd.h>
#include "vine-data-path-plugin.h"
+#include "vine-constants.h"
#include "vine-log.h"
#include "vine-utils.h"
#include "vine-queue.h"
+#include "ble-gatt-plugin-utils.h"
using namespace std;
-// TODO: change UUIDs
-#define VINE_GATT_SERVICE_UUID "000018f2-0000-1000-8000-00805f9b34fb"
-#define VINE_GATT_CONNECTION_CHAR_UUID "5fbfd598-ab0f-4c20-9966-60a11a41e974"
-#define VINE_GATT_READ_WRITE_CHAR_UUID "00002af6-0000-1000-8000-00805f9b34fb"
-#define VINE_GATT_DESC_UUID "fa87c0d0-afac-11de-8a39-0800200c9a66"
+#define VINE_GATT_UUID_NAME_CONNECTION "Connection"
+#define VINE_GATT_UUID_NAME_READ_WRITE "ReadWrite"
// 2-way handshake for VINE GATT connection
#define VINE_GATT_CONNECTION_SYN "VINE_GATT_CONNECTION_SYN"
VineQueue<gatt_data_s *> *write_buffer;
bool ready_to_write;
char *remote_address;
+ char *token;
void *user; // vine_data_path_h
};
if (gatt->type == VINE_GATT_ROLE_SERVER) {
bt_gatt_server_notify_characteristic_changed_value(gatt->connection_char,
__send_conn_fin_to_client_completed_cb, gatt->remote_address, (void *)gatt);
- } else if (gatt->type = VINE_GATT_ROLE_CLIENT) {
+ } else if (gatt->type == VINE_GATT_ROLE_CLIENT) {
bt_gatt_client_write_value(gatt->connection_char,
__send_conn_fin_to_server_completed_cb, (void *)gatt);
}
bt_gatt_h service = NULL;
bt_gatt_h connection_char = NULL;
bt_gatt_h characteristic = NULL;
+ char uuid[GATT_UUID_STR_LEN + 1] = {0, };
int ret = BT_ERROR_OPERATION_FAILED;
ret = bt_gatt_client_create(remote_address, &client);
if (ret != BT_ERROR_NONE)
goto ERR;
- ret = bt_gatt_client_get_service(client, VINE_GATT_SERVICE_UUID, &service);
+ ret = gatt_utils_get_uuid(gatt->token, NULL, uuid);
+ if (ret != VINE_DATA_PATH_ERROR_NONE) {
+ VINE_LOGE("Failed to get servce uuid.");
+ goto ERR;
+ }
+
+ ret = bt_gatt_client_get_service(client, uuid, &service);
if (ret != BT_ERROR_NONE)
goto ERR;
- ret = bt_gatt_service_get_characteristic(service,
- VINE_GATT_CONNECTION_CHAR_UUID, &connection_char);
+ ret = gatt_utils_get_uuid(gatt->token, VINE_GATT_UUID_NAME_CONNECTION, uuid);
+ if (ret != VINE_DATA_PATH_ERROR_NONE) {
+ VINE_LOGE("Failed to get connection char uuid.");
+ goto ERR;
+ }
+
+ ret = bt_gatt_service_get_characteristic(service, uuid, &connection_char);
if (ret != BT_ERROR_NONE)
goto ERR;
goto ERR;
}
- ret = bt_gatt_service_get_characteristic(service,
- VINE_GATT_READ_WRITE_CHAR_UUID, &characteristic);
+ ret = gatt_utils_get_uuid(gatt->token, VINE_GATT_UUID_NAME_READ_WRITE, uuid);
+ if (ret != VINE_DATA_PATH_ERROR_NONE) {
+ VINE_LOGE("Failed to get read write char uuid.");
+ goto ERR;
+ }
+
+ ret = bt_gatt_service_get_characteristic(service, uuid, &characteristic);
if (ret != BT_ERROR_NONE)
goto ERR;
}
static void __gatt_connection_state_changed_cb(int result, bool connected,
- const char *remote_address, void *user_data)
+ const char *remote_address, void *user_data)
{
VINE_LOGI("result[%d] connected[%d] remote address[%s]", result, connected, remote_address);
gatt->read_write_desc = NULL;
free(gatt->remote_address);
gatt->remote_address = NULL;
+ free(gatt->token);
+ gatt->token = NULL;
free(gatt);
return VINE_DATA_PATH_ERROR_NONE;
bt_gatt_h connection_desc = NULL;
bt_gatt_h read_write_char = NULL;
bt_gatt_h read_write_desc = NULL;
+ char uuid[GATT_UUID_STR_LEN + 1] = {0, };
int ret = BT_ERROR_OPERATION_FAILED;
// This returns OPERATION_FAILED when already initialized. ignore it.
goto ERR;
}
- ret = bt_gatt_service_create(VINE_GATT_SERVICE_UUID, BT_GATT_SERVICE_TYPE_PRIMARY, &service);
+ ret = gatt_utils_get_uuid(gatt->token, NULL, uuid);
+ if (ret != VINE_DATA_PATH_ERROR_NONE) {
+ VINE_LOGE("Failed to get servce uuid.");
+ goto ERR;
+ }
+
+ ret = bt_gatt_service_create(uuid, BT_GATT_SERVICE_TYPE_PRIMARY, &service);
if (ret != BT_ERROR_NONE) {
VINE_LOGE("Failed to create service.");
goto ERR;
}
- connection_char = _add_gatt_characteristic(service, VINE_GATT_CONNECTION_CHAR_UUID,
+ ret = gatt_utils_get_uuid(gatt->token, VINE_GATT_UUID_NAME_CONNECTION, uuid);
+ if (ret != VINE_DATA_PATH_ERROR_NONE) {
+ VINE_LOGE("Failed to get connection char uuid.");
+ goto ERR;
+ }
+
+ connection_char = _add_gatt_characteristic(service, uuid,
__gatt_server_read_connection_value_requested_cb,
__gatt_server_write_connection_value_requested_cb,
__gatt_server_noti_connection_state_changed_cb, handle);
goto ERR;
}
- read_write_char = _add_gatt_characteristic(service, VINE_GATT_READ_WRITE_CHAR_UUID,
+ ret = gatt_utils_get_uuid(gatt->token, VINE_GATT_UUID_NAME_READ_WRITE, uuid);
+ if (ret != VINE_DATA_PATH_ERROR_NONE) {
+ VINE_LOGE("Failed to get read write char uuid.");
+ goto ERR;
+ }
+
+ read_write_char = _add_gatt_characteristic(service, uuid,
__gatt_server_read_value_requested_cb,
__gatt_server_write_value_requested_cb,
__gatt_server_noti_state_changed_cb, handle);
int gatt_set_token(vine_dp_plugin_h handle, const char *token)
{
+ RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL");
+ RET_VAL_IF(token == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "token is NULL");
+
+ vine_gatt_s *gatt = (vine_gatt_s *)handle;
+ int len = strlen(token);
+ if (len < 0 || len > VINE_MAX_SERVICE_TYPE_LEN)
+ return -1;
+
+ if (gatt->token)
+ free(gatt->token);
+ gatt->token = strdup(token);
return VINE_DATA_PATH_ERROR_NONE;
}
int gatt_get_token(vine_dp_plugin_h handle, char **token)
{
+ RET_VAL_IF(handle == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "handle is NULL");
+ RET_VAL_IF(token == NULL, VINE_DATA_PATH_ERROR_INVALID_PARAMETER, "token is NULL");
+
+ vine_gatt_s *gatt = (vine_gatt_s *)handle;
+ if (strlen(gatt->token) == 0) {
+ *token = NULL;
+ return VINE_DATA_PATH_ERROR_INVALID_OPERATION;
+ }
+
+ *token = strdup(gatt->token);
return VINE_DATA_PATH_ERROR_NONE;
}
int vine_data_path_open(vine_data_path_method_e method,
vine_address_family_e addr_family, int port,
const char *iface_name, int max_conn,
- vine_security_h security, const char *host_name,
+ vine_security_h security, const char *host_name, const char *token,
vine_data_path_opened_cb opened_cb, void *opened_cb_data,
vine_data_path_accepted_cb accepted_cb, void *accepted_cb_data,
vine_data_path_h *opened_datapath,
int vine_data_path_open(vine_data_path_method_e method,
vine_address_family_e addr_family, int port, const char *iface_name,
- int max_conn, vine_security_h security, const char *host_name,
+ int max_conn, vine_security_h security, const char *host_name, const char *token,
vine_data_path_opened_cb opened_cb, void *opened_cb_data,
vine_data_path_accepted_cb accepted_cb, void *accepted_cb_data,
vine_data_path_h *opened_datapath,
}
}
+ if (token && dp->plugin_fn->set_token) {
+ ret = dp->plugin_fn->set_token(dp->plugin_handle, token);
+ if (ret != VINE_DATA_PATH_ERROR_NONE) {
+ vine_data_path_destroy(dp);
+ _destroy_security_info(&ssl);
+ return __convert_data_path_error_to_vine_error((vine_data_path_error)ret);
+ }
+ }
+
ret = dp->plugin_fn->open(dp->plugin_handle, dp_addr_family, port, iface_name, max_conn, ssl);
_destroy_security_info(&ssl);
{
RET_ERR_IF_DP_OPEN_STATE_ISNT_IDLE(mOpenState);
+ int ret;
+ char *service_type = NULL;
+
+ if (mService && mMethod == VINE_DATA_PATH_METHOD_BLE_GATT) {
+ ret = vine_service_get_type(mService, &service_type);
+ if (ret != VINE_ERROR_NONE)
+ return ret;
+ }
+
mOpenedCb = callback;
mOpenedCbData = user_data;
mOpenState = VINE_DP_OPEN_STATE_WAIT;
- int ret = vine_data_path_open(mMethod,
+ ret = vine_data_path_open(mMethod,
mAddrFamily, mListenPort,
mIfaceName.size() > 0 ? mIfaceName.c_str() : NULL,
- mMaxConnNum, mSecurity, NULL,
+ mMaxConnNum, mSecurity, NULL, service_type,
_opened_cb, static_cast<void *>(this),
_accepted_cb, static_cast<void *>(this),
&mDataPath, mEventQueue);
RET_VAL_IF(isCreatedByServerDp, VINE_ERROR_INVALID_OPERATION, "cannot open");
RET_ERR_IF_DP_OPEN_STATE_ISNT_IDLE(mOpenState);
+ int ret;
+ char *service_type = NULL;
+
+ if (mService && mMethod == VINE_DATA_PATH_METHOD_BLE_GATT) {
+ ret = vine_service_get_type(mService, &service_type);
+ if (ret != VINE_ERROR_NONE)
+ return ret;
+ }
+
mOpenedCb = callback;
mOpenedCbData = user_data;
mOpenState = VINE_DP_OPEN_STATE_WAIT;
- int ret = vine_data_path_connect(mMethod,
+ ret = vine_data_path_connect(mMethod,
mAddrFamily,
mMethod == VINE_DATA_PATH_METHOD_BLE_GATT ? mPeerAddr.c_str() : mPeerIp.c_str(),
mPeerPort,
mIfaceName.size() > 0 ? mIfaceName.c_str() : NULL,
- mSecurity, NULL, NULL,
+ mSecurity, NULL, service_type,
_connected_cb, static_cast<void *>(this), &mDataPath, mEventQueue);
if (ret != VINE_ERROR_NONE)
mOpenState = VINE_DP_OPEN_STATE_NONE;
int ret = vine_data_path_open(mMethod,
mAddrFamily, mListenPort,
mIfaceName.size() > 0 ? mIfaceName.c_str() : NULL,
- mMaxConnNum, mSecurity, mId.c_str(),
+ mMaxConnNum, mSecurity, mId.c_str(), NULL,
_pubsub_opened_cb, static_cast<void *>(this),
_pubsub_accepted_cb, static_cast<void *>(this),
&mServerDataPath, mEventQueue);
if (vine_configs.with_ble) {
vine_dp_set_method(vine_configs.dp, VINE_DP_METHOD_BLE_GATT);
- vine_dp_set_remote_address(vine_configs.dp, tool_config_get_remote_address());
+ if (type == VINE_DP_TYPE_CLIENT) {
+ vine_service_create(&vine_configs.service);
+ vine_service_set_type(vine_configs.service, tool_config_get_service_type());
+ }
+ vine_dp_set_remote_address(vine_configs.dp, tool_config_get_remote_address());
+ vine_dp_set_service(vine_configs.dp, vine_configs.service);
}
if (type == VINE_DP_TYPE_CLIENT) {