Skip to content

Drop C++ standard to C++17 and enhance multicast T2O support#126

Open
chace219 wants to merge 10 commits into
nimbuscontrols:masterfrom
chace219:master
Open

Drop C++ standard to C++17 and enhance multicast T2O support#126
chace219 wants to merge 10 commits into
nimbuscontrols:masterfrom
chace219:master

Conversation

@chace219

@chace219 chace219 commented Jul 1, 2026

Copy link
Copy Markdown

This pull request introduces support for receiving Class 1/3 I/O data over multicast in the ConnectionManager and related socket classes, enabling compatibility with devices that use multicast T2O (Target-to-Originator) connections. It also includes a downgrade of the C++ standard requirement from C++20 to C++17 for compatibility with the Luckfox/RV1106 SDK toolchain, and several robustness improvements in socket handling.

Multicast I/O Support and Socket Handling:

  • Added logic in ConnectionManager.cpp to detect multicast T2O endpoints from T2O_SOCKADDR_INFO, join the appropriate multicast group, and bind sockets accordingly, including new methods findOrCreateMulticastSocket and attachIoReceiveHandler to manage multicast and unicast sockets. [1] [2] [3]
  • Extended UDPBoundSocket to support binding to multicast groups, joining and dropping multicast group membership, and cleaning up on destruction. The constructor now takes a bindToGroup flag, and new methods manage multicast group membership. [1] [2]

C++ Standard Compatibility:

  • Downgraded the required C++ standard from C++20 to C++17 in CMakeLists.txt and updated the documentation in README.md to reflect this change, ensuring compatibility with GCC 8.3 and the Luckfox/RV1106 SDK. [1] [2]

Robustness Improvements:

  • Improved the BaseSocket::select method to avoid undefined behavior when called with an empty socket list by sleeping for the timeout duration instead of dereferencing an empty range.

Platform Compatibility:

  • Added platform-specific includes for socket headers to ConnectionManager.cpp and UDPBoundSocket.cpp to ensure portability across Unix and Windows systems. [1] [2]

I/O Data Handling:

  • Enhanced handling of sequence counts in Class 1/3 I/O connections to avoid advertising a nonzero connection size for null connections, preventing Forward_Open failures with conformant adapters.

chace219 and others added 10 commits June 16, 2026 15:43
Upstream sets CMAKE_CXX_STANDARD 20, which the SDK cross toolchain
(arm-rockchip830-linux-uclibcgnueabihf-g++ 8.3.0) cannot compile. The
codebase uses no C++20-only features, so dropping to C++17 is a clean
change. A bare set() in CMakeLists also overrides -DCMAKE_CXX_STANDARD
from the buildroot package, so the source must carry the standard.

Cross-compiled clean (lib + all examples incl. implicit_messaging) for
ARM with GCC 8.3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
EIPScanner previously only set up a unicast T2O receive socket
(findOrCreateSocket bound to host:2222), ignoring T2O_SOCKADDR_INFO. So
adapters that produce inputs to a multicast group were never received and
the scanner fell back to / required point-to-point.

This adds multicast T2O receive:
  - UDPBoundSocket::joinMulticastGroup() — IP_ADD_MEMBERSHIP on the bound
    socket; IP_DROP_MEMBERSHIP in the destructor.
  - ConnectionManager parses T2O_SOCKADDR_INFO from the Forward_Open
    response; if the advertised T2O address is multicast (224/4) it
    creates a group-joined receive socket, else unicast (unchanged).
  - Shared receive handler (attachIoReceiveHandler) demuxes by T2O
    connection id for both unicast and multicast sockets.

Selectable per connection by the originator requesting MULTICAST vs P2P
t2o network connection params. Cross-compiles C++17/GCC 8.3 for ARM.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Binding the multicast receive socket to INADDR_ANY:2222 alongside the
unicast receive socket on the same port made unicast-vs-multicast
delivery ambiguous in mixed deployments. Add a bindToGroup option to
UDPBoundSocket and bind the multicast socket to the group address so it
only receives that group's datagrams; unicast still binds INADDR_ANY.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
*std::max_element() over an empty range returns end(); dereferencing it is
undefined behaviour and segfaulted the whole process whenever select() ran
with no open sockets — e.g. right after a Forward_Open was rejected, leaving
ConnectionManager::_socketMap empty (every failed connection killed the daemon).
Sleep out the timeout and return when the socket list is empty.
forwardOpen() unconditionally added 2 to both O2T and T2O network
connection parameters for Class 1/3 connections to reserve the 2-byte
sequence count carried by I/O data. That is wrong for a NULL connection
(the Input-Only / Listen-Only O2T heartbeat, e.g. assembly instance 198
on the Joral ProxEncoder, "0 bytes"): a null leg carries no data and no
sequence count, so the +2 made a 0-byte heartbeat advertise connection
size 2. Conformant adapters reject that with Forward_Open extended
status 0x0123 (invalid O2T network connection type), so no Class 1 I/O
connection could ever open against such a device.

Only reserve the sequence count on a real (non-null) data leg, gated on
the per-leg connection type from the parameter builder.
Fix socket selection and connection size handling for NULL legs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant