eProsima / Micro-XRCE-DDS

An XRCE DDS implementation. Looking for commercial support? Contact info@eprosima.com
Apache License 2.0
156 stars 17 forks source link

Sequence types fail in serializing/deserializing #178

Closed hr-ti closed 2 weeks ago

hr-ti commented 2 weeks ago

I'm using microROS for my STM32 board and attempting to use services. The issue I'm getting on the MCU side is that deserializing any array/sequence type in a service request results in an error where the data length exceeds the capacity of the buffer, which is defaulting to 0 (erroring here).

I've verified that UDP traffic is working correctly. So I can only suspect that the host side is incorrectly converting service requests either in the RMW or the agent, not too sure how to confirm so input here would be great.

Running my firmware through a debugger shows that it casts the appropriate service request typesupport onto the incoming ros_message once a service request is found, but capacity is always 0. Here's the generated typesupport code:

static bool _SetString_Request__cdr_deserialize(
  ucdrBuffer * cdr,
  void * untyped_ros_message)
{
  (void) cdr;

  bool rv = false;

  if (!untyped_ros_message) {
    return false;
  }
  _SetString_Request__ros_msg_type * ros_message = (_SetString_Request__ros_msg_type *)(untyped_ros_message);
  (void)ros_message;

  // Field name: data
  {
    size_t capacity = ros_message->data.capacity;
    uint32_t string_size;
    rv = ucdr_deserialize_sequence_char(cdr, ros_message->data.data, capacity, &string_size);
    if (rv) {
      ros_message->data.size = (string_size == 0) ? 0 : string_size - 1;
    } else if(string_size > capacity){
      cdr->error = false;
      cdr->last_data_size = 1;
      ros_message->data.size = 0;
      ucdr_align_to(cdr, sizeof(char));
      ucdr_advance_buffer(cdr, string_size);
    }
  }
  return rv;

My understanding could be wrong, but udr_deserialize_sequence_char uses ros_message->data.capacity to copy the appropriate amount of the input buffer cdr to ros_message. Here, ros_message->data.capacity is 0, udr_deserialize_sequence_char fails, rv is false and therefore causes an executor error.

Viewing the cdr buffer, I can see that the string I pass through is correct, including its length (+ null terminator), but ros_message attributes are set to 0.

I get similar results when using a bytearray, but passing an empty bytearray works since capacity == length = 0.

I'm lost on where the buffer capacity property is set, but I'm hoping this is a user error and not an error from RMW.

pablogs9 commented 2 weeks ago

Are you initializing your micro-ROS type's memory as explained here: https://docs.vulcanexus.org/en/latest/rst/tutorials/micro/memory_management/memory_management.html#message-memory ?

hr-ti commented 2 weeks ago

That did the trick! I'm surprised I didn't find this documentation until now, thanks anyways