Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Message Queue Limit to Prevent Memory Exhaustion in Embedded Devices #629

Merged
merged 35 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
2a9d523
Issue 626: Implement Message Queue Limit to Prevent Memory Exhaustion…
sp-milos May 20, 2024
00bcf01
- block event processing when the network event queue is full
sp-martin May 28, 2024
9c9d562
- separete control-flow (signal) socket handling
sp-martin May 29, 2024
544f82e
- per device queue limit handling
sp-martin May 30, 2024
da71883
- fixed formatting and static analysis
sp-martin May 31, 2024
4eec493
- separate define for device concurent requests
sp-martin May 31, 2024
7877fd4
-send wakeup only to certain device network thread
sp-martin Jun 3, 2024
cbfcc01
- fixed android and esp32 builds
sp-martin Jun 3, 2024
eba31db
- renamed shutdown_pipe to wakeup_pipe
sp-martin Jun 3, 2024
cf6bac9
- optimized traversal of file descriptors
sp-martin Jun 3, 2024
a82dc4a
- fixed android and esp32 build breaks
sp-martin Jun 4, 2024
8170cad
- calculate max fd value from the recent device file descriptor set
sp-martin Jun 4, 2024
0607c59
- improved error handling and logging for signal_event_thread
sp-martin Jun 5, 2024
5419e5b
- logging the error code instead of a string using strerror()
sp-martin Jun 5, 2024
4747dee
- android port of Message Queue Limit
sp-martin Jun 5, 2024
6a25e74
- formatting
sp-martin Jun 5, 2024
fcc5352
- fixed build break after automerge
sp-martin Jun 5, 2024
2b2f467
- fixed build break when DOC_DYNAMIC_ALLOCATION_ENABLED=OFF
sp-martin Jun 6, 2024
e3199dc
- fixed android builds
sp-martin Jun 6, 2024
497f503
- fixed handling of tcp controlflow sockets on android
sp-martin Jun 6, 2024
129c206
- formatting, android build break fix
sp-martin Jun 6, 2024
65ffb5d
- linux build break fix
sp-martin Jun 6, 2024
ec4dac2
- unix amd64/arm64 build break fix
sp-martin Jun 6, 2024
0b456a5
- esp32 port of Message Queue Limit
sp-martin Jun 7, 2024
95e6cda
Added Windows port of message queue limit.
sp-milos Jun 10, 2024
3153809
Allow to set OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS in CMake
Danielius1922 Jun 12, 2024
98e3782
- tests for the network event queue, wakeup connectivity tests
sp-martin Jun 12, 2024
26df754
Automatic format commit
CascodaBot Jun 13, 2024
e6338d2
- fixed OC_DYNAMIC_ALLOCATION=OFF builds
sp-martin Jun 13, 2024
718ce71
- generic solution for comparing fd_set
sp-martin Jun 13, 2024
4b254d8
Run tests with OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS=1 on GitHub
Danielius1922 Jun 13, 2024
30cace2
- fixed generation of random negative numbers causing the pick_random…
sp-martin Jun 13, 2024
72f5d63
- corrected issues reported by SonarCloud
sp-martin Jun 14, 2024
584a756
- addressed sonar cloud issues
sp-martin Jun 14, 2024
bbdd320
- run tests on GitHub with thread sanitizer
Danielius1922 Jun 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/cmake-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ jobs:
cc: "gcc"
cxx: "g++"
build_testing: "ON"
- name: "MinGW-gcc debug-discovery-resource-observable-rep-realloc-concurrent-requests-1"
build_type: "Debug"
cc: "gcc"
cxx: "g++"
build_testing: "ON"
build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS=1"

steps:
- name: Checkout repository
Expand Down Expand Up @@ -93,6 +99,7 @@ jobs:
-D PLGD_DEV_TIME_ENABLED=ON
-D OC_ETAG_ENABLED=ON
-D OC_DEBUG_ENABLED=ON
${{ matrix.build_args }}
COMMAND_ERROR_IS_FATAL ANY
)

Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/plgd-device-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ jobs:
args: "-DOC_TSAN_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON"
docker_file: docker/apps/Dockerfile.cloud-server-debug-clang

- name: cloud-server-access-in-RFOTM-concurrent-requests-1
# same configuration as " cloud-server-access-in-RFOTM-concurrent-requests-1" in the SonarCloud scan job, skip for events that trigger both jobs
skip: ${{ github.event_name != 'workflow_dispatch' }}
args: "-DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS=1"
- name: cloud-server-access-in-RFOTM-concurrent-requests-1-tsan
args: "-DOC_TSAN_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS=1"
docker_file: docker/apps/Dockerfile.cloud-server-debug-clang

- name: cloud-server-discovery-resource-observable
args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON"
- name: cloud-server-discovery-resource-observable-asan
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/plgd-hub-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ jobs:
build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_TSAN_ENABLED=ON"
docker_file: docker/apps/Dockerfile.cloud-server-debug-clang

- name: cloud-server-discovery-resource-observable-access-in-RFOTM-rep-realloc-concurrent-requests-1
# same configuration as "cloud-server-discovery-resource-observable-access-in-RFOTM-rep-realloc-concurrent-requests-1" in the SonarCloud scan job, skip for events that trigger both jobs
skip: ${{ github.event_name != 'workflow_dispatch' }}
build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS=1"
- name: cloud-server-discovery-resource-observable-access-in-RFOTM-rep-realloc-concurrent-requests-1-tsan
build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS=1 -DOC_TSAN_ENABLED=ON"
docker_file: docker/apps/Dockerfile.cloud-server-debug-clang

# ports
- name: cloud-server-tcp-disabled
args: "--udp-port 61234 --udp-port4 61234 --dtls-port 61235 --dtls-port4 61235 --tcp-port -1 --tcp-port4 -1 --tls-port -1 --tls-port4 -1"
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/sonar-cloud-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ jobs:
include:
# cloud (ipv4+tcp) on, collection create on, push on, rfotm on
- build_args: "-DOC_CLOUD_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON -DOC_PUSH_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON"
# security off, ipv4 on, collection create on, push on
- build_args: "-DOC_SECURITY_ENABLED=OFF -DOC_IPV4_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON -DOC_PUSH_ENABLED=ON"
# security off, ipv4 on, collection create on, push on, max num concurrent requests=1
- build_args: "-DOC_SECURITY_ENABLED=OFF -DOC_IPV4_ENABLED=ON -DOC_COLLECTIONS_IF_CREATE_ENABLED=ON -DOC_PUSH_ENABLED=ON -DOC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS=1"
# ipv6 dns on, oscore off, rep realloc on, json encoder on, introspection IDD off
- build_args: "-DOC_DNS_LOOKUP_IPV6_ENABLED=ON -DOC_OSCORE_ENABLED=OFF -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_JSON_ENCODER_ENABLED=ON -DOC_IDD_API_ENABLED=OFF"
# cloud (ipv4+tcp) on, dynamic allocation off, rfotm on, push off (because it forces dynamic allocation)
Expand All @@ -51,6 +51,8 @@ jobs:
include:
- name: cloud-server
build_args: ""
- name: cloud-server-access-in-RFOTM-concurrent-requests-1
build_args: "-DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS=1"
- name: cloud-server-discovery-resource-observable-access-in-RFOTM-rep-realloc
build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON"
# try with SHA384
Expand All @@ -72,6 +74,8 @@ jobs:
include:
- name: cloud-server-discovery-resource-observable-access-in-RFOTM
build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON"
- name: cloud-server-discovery-resource-observable-access-in-RFOTM-rep-realloc-concurrent-requests-1
build_args: "-DOC_DISCOVERY_RESOURCE_OBSERVABLE_ENABLED=ON -DOC_RESOURCE_ACCESS_IN_RFOTM_ENABLED=ON -DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON -DOC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS=1"
- name: dtls-cloud-server-rep-realloc
build_args: "-DOC_REPRESENTATION_REALLOC_ENCODING_ENABLED=ON"
hub_args: "-e COAP_GATEWAY_UDP_ENABLED=true"
Expand Down
101 changes: 59 additions & 42 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ if(BUILD_TESTING AND UNIX AND (OC_COMPILER_IS_GCC OR OC_COMPILER_IS_CLANG))
endif()

######## Build configuration options ########
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

set(BUILD_EXAMPLE_APPLICATIONS ON CACHE BOOL "Build example applications.")
set(BUILD_MBEDTLS ON CACHE BOOL "Build Mbed TLS library. When set to OFF, the Mbed TLS library with the OCF patches has to be provided.")
set(BUILD_MBEDTLS_FORCE_3_5_0 OFF CACHE BOOL "Force v3.5.0 of the MbedTLS library to be used (by default v3.1.0 is used by master)")
Expand Down Expand Up @@ -57,15 +59,6 @@ set(OC_PUSH_ENABLED OFF CACHE BOOL "Enable Push Notification.")
set(OC_PUSHDEBUG_ENABLED OFF CACHE BOOL "Enable debug messages for Push Notification.")
set(OC_RESOURCE_ACCESS_IN_RFOTM_ENABLED OFF CACHE BOOL "Enable resource access in RFOTM.")
set(OC_MEMORY_TRACE_ENABLED OFF CACHE BOOL "Enable memory tracing.")
if (OC_DEBUG_ENABLED)
set(OC_LOG_MAXIMUM_LOG_LEVEL "TRACE" CACHE STRING "Maximum supported log level in compile time.")
else()
set(OC_LOG_MAXIMUM_LOG_LEVEL "DISABLED" CACHE STRING "Maximum supported log level in compile time.")
endif()
set(OC_INOUT_BUFFER_SIZE "" CACHE STRING "Custom static buffer size for network messages.")
set(OC_INOUT_BUFFER_POOL "" CACHE STRING "Custom static pool size of network messages.")
set(OC_APP_DATA_BUFFER_SIZE "" CACHE STRING "Custom static buffer size for application messages.")
set(OC_APP_DATA_BUFFER_POOL "" CACHE STRING "Custom static size of application messages.")
set(OC_VERSION_1_1_0_ENABLED OFF CACHE BOOL "Enable OCF version 1.1")
set(OC_ETAG_ENABLED OFF CACHE BOOL "Enable Entity Tag (ETag) support.")
set(OC_JSON_ENCODER_ENABLED OFF CACHE BOOL "Enable JSON encoder/decoder support.")
Expand All @@ -75,7 +68,16 @@ if (BUILD_EXAMPLE_APPLICATIONS OR BUILD_TESTING)
endif()
set(PLGD_DEV_TIME_ENABLED OFF CACHE BOOL "Enable plgd time feature.")

set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if (OC_DEBUG_ENABLED)
set(OC_LOG_MAXIMUM_LOG_LEVEL "TRACE" CACHE STRING "Maximum supported log level in compile time.")
else()
set(OC_LOG_MAXIMUM_LOG_LEVEL "DISABLED" CACHE STRING "Maximum supported log level in compile time.")
endif()
set(OC_INOUT_BUFFER_SIZE "" CACHE STRING "Custom static buffer size for network messages.")
set(OC_INOUT_BUFFER_POOL "" CACHE STRING "Custom static pool size of network messages.")
set(OC_APP_DATA_BUFFER_SIZE "" CACHE STRING "Custom static buffer size for application messages.")
set(OC_APP_DATA_BUFFER_POOL "" CACHE STRING "Custom static size of application messages.")
set(OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS "" CACHE STRING "Maximum number of messages in the network event queue for a device.")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The introduction of OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS is crucial for managing memory on devices. Ensure this is well-documented in the developer's guide or relevant markdown files to aid understanding and usage.

Consider adding a detailed comment here explaining the purpose and usage of OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS to improve code readability and maintenance.


set(OC_ASAN_ENABLED OFF CACHE BOOL "Enable address sanitizer build.")
set(OC_LSAN_ENABLED OFF CACHE BOOL "Enable leak sanitizer build.")
Expand Down Expand Up @@ -399,38 +401,6 @@ if(OC_MEMORY_TRACE_ENABLED)
list(APPEND TEST_COMPILE_DEFINITIONS "OC_MEMORY_TRACE")
endif()

if (NOT("${OC_INOUT_BUFFER_SIZE}" STREQUAL ""))
if(NOT OC_DYNAMIC_ALLOCATION_ENABLED)
message(FATAL_ERROR "Cannot set custom static buffer size for network messages without dynamic allocation")
endif()
list(APPEND PUBLIC_COMPILE_DEFINITIONS "OC_INOUT_BUFFER_SIZE=(${OC_INOUT_BUFFER_SIZE})")
list(APPEND MBEDTLS_COMPILE_DEFINITIONS "OC_INOUT_BUFFER_SIZE=(${OC_INOUT_BUFFER_SIZE})")
endif()

if (NOT("${OC_INOUT_BUFFER_POOL}" STREQUAL ""))
if(NOT OC_DYNAMIC_ALLOCATION_ENABLED)
message(FATAL_ERROR "Cannot set custom static pool size for network messages without dynamic allocation")
endif()
list(APPEND PUBLIC_COMPILE_DEFINITIONS "OC_INOUT_BUFFER_POOL=(${OC_INOUT_BUFFER_POOL})")
list(APPEND MBEDTLS_COMPILE_DEFINITIONS "OC_INOUT_BUFFER_POOL=(${OC_INOUT_BUFFER_POOL})")
endif()

if (NOT("${OC_APP_DATA_BUFFER_SIZE}" STREQUAL ""))
if(NOT OC_DYNAMIC_ALLOCATION_ENABLED)
message(FATAL_ERROR "Cannot set custom static buffer size for application messages without dynamic allocation")
endif()
list(APPEND PUBLIC_COMPILE_DEFINITIONS "OC_APP_DATA_BUFFER_SIZE=(${OC_APP_DATA_BUFFER_SIZE})")
list(APPEND MBEDTLS_COMPILE_DEFINITIONS "OC_APP_DATA_BUFFER_SIZE=(${OC_APP_DATA_BUFFER_SIZE})")
endif()

if (NOT("${OC_APP_DATA_BUFFER_POOL}" STREQUAL ""))
if(NOT OC_DYNAMIC_ALLOCATION_ENABLED)
message(FATAL_ERROR "Cannot set custom static pool size for application messages without dynamic allocation")
endif()
list(APPEND PUBLIC_COMPILE_DEFINITIONS "OC_APP_DATA_BUFFER_POOL=(${OC_APP_DATA_BUFFER_POOL})")
list(APPEND MBEDTLS_COMPILE_DEFINITIONS "OC_APP_DATA_BUFFER_POOL=(${OC_APP_DATA_BUFFER_POOL})")
endif()

if(OC_VERSION_1_1_0_ENABLED)
list(APPEND PUBLIC_COMPILE_DEFINITIONS "OC_SPEC_VER_OIC")
endif()
Expand All @@ -454,6 +424,53 @@ if(PLGD_DEV_TIME_ENABLED)
endif()
endif()

if(NOT("${OC_INOUT_BUFFER_SIZE}" STREQUAL ""))
if(NOT OC_DYNAMIC_ALLOCATION_ENABLED)
message(FATAL_ERROR "Cannot OC_INOUT_BUFFER_SIZE without dynamic allocation")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error handling for dynamic allocation settings is robust, ensuring that features dependent on dynamic allocation are not mistakenly enabled without it. However, consider enhancing the error messages to guide users more effectively on how to correct their setup.

- message(FATAL_ERROR "Cannot set OC_INOUT_BUFFER_SIZE without dynamic allocation")
+ message(FATAL_ERROR "Dynamic allocation is disabled. Enable OC_DYNAMIC_ALLOCATION to set OC_INOUT_BUFFER_SIZE.")
- message(FATAL_ERROR "Cannot set OC_INOUT_BUFFER_POOL without dynamic allocation")
+ message(FATAL_ERROR "Dynamic allocation is disabled. Enable OC_DYNAMIC_ALLOCATION to set OC_INOUT_BUFFER_POOL.")
- message(FATAL_ERROR "Cannot set OC_APP_DATA_BUFFER_SIZE without dynamic allocation")
+ message(FATAL_ERROR "Dynamic allocation is disabled. Enable OC_DYNAMIC_ALLOCATION to set OC_APP_DATA_BUFFER_SIZE.")
- message(FATAL_ERROR "Cannot set OC_APP_DATA_BUFFER_POOL without dynamic allocation")
+ message(FATAL_ERROR "Dynamic allocation is disabled. Enable OC_DYNAMIC_ALLOCATION to set OC_APP_DATA_BUFFER_POOL.")
- message(FATAL_ERROR "Cannot set OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS without dynamic allocation")
+ message(FATAL_ERROR "Dynamic allocation is disabled. Enable OC_DYNAMIC_ALLOCATION to set OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS.")

Also applies to: 439-439, 449-449, 459-459, 469-469

endif()
list(APPEND PUBLIC_COMPILE_DEFINITIONS "OC_INOUT_BUFFER_SIZE=(${OC_INOUT_BUFFER_SIZE})")
if(BUILD_MBEDTLS)
list(APPEND MBEDTLS_COMPILE_DEFINITIONS "OC_INOUT_BUFFER_SIZE=(${OC_INOUT_BUFFER_SIZE})")
endif()
endif()

if(NOT("${OC_INOUT_BUFFER_POOL}" STREQUAL ""))
if(NOT OC_DYNAMIC_ALLOCATION_ENABLED)
message(FATAL_ERROR "Cannot set OC_INOUT_BUFFER_POOL without dynamic allocation")
endif()
list(APPEND PUBLIC_COMPILE_DEFINITIONS "OC_INOUT_BUFFER_POOL=(${OC_INOUT_BUFFER_POOL})")
if(BUILD_MBEDTLS)
list(APPEND MBEDTLS_COMPILE_DEFINITIONS "OC_INOUT_BUFFER_POOL=(${OC_INOUT_BUFFER_POOL})")
endif()
endif()

if(NOT("${OC_APP_DATA_BUFFER_SIZE}" STREQUAL ""))
if(NOT OC_DYNAMIC_ALLOCATION_ENABLED)
message(FATAL_ERROR "Cannot set OC_APP_DATA_BUFFER_SIZE without dynamic allocation")
endif()
list(APPEND PUBLIC_COMPILE_DEFINITIONS "OC_APP_DATA_BUFFER_SIZE=(${OC_APP_DATA_BUFFER_SIZE})")
if(BUILD_MBEDTLS)
list(APPEND MBEDTLS_COMPILE_DEFINITIONS "OC_APP_DATA_BUFFER_SIZE=(${OC_APP_DATA_BUFFER_SIZE})")
endif()
endif()

if(NOT("${OC_APP_DATA_BUFFER_POOL}" STREQUAL ""))
if(NOT OC_DYNAMIC_ALLOCATION_ENABLED)
message(FATAL_ERROR "Cannot OC_APP_DATA_BUFFER_POOL without dynamic allocation")
endif()
list(APPEND PUBLIC_COMPILE_DEFINITIONS "OC_APP_DATA_BUFFER_POOL=(${OC_APP_DATA_BUFFER_POOL})")
if(BUILD_MBEDTLS)
list(APPEND MBEDTLS_COMPILE_DEFINITIONS "OC_APP_DATA_BUFFER_POOL=(${OC_APP_DATA_BUFFER_POOL})")
endif()
endif()

if(NOT("${OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS}" STREQUAL ""))
if(NOT OC_DYNAMIC_ALLOCATION_ENABLED)
message(FATAL_ERROR "Cannot set OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS without dynamic allocation")
Danielius1922 marked this conversation as resolved.
Show resolved Hide resolved
endif()
list(APPEND PUBLIC_COMPILE_DEFINITIONS "OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS=(${OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS})")
endif()

if(BUILD_TESTING)
list(APPEND PRIVATE_COMPILE_DEFINITIONS "OC_TEST")
if(BUILD_MBEDTLS)
Expand Down
6 changes: 4 additions & 2 deletions api/cloud/unittest/rd_client_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ TEST_F(TestRDClient, Publish_FailBadInput)
/*user_data*/ nullptr));
}

#if defined(OC_DYNAMIC_ALLOCATION) && !defined(OC_APP_DATA_BUFFER_SIZE)
#if defined(OC_DYNAMIC_ALLOCATION) && !defined(OC_APP_DATA_BUFFER_SIZE) && \
!defined(OC_REP_ENCODING_REALLOC)

TEST_F(TestRDClient, Publish_FailPayloadTooLarge)
{
Expand All @@ -228,7 +229,8 @@ TEST_F(TestRDClient, Publish_FailPayloadTooLarge)
oc_set_max_app_data_size(kDefaultSize);
}

#endif // OC_DYNAMIC_ALLOCATION && !OC_APP_DATA_BUFFER_SIZE
#endif // OC_DYNAMIC_ALLOCATION && !OC_APP_DATA_BUFFER_SIZE &&
// !OC_REP_ENCODING_REALLOC

#ifndef OC_DYNAMIC_ALLOCATION

Expand Down
2 changes: 1 addition & 1 deletion api/oc_core_res.c
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ static bool
core_is_resource_uri(const char *uri, size_t uri_len, const char *r_uri,
size_t r_uri_len)
{
if (uri[0] == '/') {
if (uri_len > 0 && uri[0] == '/') {
uri = &uri[1];
--uri_len;
}
Expand Down
64 changes: 62 additions & 2 deletions api/oc_network_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,37 @@ static bool g_interface_up;
static bool g_interface_down;
#endif /* OC_NETWORK_MONITOR */

#ifdef OC_DYNAMIC_ALLOCATION
static size_t
get_events_queue_length(size_t device, oc_list_t events)
{
size_t msg_count = 0;
for (oc_message_t *msg = (oc_message_t *)oc_list_head(events); msg != NULL;
msg = msg->next) {
if (msg->endpoint.device == device) {
++msg_count;
}
}
return msg_count;
}

static void
send_wakeup_signal(oc_list_t events)
{
size_t msg_total = oc_list_length(events);

int deviceId = 0;
while (msg_total >= OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS) {
size_t msg_device_count = get_events_queue_length(deviceId, events);
if (msg_device_count >= OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS) {
oc_connectivity_wakeup(deviceId);
}
msg_total -= msg_device_count;
++deviceId; // advance to the next device
}
}
#endif /* OC_DYNAMIC_ALLOCATION */

static void
oc_process_network_event(void)
{
Expand All @@ -65,6 +96,11 @@ oc_process_network_event(void)
#endif /* OC_NETWORK_MONITOR */
oc_network_event_handler_mutex_unlock();

#ifdef OC_DYNAMIC_ALLOCATION
// send a wake-up signal in case the queue might reach the limit for a device
send_wakeup_signal(network_events);
#endif /* OC_DYNAMIC_ALLOCATION */

#ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT
oc_tcp_on_connect_event_t *event =
(oc_tcp_on_connect_event_t *)oc_list_pop(network_tcp_connect_events);
Expand Down Expand Up @@ -153,10 +189,10 @@ oc_network_tcp_connect_event(oc_tcp_on_connect_event_t *event)
}
#endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */

int
size_t
oc_network_drop_receive_events(const oc_endpoint_t *endpoint)
{
int dropped = 0;
size_t dropped = 0;
oc_network_event_handler_mutex_lock();
for (oc_message_t *message = (oc_message_t *)oc_list_head(g_network_events);
message != NULL;) {
Expand All @@ -178,7 +214,20 @@ oc_network_drop_receive_events(const oc_endpoint_t *endpoint)
}
message = next;
}

#ifdef OC_DYNAMIC_ALLOCATION
size_t queue_len =
get_events_queue_length(endpoint->device, g_network_events);
// unlock mutex and send a wake-up signal in case the queue for the device was
// full
oc_network_event_handler_mutex_unlock();
if (queue_len + dropped >= OC_DEVICE_MAX_NUM_CONCURRENT_REQUESTS) {
oc_connectivity_wakeup(endpoint->device);
}
#else
oc_network_event_handler_mutex_unlock();
#endif /* OC_DYNAMIC_ALLOCATION */

return dropped;
}

Expand All @@ -204,3 +253,14 @@ oc_network_interface_event(oc_interface_event_t event)
_oc_signal_event_loop();
}
#endif /* OC_NETWORK_MONITOR */

#ifdef OC_DYNAMIC_ALLOCATION
size_t
oc_network_get_event_queue_length(size_t device)
{
oc_network_event_handler_mutex_lock();
size_t msg_count = get_events_queue_length(device, g_network_events);
oc_network_event_handler_mutex_unlock();
return msg_count;
}
#endif /* OC_DYNAMIC_ALLOCATION */
11 changes: 10 additions & 1 deletion api/oc_network_events_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ void oc_network_tcp_connect_event(oc_tcp_on_connect_event_t *event)
* @param endpoint the endpoint (cannot be NULL)
* @return number of events dropped
*/
int oc_network_drop_receive_events(const oc_endpoint_t *endpoint) OC_NONNULL();
size_t oc_network_drop_receive_events(const oc_endpoint_t *endpoint)
OC_NONNULL();

#ifdef OC_NETWORK_MONITOR
/**
Expand All @@ -78,6 +79,14 @@ typedef struct oc_network_interface_cb
void oc_network_interface_event(oc_interface_event_t event);
#endif /* OC_NETWORK_MONITOR */

/**
* @brief Returns the network event queue length for the device
*
* @param device valid device index
* @return number of events in the queue
*/
size_t oc_network_get_event_queue_length(size_t device);

#ifdef __cplusplus
}
#endif
Expand Down
7 changes: 7 additions & 0 deletions api/unittest/introspectiontest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ TEST_F(TestIntrospectionWithServer, GetRequest)
// the IDD data is too large for non-dynamic allocation and byte pool gets
// exhausted

#ifndef OC_REP_ENCODING_REALLOC

// TODO: if the default application data size is too small, the introspection
// data should realloc the buffer to sufficient size

TEST_F(TestIntrospectionWithServer, GetDataRequest)
{
auto epOpt = oc::TestDevice::GetEndpoint(kDeviceID);
Expand All @@ -221,6 +226,8 @@ TEST_F(TestIntrospectionWithServer, GetDataRequest)
EXPECT_TRUE(invoked);
}

#endif /* !OC_REP_ENCODING_REALLOC */

TEST_F(TestIntrospectionWithServer, GetDataRequest_Fail)
{
oc::TestDevice::StopServer();
Expand Down
Loading
Loading