ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

ROS service TCP packet structure

asked 2021-06-14 08:12:17 -0600

m.bahno gravatar image

Is somewhere in documentation stated the structure of a TCP packet used for persistent service communication? I deduced, that last bytes correspond to service arguments (or response values), however the rest is a undecodable for me.

I want to sniff (tcpdump) TCP packets sent by ROS service between two nodes. However, I need the detect correct packets from all packets sent by a node, so I think I need to locate bytes, which uniquely identify the service. But where they are and where I can find the signature of the specific service? I tried to locate md5 sum, but it is not there.

Thank you for any hints, I know, I can spend many hours reading the source code to understand in detail, how serialisation works in ROS, but a simple packet structure would be a huge help to me.

edit retag flag offensive close merge delete

Comments

IIRC, Wireshark has a dissector for ROS traffic built-in for a few years now. I'm not entirely sure whether it supports services though, but that would be easily checked.


Edit: this one: TCP based Robot Operating System protocol (TCPROS).

gvdhoorn gravatar image gvdhoorn  ( 2021-06-14 09:40:39 -0600 )edit

Thank you for pointing to this option! However, it does not decode ROS services.

m.bahno gravatar image m.bahno  ( 2021-06-14 10:22:06 -0600 )edit
1

Afaik services use TCPROS as well, so I'm curious why it wouldn't dissect it.


Edit: testing it a bit, it does seem to be able to dissect the request header, but not the payload. Perhaps it doesn't support or achieve reassembly of the stream properly:


wireshark tcpros service dissection

As to whether there is a "simple packet structure": afaik there is no single document which describes that. Perhaps wiki/TCPROS comes closest.

gvdhoorn gravatar image gvdhoorn  ( 2021-06-14 10:38:49 -0600 )edit

Though this is true only for service connection initialisation (every time for non-persistent services, but only once in the beginning for persistent ones). So for my usecase (starting to listen in the middle of the communication), it does not help. But it is good to know, wireshark provides dissection of some ROS messages.

m.bahno gravatar image m.bahno  ( 2021-06-15 08:57:00 -0600 )edit

So if you don't know the service types involved, how would you go about dissecting the data? Service payload doesn't seem to include any indication of the layout of the data, which seems to make dissection difficult.

gvdhoorn gravatar image gvdhoorn  ( 2021-06-15 10:49:15 -0600 )edit

I do know the service type. But for persistent TCP service connection, only first packet contains the header and I am not guaranteed to catch it (most of the times I will not). So my goal was to dissect ROS service message WITHOUT header (which persistent services do not send) of known service. Or at least get some service-unique part...

m.bahno gravatar image m.bahno  ( 2021-06-15 11:17:18 -0600 )edit

For me, it is enough to recognise the packet among others (to sniff all packets of one service). Since the service packet is quite long (~ 70 bytes + payload), I supposed there are some bytes telling of what service this packet belongs to (since in one ROS node, more service servers can operate). So far I did simple packet difference and located bytes, which change on different ROS runs for the same service, but that's far from perfect. I also tried to use service URIs (to catch only packets between two ports - client and server), however client port is harder to obtain, can change and this approach is useless for more clients.

Maybe I get a bit off topic in here, but it is a background motivation for my question.

m.bahno gravatar image m.bahno  ( 2021-06-15 11:18:22 -0600 )edit

I do know the service type.

well that helps. But from what I remember/saw, plain payload of service invocation does not include any indication of which service type is involved. Interpretation of bytes is dependent on external/prior exchanged information between client and server.

Is it really possible to dissect the data without having witnessed the session setup?

Since the service packet is quite long (~ 70 bytes + payload)

is this always the case? The AddTwoInts service I tested above has a payload of around 24 bytes I believe (a, b and some other number).

So my goal was to dissect ROS service message WITHOUT header (which persistent services do not send) of known service. Or at least get some service-unique part...

yes, so that's what I was referring to. If you miss out the header, the rest if just "random" binary data.

gvdhoorn gravatar image gvdhoorn  ( 2021-06-15 11:36:30 -0600 )edit

1 Answer

Sort by ยป oldest newest most voted
0

answered 2021-06-16 04:51:05 -0600

m.bahno gravatar image

updated 2021-06-16 04:52:10 -0600

After some time, I was able (with help of gvdhoorn) to get the structure by myself (I found no clear structure description in documentation). So this is what I found out on the way:

For persistent services, service call TCP packets structure is following (excluding ROS non-related TCP structure):

Request: 4B (payload length) + XB (payload = all service arguments)

Response: 1B (sevice status 'ok' byte - see here) + 4B (payload length) + XB (payload = all service return values)

Unfortunately, there is no service identifier included in those messages, only on initial handshake. However, one option would be to include one more argument (return value), which would be constant identifier. Another option is to find out client communication port and dump only communication on this port. Nevertheless, both approaches have its disadvantages.

Related tips&tricks:

  • wireshark is able to recognize ROS TCP packet and read header - usefull for ROS messages or non-persistant services
edit flag offensive delete link more

Comments

1

If a posteriori analysis would be good enough for your use-case you could write a Python script with something like caizhengxin/python-libpcap or KimiNewt/pyshark which iterates over all packets and then reconstructs the service exchanges based on the XML-RPC traffic exchanged by the nodes and the master.

That should not be too difficult, provided your capture is started before the persistent connection is started.

Or: if you know the types of services, you could "tell" your script that information and deserialise data that way.

gvdhoorn gravatar image gvdhoorn  ( 2021-06-16 06:35:35 -0600 )edit

A posteriori analysis is not a problem in principle. But significant disadventage of this approach is, that you collect all TCP traffic data and for my usecase (runtime in hours with many topics at ~10-1000 Hz publishing frenquency) it would generate huge amount of data. I prefer to target the communication. So in the end I used the option with known client and server port and sniff only that communication.

However, if persistent connection breakes, I am in trouble. So it is a compromise...

m.bahno gravatar image m.bahno  ( 2021-06-16 07:16:06 -0600 )edit

It gets a bit academic at this point, but it's possible to use a live-capture and process it live. Possibly even with a small ringbuffer. pyshark apparently can do this: Reading from a live interface using a ring buffer.

That would avoid capturing all traffic, as you could literally listen in on the XML-RPC traffic and then figure out which packets to keep by filtering for those streams.

(lots of hand waving here of course)


Edit: if you go in this direction I would really be interested in this and possibly contribute.

gvdhoorn gravatar image gvdhoorn  ( 2021-06-16 07:24:15 -0600 )edit

It gets a bit academic at this point, but it's possible to use a live-capture and process it live.

I suppose it would. Unfortunately, I am forced to go for effective way right now, so as long it works for my use-case, I will stick to that and not to make a complete solution. I am actually using pyshark right know, but I have some problems with it.

If end up going for the complete solutions, I would like to share it, but I am not sure if I company I work for allows it. But if so, I'll let you know. Personally I also find this as the most complete and elegant solution, but sometimes one has to go for a quick one... Anyway, thanks again for inspiring comments!

m.bahno gravatar image m.bahno  ( 2021-06-16 08:11:33 -0600 )edit

Question Tools

Stats

Asked: 2021-06-14 08:12:17 -0600

Seen: 652 times

Last updated: Jun 16 '21