diff --git a/.gitignore b/.gitignore index 5f084ad34..5930eee58 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,12 @@ +# global files +*.o +*.cmd +*.tmp +*.gcda +*.gcno +whitespace_commit_checker.sh + +# android port/android/client port/android/server port/android/temp_sensor @@ -19,6 +28,7 @@ port/android/libiotivity-lite-server.* port/android/libiotivity-lite-client-server.* port/android/*.so +# linux port/linux/client port/linux/server port/linux/temp_sensor @@ -47,34 +57,7 @@ port/linux/tests/* port/linux/obj/ port/linux/onboarding_tool_creds/ port/linux/smart_lock -port/windows/vs2015/.vs/ -port/windows/vs2015/Debug/ -port/windows/vs2015/Release/ -port/windows/vs2015/simpleserver_creds/ -port/windows/vs2015/Win32/ -port/windows/vs2015/x64/ -port/windows/vs2015/onboarding_tool/Debug -port/windows/vs2015/onboarding_tool/x64 -port/windows/vs2015/*.VC.opendb -port/windows/vs2015/*.VC.db -port/windows/vs2015/*.vcxproj.user -port/zephyr/outdir/ -port/contiki/*.a -port/contiki/*.map -port/contiki/obj_native/ -port/contiki/*.native -port/contiki/symbols.* -port/openthread/output -port/esp32/build/ -port/esp32/sdkconfig -port/esp32/esp-idf/ -port/esp32/sdkconfig.old -*.o -*.cmd -*.tmp -*.gcda -*.gcno -whitespace_commit_checker.sh + port/linux/platformtest port/linux/storage_test port/linux/apitest @@ -85,7 +68,7 @@ port/linux/securitytest port/linux/simpleserver_pki port/linux/stapptest -#creds files +# creds files port/linux/client_creds port/linux/server_creds port/linux/temp_sensor_creds @@ -99,19 +82,45 @@ port/linux/multi_device_server_creds port/linux/server_multithread_linux_creds port/linux/client_multithread_linux_creds -#service -service/cloud-access/unittest/obj -service/resource-directory/client/unittest/obj +port/windows/vs2015/.vs/ +port/windows/vs2015/Debug/ +port/windows/vs2015/Release/ +port/windows/vs2015/simpleserver_creds/ +port/windows/vs2015/Win32/ +port/windows/vs2015/x64/ +port/windows/vs2015/onboarding_tool/Debug +port/windows/vs2015/onboarding_tool/x64 +port/windows/vs2015/*.VC.opendb +port/windows/vs2015/*.VC.db +port/windows/vs2015/*.vcxproj.user + +# zephyr +port/zephyr/outdir/ + +# openthread +port/openthread/output + +# esp32 +port/esp32/build/ +port/esp32/sdkconfig +port/esp32/esp-idf/ +port/esp32/sdkconfig.old -#vscode setting files +# vscode setting files .vscode -.clang-tidy +# eclipse +.settings +.project +.cproject +# cmake build folder build +build4test -python/plgd_headers.config +# sonarqube +.scannerwork -# eclipse config file -.cproject -.project +# clang-tidy +.clang-tidy +compile_commands.json diff --git a/api/oc_collection.c b/api/oc_collection.c index b9edda88e..6d78c1646 100644 --- a/api/oc_collection.c +++ b/api/oc_collection.c @@ -609,13 +609,15 @@ oc_get_next_collection_with_link(const oc_resource_t *resource, collection = (oc_collection_t *)collection->res.next; } - while (collection != NULL && collection->res.device == resource->device) { - const oc_link_t *link = (oc_link_t *)oc_list_head(collection->links); - while (link != NULL) { - if (link->resource == resource) { - return collection; + while (collection != NULL) { + if (collection->res.device == resource->device) { + const oc_link_t *link = (oc_link_t *)oc_list_head(collection->links); + while (link != NULL) { + if (link->resource == resource) { + return collection; + } + link = link->next; } - link = link->next; } collection = (oc_collection_t *)collection->res.next; } diff --git a/api/oc_core_res.c b/api/oc_core_res.c index 04132afb5..d59d8ee24 100644 --- a/api/oc_core_res.c +++ b/api/oc_core_res.c @@ -312,9 +312,10 @@ oc_create_device_resource(size_t device_count, const char *uri, const char *rt) #ifdef OC_CLOUD properties |= OC_OBSERVABLE; #endif /* OC_CLOUD */ - if (oc_strnlen(rt, OC_CHAR_ARRAY_LEN(OCF_D_RT) + 1) == - OC_CHAR_ARRAY_LEN(OCF_D_RT) && - strncmp(rt, OCF_D_RT, OC_CHAR_ARRAY_LEN(OCF_D_RT)) == 0) { + oc_string_view_t rtv = + oc_string_view(rt, oc_strnlen(rt, OC_CHAR_ARRAY_LEN(OCF_D_RT) + 1)); + if (oc_string_view_is_equal( + rtv, oc_string_view(OCF_D_RT, OC_CHAR_ARRAY_LEN(OCF_D_RT)))) { oc_core_populate_resource(OCF_D, device_count, uri, OC_IF_R | OC_IF_BASELINE, OC_IF_R, properties, oc_core_device_handler, /*put*/ NULL, @@ -392,6 +393,21 @@ oc_core_add_new_device(oc_add_new_device_t cfg) return &g_oc_device_info[device_count]; } +bool +oc_core_get_device_index(oc_uuid_t di, size_t *device) +{ + uint32_t device_count = OC_ATOMIC_LOAD32(g_device_count); + for (size_t i = 0; i < device_count; i++) { + if (oc_uuid_is_equal(g_oc_device_info[i].di, di)) { + if (device != NULL) { + *device = i; + } + return true; + } + } + return false; +} + static void oc_device_bind_rt(size_t device_index, const char *rt) { @@ -436,18 +452,18 @@ oc_device_bind_resource_type(size_t device, const char *type) oc_device_bind_rt(device, type); } -void +bool oc_store_uri(const char *s_uri, oc_string_t *d_uri) { size_t s_len = oc_strnlen(s_uri, OC_MAX_STRING_LENGTH); if (s_len >= OC_MAX_STRING_LENGTH) { OC_ERR("Invalid URI"); - return; + return false; } if (s_uri[0] == '/') { oc_set_string(d_uri, s_uri, s_len); - return; + return true; } oc_string_t uri; @@ -455,8 +471,9 @@ oc_store_uri(const char *s_uri, oc_string_t *d_uri) memcpy(oc_string(uri) + 1, s_uri, s_len); (oc_string(uri))[0] = '/'; (oc_string(uri))[s_len + 1] = '\0'; - oc_new_string(d_uri, oc_string(uri), oc_string_len(uri)); + oc_new_string(d_uri, oc_string(uri), s_len + 1); oc_free_string(&uri); + return true; } static oc_resource_t * @@ -653,13 +670,15 @@ core_is_resource_uri(const char *uri, size_t uri_len, const char *r_uri, uri = &uri[1]; --uri_len; } + oc_string_view_t uriv = oc_string_view(uri, uri_len); + if (r_uri[0] == '/') { r_uri = &r_uri[1]; --r_uri_len; } + oc_string_view_t r_uriv = oc_string_view(r_uri, r_uri_len); - return uri_len == r_uri_len && - (uri_len == 0 || memcmp(uri, r_uri, uri_len) == 0); + return oc_string_view_is_equal(uriv, r_uriv); } int diff --git a/api/oc_core_res_internal.h b/api/oc_core_res_internal.h index 02b6a993f..84aad6bf7 100644 --- a/api/oc_core_res_internal.h +++ b/api/oc_core_res_internal.h @@ -70,8 +70,10 @@ void oc_core_encode_interfaces_mask(CborEncoder *parent, unsigned iface_mask, * * @param s_uri source string (cannot be NULL) * @param d_uri destination (to be allocated) to store the uri (cannot be NULL) + * + * @return true on success */ -void oc_store_uri(const char *s_uri, oc_string_t *d_uri) OC_NONNULL(); +bool oc_store_uri(const char *s_uri, oc_string_t *d_uri) OC_NONNULL(); /** * @brief populate resource diff --git a/api/oc_uuid.c b/api/oc_uuid.c index ca076c83f..4c7f309cb 100644 --- a/api/oc_uuid.c +++ b/api/oc_uuid.c @@ -178,3 +178,10 @@ oc_uuid_is_equal(oc_uuid_t first, oc_uuid_t second) { return memcmp(first.id, second.id, OC_UUID_ID_SIZE) == 0; } + +bool +oc_uuid_is_empty(oc_uuid_t uuid) +{ + oc_uuid_t nil_uuid = { { 0 } }; + return (memcmp(&uuid, &nil_uuid, sizeof(oc_uuid_t)) == 0); +} diff --git a/api/unittest/coreresourcetest.cpp b/api/unittest/coreresourcetest.cpp index 7a18fcb73..f9a9882b1 100644 --- a/api/unittest/coreresourcetest.cpp +++ b/api/unittest/coreresourcetest.cpp @@ -26,6 +26,7 @@ #include "tests/gtest/Device.h" #include "tests/gtest/RepPool.h" #include "util/oc_macros_internal.h" +#include "util/oc_secure_string_internal.h" #ifdef OC_HAS_FEATURE_PUSH #include "api/oc_push_internal.h" @@ -46,6 +47,7 @@ static const std::string kOCFSpecVersion{ "ocf.1.0.0" }; static const std::string kOCFDataModelVersion{ "ocf.res.1.0.0" }; static constexpr size_t kDevice1ID{ 0 }; +static constexpr size_t kDevice2ID{ 1 }; static constexpr std::string_view kDevice1Name{ "Test Device 1" }; static constexpr std::string_view kDevice2Name{ "Test Device 2" }; @@ -184,6 +186,25 @@ TEST_F(TestCoreResource, EncodeInterfaces_P) encodeInterfaces(all_ifs_mask, all_ifstrs, includePrivateInterfaces); } +TEST_F(TestCoreResource, StoreURI_P) +{ + oc_string_t uri; + ASSERT_TRUE(oc_store_uri("oic/d", &uri)); + EXPECT_STREQ("/oic/d", oc_string(uri)); + oc_free_string(&uri); + + ASSERT_TRUE(oc_store_uri("/oic/d", &uri)); + EXPECT_STREQ("/oic/d", oc_string(uri)); + oc_free_string(&uri); +} + +TEST_F(TestCoreResource, StoreURI_F) +{ + oc_string_t uri; + std::string tooLong(OC_MAX_STRING_LENGTH + 1, 'a'); + ASSERT_FALSE(oc_store_uri(tooLong.c_str(), &uri)); +} + class TestCoreResourceWithDevice : public testing::Test { public: #if defined(OC_SERVER) && defined(OC_DYNAMIC_ALLOCATION) @@ -220,7 +241,7 @@ class TestCoreResourceWithDevice : public testing::Test { /*uri=*/"/oic/d", }, { - /*rt=*/"oic.d.test2", + /*rt=*/OCF_D_RT, /*name=*/std::string(kDevice2Name), /*spec_version=*/"ocf.1.0.0", /*data_model_version=*/"ocf.res.1.0.0", @@ -436,6 +457,22 @@ TEST_F(TestCoreResourceWithDevice, CoreGetResourceIsVerticalResource_P) #endif /* OC_SERVER */ } +TEST_F(TestCoreResourceWithDevice, GetDeviceIndex_P) +{ + EXPECT_TRUE( + oc_core_get_device_index(oc_core_get_device_info(kDevice1ID)->di, nullptr)); + size_t index{}; + EXPECT_TRUE( + oc_core_get_device_index(oc_core_get_device_info(kDevice2ID)->di, &index)); + EXPECT_EQ(kDevice2ID, index); +} + +TEST_F(TestCoreResourceWithDevice, GetDeviceIndex_F) +{ + oc_uuid_t invalid{}; + EXPECT_FALSE(oc_core_get_device_index(invalid, nullptr)); +} + TEST_F(TestCoreResourceWithDevice, SetName_P) { std::string name = "new name"; diff --git a/api/unittest/uuidtest.cpp b/api/unittest/uuidtest.cpp index 8110395e5..d9aade5cc 100644 --- a/api/unittest/uuidtest.cpp +++ b/api/unittest/uuidtest.cpp @@ -1,6 +1,7 @@ /****************************************************************** * * Copyright 2018 Samsung Electronics All Rights Reserved. + * Copyright 2024 ETRI 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. @@ -29,6 +30,16 @@ constexpr const char UUID2[] = "XYZabcdefghijklmnopqrstuvwxyz012"; using uuid_buffer_t = std::array; +TEST(UUID, UUIDIsNill) +{ + oc_uuid_t uuid{}; + EXPECT_TRUE(oc_uuid_is_empty(uuid)); + + oc_uuid_t uuid2{}; + oc_str_to_uuid(UUID, &uuid2); + EXPECT_FALSE(oc_uuid_is_empty(uuid2)); +} + TEST(UUID, StrToUUIDTest_P) { oc_uuid_t uuid{}; @@ -227,4 +238,4 @@ TEST(UUIDComparison, NonEmptyUUID) EXPECT_FALSE(oc_uuid_is_equal(uuid, gen_uuid)); EXPECT_FALSE(oc_uuid_is_equal(gen_uuid, uuid)); -} \ No newline at end of file +} diff --git a/include/oc_core_res.h b/include/oc_core_res.h index 84b6d2e7a..c9f181592 100644 --- a/include/oc_core_res.h +++ b/include/oc_core_res.h @@ -89,6 +89,15 @@ oc_uuid_t *oc_core_get_device_id(size_t device); */ oc_device_info_t *oc_core_get_device_info(size_t device); +/** + * @brief retrieve the index of device with given id + * + * @param di device id to be used for search + * @param[out] device device index of the device with the given id + * @return true if found + */ +bool oc_core_get_device_index(oc_uuid_t di, size_t *device); + /** * @brief retrieve the platform information * diff --git a/include/oc_uuid.h b/include/oc_uuid.h index 74d694eb7..4835723f4 100644 --- a/include/oc_uuid.h +++ b/include/oc_uuid.h @@ -28,6 +28,7 @@ #include "oc_export.h" #include "util/oc_compiler.h" +#include "util/oc_features.h" #include #include #include @@ -141,6 +142,17 @@ void oc_gen_uuid(oc_uuid_t *uuid) OC_NONNULL(); OC_API bool oc_uuid_is_equal(oc_uuid_t first, oc_uuid_t second); +/** + * @brief Check if the uuid is empty. An empty uuid is one that has all its + * bytes set to zero. + * + * @param uuid A uuid to be checked + * @return true if the uuid is empty + * @return false Otherwise + */ +OC_API +bool oc_uuid_is_empty(oc_uuid_t uuid); + #ifdef __cplusplus } #endif diff --git a/port/android/ipadapter.c b/port/android/ipadapter.c index aa69e6173..dc228895c 100644 --- a/port/android/ipadapter.c +++ b/port/android/ipadapter.c @@ -261,9 +261,6 @@ get_ip_context_for_device(size_t device) while (dev != NULL && dev->device != device) { dev = dev->next; } - if (!dev) { - return NULL; - } return dev; } @@ -1587,6 +1584,11 @@ void oc_connectivity_shutdown(size_t device) { ip_context_t *dev = get_ip_context_for_device(device); + if (dev == NULL) { + OC_WRN("no ip-context found for device(%zu)", device); + return; + } + dev->terminate = 1; if (write(dev->shutdown_pipe[1], "\n", 1) < 0) { OC_WRN("cannot wakeup network thread"); diff --git a/port/arduino/adapter/ipadapter.c b/port/arduino/adapter/ipadapter.c index 939a6ee57..5bbaabc8c 100644 --- a/port/arduino/adapter/ipadapter.c +++ b/port/arduino/adapter/ipadapter.c @@ -58,9 +58,6 @@ get_ip_context_for_device(size_t device) while (dev != NULL && dev->device != device) { dev = dev->next; } - if (!dev) { - return NULL; - } return dev; } @@ -222,6 +219,11 @@ void oc_connectivity_shutdown(size_t device) { ip_context_t *dev = get_ip_context_for_device(device); + if (dev == NULL) { + OC_WRN("no ip-context found for device(%zu)", device); + return; + } + oc_process_exit(&ip_adapter_process); close(dev->server4_sock); close(dev->mcast4_sock); diff --git a/port/esp32/adapter/src/ipadapter.c b/port/esp32/adapter/src/ipadapter.c index 09730dc82..1f2dac88f 100644 --- a/port/esp32/adapter/src/ipadapter.c +++ b/port/esp32/adapter/src/ipadapter.c @@ -231,9 +231,6 @@ get_ip_context_for_device(size_t device) while (dev != NULL && dev->device != device) { dev = dev->next; } - if (!dev) { - return NULL; - } return dev; } @@ -1575,6 +1572,11 @@ void oc_connectivity_shutdown(size_t device) { ip_context_t *dev = get_ip_context_for_device(device); + if (dev == NULL) { + OC_WRN("no ip-context found for device(%zu)", device); + return; + } + dev->terminate = 1; if (write(dev->shutdown_pipe[1], "\n", 1) < 0) { OC_WRN("cannot wakeup network thread"); diff --git a/port/linux/ipadapter.c b/port/linux/ipadapter.c index 2116cf6c5..7486deb6a 100644 --- a/port/linux/ipadapter.c +++ b/port/linux/ipadapter.c @@ -505,8 +505,7 @@ oc_endpoint_t * oc_connectivity_get_endpoints(size_t device) { ip_context_t *dev = oc_get_ip_context_for_device(device); - - if (!dev) { + if (dev == NULL) { return NULL; } @@ -1519,6 +1518,11 @@ void oc_connectivity_shutdown(size_t device) { ip_context_t *dev = oc_get_ip_context_for_device(device); + if (dev == NULL) { + OC_WRN("no ip-context found for device(%zu)", device); + return; + } + OC_ATOMIC_STORE8(dev->terminate, 1); do { if (write(dev->shutdown_pipe[1], "\n", 1) < 0) { diff --git a/port/linux/tcpsession.c b/port/linux/tcpsession.c index 4c372d0ff..344583bb9 100644 --- a/port/linux/tcpsession.c +++ b/port/linux/tcpsession.c @@ -1295,7 +1295,7 @@ oc_tcp_connect(oc_endpoint_t *endpoint, on_tcp_connect_t on_tcp_connect, { ip_context_t *dev = oc_get_ip_context_for_device(endpoint->device); if (dev == NULL) { - OC_ERR("cannot find context for device(%zu)", endpoint->device); + OC_ERR("cannot find ip-context for device(%zu)", endpoint->device); return -1; } return oc_tcp_connect_to_endpoint(dev, endpoint, on_tcp_connect, diff --git a/port/unittest/connectivitytest.cpp b/port/unittest/connectivitytest.cpp index 52f9104aa..f5a747cee 100644 --- a/port/unittest/connectivitytest.cpp +++ b/port/unittest/connectivitytest.cpp @@ -59,7 +59,7 @@ class TestConnectivity : public testing::Test { std::atomic TestConnectivity::is_callback_received{ false }; -TEST(TestConnectivity_init, oc_connectivity_initDefault) +TEST(TestConnectivity_init, Default) { oc_connectivity_ports_t ports; memset(&ports, 0, sizeof(oc_connectivity_ports_t)); @@ -68,7 +68,7 @@ TEST(TestConnectivity_init, oc_connectivity_initDefault) oc_connectivity_shutdown(kDeviceID); } -TEST(TestConnectivity_init, oc_connectivity_initTCPDisabled) +TEST(TestConnectivity_init, TCPDisabled) { oc_connectivity_ports_t ports; memset(&ports, 0, sizeof(oc_connectivity_ports_t)); @@ -91,7 +91,7 @@ TEST(TestConnectivity_init, oc_connectivity_initTCPDisabled) oc_connectivity_shutdown(kDeviceID); } -TEST(TestConnectivity_init, oc_connectivity_initUDPDisabled) +TEST(TestConnectivity_init, UDPDisabled) { oc_connectivity_ports_t ports; memset(&ports, 0, sizeof(oc_connectivity_ports_t)); @@ -114,7 +114,7 @@ TEST(TestConnectivity_init, oc_connectivity_initUDPDisabled) oc_connectivity_shutdown(kDeviceID); } -TEST(TestConnectivity_init, oc_connectivity_initAllDisabled) +TEST(TestConnectivity_init, AllDisabled) { oc_connectivity_ports_t ports; memset(&ports, 0, sizeof(oc_connectivity_ports_t)); @@ -127,6 +127,11 @@ TEST(TestConnectivity_init, oc_connectivity_initAllDisabled) oc_connectivity_shutdown(kDeviceID); } +TEST(TestConnectivity_shutdown, InvalidDevice) +{ + oc_connectivity_shutdown(42); +} + static void interface_event_handler(oc_interface_event_t event) { diff --git a/port/windows/ipadapter.c b/port/windows/ipadapter.c index e0e3fa592..34589fb06 100644 --- a/port/windows/ipadapter.c +++ b/port/windows/ipadapter.c @@ -20,12 +20,6 @@ #include "api/oc_network_events_internal.h" #include "api/oc_session_events_internal.h" -#include "port/common/posix/oc_socket_internal.h" -#include "port/oc_assert.h" -#include "port/oc_connectivity.h" -#include "port/oc_connectivity_internal.h" -#include "port/oc_log_internal.h" -#include "port/oc_network_event_handler_internal.h" #include "ipcontext.h" #include "mutex.h" #include "network_addresses.h" @@ -33,6 +27,14 @@ #include "oc_core_res.h" #include "oc_endpoint.h" #include "oc_network_monitor.h" +#include "port/common/posix/oc_socket_internal.h" +#include "port/oc_assert.h" +#include "port/oc_connectivity.h" +#include "port/oc_connectivity_internal.h" +#include "port/oc_log_internal.h" +#include "port/oc_network_event_handler_internal.h" +#include "util/oc_list.h" +#include "util/oc_memb.h" #ifdef OC_TCP #include "tcpadapter.h" @@ -80,11 +82,8 @@ OVERLAPPED ifchange_event; static LPFN_WSARECVMSG PWSARecvMsg; static LPFN_WSASENDMSG PWSASendMsg; -#ifdef OC_DYNAMIC_ALLOCATION -OC_LIST(ip_contexts); -#else /* OC_DYNAMIC_ALLOCATION */ -static ip_context_t devices[OC_MAX_NUM_DEVICES]; -#endif /* !OC_DYNAMIC_ALLOCATION */ +OC_LIST(g_ip_contexts); +OC_MEMB(g_ip_context_s, ip_context_t, OC_MAX_NUM_DEVICES); OC_MEMB(device_eps, oc_endpoint_t, 1); @@ -213,17 +212,12 @@ oc_network_event_handler_mutex_destroy(void) static ip_context_t * get_ip_context_for_device(size_t device) { -#ifdef OC_DYNAMIC_ALLOCATION - ip_context_t *dev = oc_list_head(ip_contexts); + oc_network_event_handler_mutex_lock(); + ip_context_t *dev = oc_list_head(g_ip_contexts); while (dev != NULL && dev->device != device) { dev = dev->next; } - if (!dev) { - return NULL; - } -#else /* OC_DYNAMIC_ALLOCATION */ - ip_context_t *dev = &devices[device]; -#endif /* !OC_DYNAMIC_ALLOCATION */ + oc_network_event_handler_mutex_unlock(); return dev; } @@ -490,14 +484,18 @@ static int process_interface_change_event(void) { int ret = 0; - size_t num_devices = oc_core_get_num_devices(), i; ifaddr_t *ifaddr_list = get_network_addresses(); if (!ifaddr_list) { return -1; } - for (i = 0; i < num_devices; i++) { + size_t num_devices = oc_core_get_num_devices(); + for (size_t i = 0; i < num_devices; i++) { ip_context_t *dev = get_ip_context_for_device(i); + if (dev == NULL) { + continue; + } + ret += update_mcast_socket(dev->mcast_sock, AF_INET6, ifaddr_list); #ifdef OC_IPV4 ret += update_mcast_socket(dev->mcast4_sock, AF_INET, ifaddr_list); @@ -899,7 +897,7 @@ oc_endpoint_t * oc_connectivity_get_endpoints(size_t device) { ip_context_t *dev = get_ip_context_for_device(device); - if (!dev) { + if (dev == NULL) { return NULL; } @@ -1181,11 +1179,16 @@ oc_send_buffer2(oc_message_t *message, bool queue) void oc_send_discovery_request(oc_message_t *message) { + ip_context_t *dev = get_ip_context_for_device(message->endpoint.device); + if (dev == NULL) { + OC_ERR("cannot send discovery request: device(%zu) ip-context not found", + message->endpoint.device); + return; + } + ifaddr_t *ifaddr_list = get_network_addresses(); ifaddr_t *ifaddr; - ip_context_t *dev = get_ip_context_for_device(message->endpoint.device); - for (ifaddr = ifaddr_list; ifaddr != NULL; ifaddr = ifaddr->next) { if (message->endpoint.flags & IPV6 && ifaddr->addr.ss_family == AF_INET6) { struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&ifaddr->addr; @@ -1426,15 +1429,11 @@ oc_connectivity_init(size_t device, oc_connectivity_ports_t ports) } OC_DBG("Initializing connectivity for device %zd", device); -#ifdef OC_DYNAMIC_ALLOCATION - ip_context_t *dev = (ip_context_t *)calloc(1, sizeof(ip_context_t)); - if (!dev) { + ip_context_t *dev = (ip_context_t *)oc_memb_alloc(&g_ip_context_s); + if (dev == NULL) { oc_abort("Insufficient memory"); } - oc_list_add(ip_contexts, dev); -#else /* OC_DYNAMIC_ALLOCATION */ - ip_context_t *dev = &devices[device]; -#endif /* !OC_DYNAMIC_ALLOCATION */ + dev->device = device; OC_LIST_STRUCT_INIT(dev, eps); memset(&dev->mcast, 0, sizeof(dev->mcast)); @@ -1464,6 +1463,7 @@ oc_connectivity_init(size_t device, oc_connectivity_ports_t ports) if (dev->server_sock == (SOCKET)SOCKET_ERROR || dev->mcast_sock == (SOCKET)SOCKET_ERROR) { OC_ERR("creating server sockets"); + oc_memb_free(&g_ip_context_s, dev); return -1; } @@ -1471,6 +1471,7 @@ oc_connectivity_init(size_t device, oc_connectivity_ports_t ports) dev->secure_sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (dev->secure_sock == (SOCKET)SOCKET_ERROR) { OC_ERR("creating secure socket"); + oc_memb_free(&g_ip_context_s, dev); return -1; } #endif /* OC_SECURITY */ @@ -1479,21 +1480,25 @@ oc_connectivity_init(size_t device, oc_connectivity_ports_t ports) if (setsockopt(dev->server_sock, IPPROTO_IPV6, IPV6_PKTINFO, (char *)&on, sizeof(on)) == -1) { OC_ERR("setting recvpktinfo option %d\n", WSAGetLastError()); + oc_memb_free(&g_ip_context_s, dev); return -1; } if (setsockopt(dev->server_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)) == SOCKET_ERROR) { OC_ERR("setting sock option %d", WSAGetLastError()); + oc_memb_free(&g_ip_context_s, dev); return -1; } if (setsockopt(dev->server_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) == SOCKET_ERROR) { OC_ERR("setting reuseaddr option %d", WSAGetLastError()); + oc_memb_free(&g_ip_context_s, dev); return -1; } if (bind(dev->server_sock, (struct sockaddr *)&dev->server, sizeof(dev->server)) == SOCKET_ERROR) { OC_ERR("binding server socket %d", WSAGetLastError()); + oc_memb_free(&g_ip_context_s, dev); return -1; } @@ -1501,6 +1506,7 @@ oc_connectivity_init(size_t device, oc_connectivity_ports_t ports) if (getsockname(dev->server_sock, (struct sockaddr *)&dev->server, &socklen) == SOCKET_ERROR) { OC_ERR("obtaining server socket information %d", WSAGetLastError()); + oc_memb_free(&g_ip_context_s, dev); return -1; } @@ -1514,16 +1520,19 @@ oc_connectivity_init(size_t device, oc_connectivity_ports_t ports) if (setsockopt(dev->mcast_sock, IPPROTO_IPV6, IPV6_PKTINFO, (char *)&on, sizeof(on)) == -1) { OC_ERR("setting recvpktinfo option %d\n", WSAGetLastError()); + oc_memb_free(&g_ip_context_s, dev); return -1; } if (setsockopt(dev->mcast_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) == SOCKET_ERROR) { OC_ERR("setting reuseaddr option %d", WSAGetLastError()); + oc_memb_free(&g_ip_context_s, dev); return -1; } if (bind(dev->mcast_sock, (struct sockaddr *)&dev->mcast, sizeof(dev->mcast)) == SOCKET_ERROR) { OC_ERR("binding mcast socket %d", WSAGetLastError()); + oc_memb_free(&g_ip_context_s, dev); return -1; } @@ -1531,16 +1540,19 @@ oc_connectivity_init(size_t device, oc_connectivity_ports_t ports) if (setsockopt(dev->secure_sock, IPPROTO_IPV6, IPV6_PKTINFO, (char *)&on, sizeof(on)) == -1) { OC_ERR("setting recvpktinfo option %d\n", WSAGetLastError()); + oc_memb_free(&g_ip_context_s, dev); return -1; } if (setsockopt(dev->secure_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) == SOCKET_ERROR) { OC_ERR("setting reuseaddr option %d", WSAGetLastError()); + oc_memb_free(&g_ip_context_s, dev); return -1; } if (bind(dev->secure_sock, (struct sockaddr *)&dev->secure, sizeof(dev->secure)) == SOCKET_ERROR) { OC_ERR("binding IPv6 secure socket %d", WSAGetLastError()); + oc_memb_free(&g_ip_context_s, dev); return -1; } @@ -1548,6 +1560,7 @@ oc_connectivity_init(size_t device, oc_connectivity_ports_t ports) if (getsockname(dev->secure_sock, (struct sockaddr *)&dev->secure, &socklen) == SOCKET_ERROR) { OC_ERR("obtaining secure socket information %d", WSAGetLastError()); + oc_memb_free(&g_ip_context_s, dev); return -1; } @@ -1571,22 +1584,26 @@ oc_connectivity_init(size_t device, oc_connectivity_ports_t ports) WSASocketW(AF_INET6, SOCK_DGRAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); if (ifchange_sock == INVALID_SOCKET) { OC_ERR("creating socket to track network interface changes"); + oc_memb_free(&g_ip_context_s, dev); return -1; } BOOL v6_only = FALSE; if (setsockopt(ifchange_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6_only, sizeof(v6_only)) == SOCKET_ERROR) { OC_ERR("setting socket option to make it dual IPv4/v6"); + oc_memb_free(&g_ip_context_s, dev); return -1; } ifchange_event.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (ifchange_event.hEvent == NULL) { OC_ERR("creating network interface change event"); + oc_memb_free(&g_ip_context_s, dev); return -1; } if (WSAEventSelect(ifchange_sock, ifchange_event.hEvent, FD_ADDRESS_LIST_CHANGE) == SOCKET_ERROR) { OC_ERR("binding network interface change event to socket"); + oc_memb_free(&g_ip_context_s, dev); return -1; } DWORD bytes_returned = 0; @@ -1596,6 +1613,7 @@ oc_connectivity_init(size_t device, oc_connectivity_ports_t ports) if (err != ERROR_IO_PENDING) { OC_ERR("could not set SIO_ADDRESS_LIST_CHANGE on network interface " "change socket"); + oc_memb_free(&g_ip_context_s, dev); return -1; } } @@ -1606,10 +1624,14 @@ oc_connectivity_init(size_t device, oc_connectivity_ports_t ports) CreateThread(0, 0, network_event_thread, dev, 0, &dev->event_thread); if (dev->event_thread_handle == NULL) { OC_ERR("creating network polling thread"); + oc_memb_free(&g_ip_context_s, dev); return -1; } OC_DBG("Successfully initialized connectivity for device %zd", device); + oc_network_event_handler_mutex_lock(); + oc_list_add(g_ip_contexts, dev); + oc_network_event_handler_mutex_unlock(); return 0; } @@ -1618,6 +1640,11 @@ void oc_connectivity_shutdown(size_t device) { ip_context_t *dev = get_ip_context_for_device(device); + if (dev == NULL) { + OC_WRN("no ip-context found for device(%zu)", device); + return; + } + dev->terminate = TRUE; /* signal WSASelectEvent() in the thread to leave */ WSASetEvent(dev->event_server_handle); @@ -1646,10 +1673,10 @@ oc_connectivity_shutdown(size_t device) free_endpoints_list(dev); -#ifdef OC_DYNAMIC_ALLOCATION - oc_list_remove(ip_contexts, dev); - free(dev); -#endif /* OC_DYNAMIC_ALLOCATION */ + oc_network_event_handler_mutex_lock(); + oc_list_remove(g_ip_contexts, dev); + oc_network_event_handler_mutex_unlock(); + oc_memb_free(&g_ip_context_s, dev); OC_DBG("oc_connectivity_shutdown for device %zd", device); } @@ -1660,7 +1687,7 @@ oc_connectivity_end_session(const oc_endpoint_t *endpoint) { if (endpoint->flags & TCP) { ip_context_t *dev = get_ip_context_for_device(endpoint->device); - if (dev) { + if (dev != NULL) { oc_tcp_end_session(endpoint); } } diff --git a/util/oc_list.h b/util/oc_list.h index 5e8a8a20c..5d2159da0 100644 --- a/util/oc_list.h +++ b/util/oc_list.h @@ -132,6 +132,11 @@ extern "C" { oc_list_init((struct_ptr)->name); \ } while (0) +#define OC_LIST_STRUCT_REINIT(struct_ptr, name) \ + do { \ + (struct_ptr)->name = &((struct_ptr)->OC_LIST_CONCAT(name, _list)); \ + } while (0) + /** * The linked list type. */