ecaludp is the underlying implementation for UDP traffic in eCAL. It transparently fragments and reassembles messages to provide support for big messages. An ecaludp socket is not limited to the ordinary UDP datagram size of ~64KiB. It can transport messages up to 4 GiB.
ecaludp has npcap support for efficient receiving of multicast traffic in Windows. For that, the udpcap library is used.
ecaludp requires C++14.
ecalupd features an asio-style API. Check out the following samples to see its usage:
-
ecaludp_sample: The regular ecaludp socket API
-
ecaludp_npcap_sample The (slightly different) npcap socket API. Only available for Windows.
The following dependencies are always required to build ecaludp:
Dependency | License | Default Integration |
---|---|---|
asio | Boost Software License | git submodule |
recycle | BSD-3 | git submodule |
Additionally, when building with Npcap, the following dependencies are required:
Dependency | License | Default Integration |
---|---|---|
Udpcap | Apache 2.0 | git submodule |
npcap (SDK only) |
Npcap License | Fetched by CMake |
Pcap++ | Unlicense | Fetched by CMake |
When building the tests, the following dependency is required:
Dependency | License | Default Integration |
---|---|---|
Googletest | BSD-3 | git submodule |
-
Install cmake and git / git-for-windows
-
Checkout this repo and the asio submodule
git clone https://github.com/eclipse-ecal/ecaludp.git cd ecaludp git submodule init git submodule update
-
CMake the project (check the next section for available CMake options)
mkdir _build cd _build cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=_install
-
Build the project
- Linux:
make
- Windows: Open
_build\ecaludp.sln
with Visual Studio and build the example project
- Linux:
-
Check the functionality with the
udpcap_sample /.exe
sample project!
You can set the following CMake Options to control how ecaludp is built:
Option | Type | Default | Explanation |
---|---|---|---|
ECALUDP_ENABLE_NPCAP |
BOOL |
OFF |
Enable the NPCAP based socket emulation to receive UDP data without actually opening a socket. |
ECALUDP_BUILD_SAMPLES |
BOOL |
ON |
Build the ecaludp sample project. |
ECALUDP_BUILD_TESTS |
BOOL |
OFF |
Build the the ecaludp tests. Requires gtest to be available. If ecaludp is built as static or object library, additional tests will be built that test the internal implementation that is not available as public API. |
ECALUDP_USE_BUILTIN_ASIO |
BOOL |
ON |
Use the builtin asio submodule. If set to OFF , asio must be available from somewhere else (e.g. system libs). |
ECALUDP_USE_BUILTIN_RECYCLE |
BOOL |
ON |
Use the builtin steinwurf::recycle submodule. If set to OFF , recycle must be available from somewhere else (e.g. system libs). |
ECALUDP_USE_BUILTIN_UDPCAP |
BOOL |
ON (when building with npcap) |
Use the builtin udpcap submodule. Only needed if ECALUDP_ENABLE_NPCAP is ON . If set to OFF , udpcap must be available from somewhere else (e.g. system libs). Setting this option to ON will also use the default dependencies of udpcap (npcap-sdk, pcapplusplus). |
ECALUDP_USE_BUILTIN_GTEST |
BOOL |
ON (when building tests) |
Use the builtin GoogleTest submodule. Only needed if FINEFTP_SERVER_BUILD_TESTS is ON . If set to OFF , GoogleTest must be available from somewhere else (e.g. system libs). |
ECALUDP_LIBRARY_TYPE |
STRING |
Controls the library type of Ecaludp by injecting the string into the add_library call. Can be set to STATIC / SHARED / OBJECT. If set, this will override the regular BUILD_SHARED_LIBS CMake option. If not set, CMake will use the default setting, which is controlled by BUILD_SHARED_LIBS . |
An ecaludp message consists of one or multiple datagrams. How many datagrams that will be is determined by the fragmentation.
Each datagram carries a header starting at byte 0. The header is defined in header_v5.h. Alien datagrams can be eliminated by comparing the magic
bytes with a predefined value.
Some datagrams may also carry payload directly after the header.
size | Name | Explanation |
---|---|---|
32 bit | magic |
User-defined binary data. Used for identifying and dropping alien traffic. |
8 bit | version |
Header version. Must be 5 for protocol version 5 |
24 bit | reserved | Must be sent as 0. |
32 bit little-endian |
type |
Datagram type. Must be one of: 1 : fragmented_message_info 2 : fragment 3 : non_fragmented_message |
32 bit signed little-endian |
id |
Random ID to match fragmented parts of a message. Used differently depending on the message type: - type == fragmented_message_info (1) : The Random ID that this fragmentation info will be applied to - type == fragment (2) : The Random ID that this fragment belongs to. Used to match fragments to their fragmentation info - type == non_fragmented_message (3) : Unused field. Must be sent as -1. Must not be evaluated. |
32 bit unsigned little-endian |
num |
Fragment number. Used differently depending on the datagram type: - type == fragmented_message_info (1) : Amount of fragments that this message was split into. - type == fragment (2) : The number of this fragment - type == non_fragmented_message (3) : Unused field. Must be sent as 1 . Must not be evaluated. |
32 bit unsigned little-endian |
len |
Payload length. Used differently depending on the datagram type. The payload must start directly after the header. - type == fragmented_message_info (1) : Length of the original message before it got fragmented. Messages of this type must not carry any payload themselves. - type == fragment (2) : The payload lenght of this fragment - type == non_fragmented_message (3) : The payload length of this message |
len bytes |
payload | Payload of the message or fragment. |
There are two different types of messages that can be sent: Messages that are fragmented and messages that are not fragmented.
-
Non-fragmented data
- The entire message consists of 1 datagram carrying both a header and the payload.
- The header looks as follows:
-
type
is set tonon_fragmented_message (3)
-
id
is-1
-
num
is1
-
length
is the amount of payload bytes following after the header
-
-
Fragmented data
A message which had to be fragmented into
$n \in \mathbb{N}_0$ parts consists of$n+1$ datagrams:-
$1\times$ Fragmentation info- The first datagram carries the fragmentation info.
- The header looks as follows:
-
type
is set tofragmented_message_info (1)
-
id
is a random number. It is used to match the fragments to their fragmentation info and therefore must be unique for each fragmented message. -
num
is the amount of fragments that the message was split into (i.e.$n$ ) -
length
is the length of the original message before it got fragmented
-
- This datagram must not carry any payload.
-
$n\times$ Fragments- The following
$n$ datagrams carry the fragments. - The header looks as follows:
-
type
is set tofragment (2)
-
id
is the random number that was used in the fragmentation info -
num
is the number of this fragment (i.e.$1$ to$n$ ) -
length
is the length of the payload of this fragment.
-
- The payload of each fragment is a part of the original message.
- The following
-
The following diagram shows the communication between the sender and the receiver. The sender sends a non-fragmented message and a fragmented message. The fragmented message consists of n fragments.
Sender Receiver
| |
| Non-fragmented message |
|----------------------------------->|
| |
| Fragmentation info (n fragments) |
|----------------------------------->|
| |
| Fragment 1 |
|----------------------------------->|
| |
| Fragment 2 |
|----------------------------------->|
| |
| ... |
|----------------------------------->|
| |
| Fragment (n) |
|----------------------------------->|
| |
| |