Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions rosidl_typesupport_microxrcedds_c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ project(rosidl_typesupport_microxrcedds_c LANGUAGES C)
find_package(ament_cmake REQUIRED)
find_package(microcdr REQUIRED)
find_package(ament_cmake_python REQUIRED)
find_package(rcutils REQUIRED)
find_package(rosidl_runtime_c REQUIRED)

ament_export_dependencies(rcutils)
ament_export_dependencies(rmw)
ament_export_dependencies(rosidl_cmake)
ament_export_dependencies(rosidl_runtime_c)
Expand All @@ -47,6 +49,7 @@ target_include_directories(${PROJECT_NAME}
)

target_link_libraries(${PROJECT_NAME}
rcutils::rcutils
rosidl_runtime_c::rosidl_runtime_c
)
ament_export_libraries(${PROJECT_NAME})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,17 @@
#define ROSIDL_TYPESUPPORT_MICROXRCEDDS_C__MESSAGE_TYPE_SUPPORT_H_

#include "rosidl_runtime_c/message_type_support_struct.h"
#include "rosidl_runtime_c/string.h"

#include <rcutils/allocator.h>
#include <ucdr/microcdr.h>

// Bytes (null terminator included) reserved for a received string whose buffer is still in the
// state left by rosidl_runtime_c__String__init() (capacity 1)
#ifndef ROSIDL_TYPESUPPORT_MICROXRCEDDS_C_STRING_RESERVATION
#define ROSIDL_TYPESUPPORT_MICROXRCEDDS_C_STRING_RESERVATION 50
#endif

typedef struct message_type_support_callbacks_t
{
const char * message_namespace_;
Expand Down Expand Up @@ -48,4 +56,53 @@ typedef struct message_type_support_callbacks_t

} message_type_support_callbacks_t;

/**
* Deserializes a string into the memory already owned by `str`.
*
* If the received string does not fit, it is skipped, `str` is left empty and false is
* returned, so the message is rejected.
*
* If `str` is still in the state left by rosidl_runtime_c__String__init() (capacity 1), its
* buffer is reallocated once with the rcutils default allocator to
* ROSIDL_TYPESUPPORT_MICROXRCEDDS_C_STRING_RESERVATION bytes.
* Buffers provided by the user always have a larger capacity, so they are never reallocated.
*/
static inline bool rosidl_typesupport_microxrcedds_c__deserialize_string(
ucdrBuffer * cdr,
rosidl_runtime_c__String * str)
{
const size_t capacity = str->capacity;
uint32_t length = 0; // CDR length, null terminator included

// When the string does not fit, micro-CDR only consumes its length and sets the error flag
bool rv = ucdr_deserialize_sequence_char(cdr, str->data, capacity, &length);

if (!rv && length > capacity && 1 == capacity &&
length <= ROSIDL_TYPESUPPORT_MICROXRCEDDS_C_STRING_RESERVATION)
{
rcutils_allocator_t allocator = rcutils_get_default_allocator();
char * data = (char *)allocator.reallocate(
str->data, ROSIDL_TYPESUPPORT_MICROXRCEDDS_C_STRING_RESERVATION, allocator.state);
if (NULL != data) {
str->data = data;
str->capacity = ROSIDL_TYPESUPPORT_MICROXRCEDDS_C_STRING_RESERVATION;
cdr->error = false;
rv = ucdr_deserialize_array_char(cdr, str->data, length);
}
}

if (rv) {
str->size = (length == 0) ? 0 : length - 1;
} else if (length > str->capacity) {
// Skip the string, keeping the buffer aligned for the next member
cdr->error = false;
cdr->last_data_size = 1;
str->size = 0;
ucdr_align_to(cdr, sizeof(char));
ucdr_advance_buffer(cdr, length);
}

return rv;
}

#endif // ROSIDL_TYPESUPPORT_MICROXRCEDDS_C__MESSAGE_TYPE_SUPPORT_H_
1 change: 1 addition & 0 deletions rosidl_typesupport_microxrcedds_c/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<!-- ament_export_dependencies(rosidl_cmake) needs it findable downstream -->
<build_export_depend>rosidl_cmake</build_export_depend>

<depend>rcutils</depend>
<depend>rmw</depend>

<exec_depend>rosidl_parser</exec_depend>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,40 +353,15 @@ static bool _@(message.structure.namespaced_type.name)__cdr_deserialize(
ros_message->@(member.name).size = size;

for (size_t i = 0; rv && i < size; i++) {
size_t capacity = ros_message->@(member.name).data[i].capacity;
uint32_t string_size;
char * data = ros_message->@(member.name).data[i].data;
rv = ucdr_deserialize_sequence_char(cdr, data, capacity, &string_size);
if (rv) {
ros_message->@(member.name).data[i].size = (string_size == 0) ? 0 : string_size - 1;
} else if(string_size > capacity){
cdr->error = false;
cdr->last_data_size = 1;
ros_message->@(member.name).data[i].size = 0;
ucdr_align_to(cdr, sizeof(char));
ucdr_advance_buffer(cdr, string_size);
}
rv = rosidl_typesupport_microxrcedds_c__deserialize_string(cdr, &ros_message->@(member.name).data[i]);
}
@[ end if]@
@[ end if]@
}
@[ elif isinstance(member.type, BasicType)]@
rv = ucdr_deserialize_@(get_suffix(member.type.typename))(cdr, &ros_message->@(member.name));
@[ elif isinstance(member.type, AbstractString)]@
{
size_t capacity = ros_message->@(member.name).capacity;
uint32_t string_size;
rv = ucdr_deserialize_sequence_char(cdr, ros_message->@(member.name).data, capacity, &string_size);
if (rv) {
ros_message->@(member.name).size = (string_size == 0) ? 0 : string_size - 1;
} else if(string_size > capacity){
cdr->error = false;
cdr->last_data_size = 1;
ros_message->@(member.name).size = 0;
ucdr_align_to(cdr, sizeof(char));
ucdr_advance_buffer(cdr, string_size);
}
}
rv = rosidl_typesupport_microxrcedds_c__deserialize_string(cdr, &ros_message->@(member.name));
@[ elif isinstance(member.type, AbstractWString)]@
// Micro CDR does not support WString type.
@[ elif isinstance(member.type, NamespacedType)]@
Expand Down
1 change: 1 addition & 0 deletions test/c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ if(BUILD_TESTING)
ament_add_gtest(${TEST_NAME}
src/test_typesupport.cpp
src/cross_serialization_tests.cpp
src/test_string_reservation.cpp
)

target_link_libraries(${TEST_NAME}
Expand Down
Loading
Loading