Implemented new C++ logic

This commit is contained in:
Martino Ferrari
2026-06-12 15:25:13 +02:00
parent 617b5bd712
commit f25bd7f08e
220 changed files with 39185 additions and 850 deletions
@@ -0,0 +1,274 @@
#ifndef UDPS_SERVER_H_
#define UDPS_SERVER_H_
/**
* @file UDPSServer.h
* @brief Multi-client UDPS session-management and fragmented-send helper.
*
* UDPSServer is a plain C++ helper (not a MARTe2 Object) that encapsulates:
* - Unicast mode: up to UDPS_SERVER_MAX_UNICAST_CLIENTS simultaneous UDP clients
* that self-register via CONNECT datagrams.
* - Multicast mode: TCP listener for CONNECT + CONFIG delivery; UDP multicast
* socket for DATA datagrams.
* - Static clients: pre-configured destinations that never need to send CONNECT
* (backward-compat for push-to-fixed-IP use cases).
*
* Threading model: UDPSServer is NOT thread-safe. All public methods must be
* called from the same thread (the owner's Execute() thread).
*/
#include "BasicTCPSocket.h"
#include "BasicUDPSocket.h"
#include "InternetHost.h"
#include "StreamString.h"
#include "StructuredDataI.h"
#include "UDPSProtocol.h"
namespace MARTe {
/**
* @brief Multi-client / multicast UDPS server helper.
*
* Usage pattern:
* @code
* UDPSServer server;
* server.Initialise(data); // in component Initialise()
* server.Start(); // in PrepareNextState() / Start()
* // inside Execute() loop:
* server.ServiceClients(); // poll CONNECT / DISCONNECT / ACK
* if (server.HasClients()) {
* server.SendConfig(cfgBuf, cfgSize); // when config changes
* server.SendData(counter, dataBuf, dataSize);
* }
* server.Stop(); // in StopCurrentStateExecution()
* @endcode
*/
class UDPSServer {
public:
/** Maximum number of simultaneous unicast clients. */
static const uint32 UDPS_SERVER_MAX_UNICAST_CLIENTS = 16u;
/** Maximum number of simultaneous multicast TCP control connections. */
static const uint32 UDPS_SERVER_MAX_TCP_CLIENTS = 8u;
/** Default stale-client eviction timeout (seconds). */
static const uint32 UDPS_SERVER_DEFAULT_CLIENT_TIMEOUT_S = 30u;
/** Default maximum UDP payload size (bytes, EXCLUDING the 17-byte header). */
static const uint32 UDPS_SERVER_DEFAULT_MAX_PAYLOAD = 1400u;
UDPSServer();
~UDPSServer();
/**
* @brief Read configuration from a StructuredDataI node.
*
* Expected keys (all optional except Port for unicast):
* - Port (uint16) UDP port to bind (unicast) or TCP listen port (multicast).
* - MulticastGroup (char*) IPv4 multicast address; presence enables multicast mode.
* - DataPort (uint16) UDP port used for DATA datagrams in multicast mode
* (defaults to Port+1 if omitted).
* - MaxPayloadSize (uint32) Max payload bytes per datagram, excluding header.
* Defaults to UDPS_SERVER_DEFAULT_MAX_PAYLOAD.
* - ClientTimeout (uint32) Seconds before a silent unicast client is evicted.
* Defaults to UDPS_SERVER_DEFAULT_CLIENT_TIMEOUT_S.
* Set to 0 to disable timeout-based eviction.
*/
bool Initialise(StructuredDataI &data);
/**
* @brief Open sockets and begin accepting clients.
* @return true on success.
*/
bool Start();
/**
* @brief Close all sockets and evict all clients. Frees cached CONFIG.
*/
bool Stop();
/**
* @brief Non-blocking poll for incoming CONNECT / DISCONNECT / ACK messages.
*
* Must be called regularly from the owner's Execute() main loop.
* In multicast mode also polls the TCP listener for new connections.
*/
void ServiceClients();
/**
* @brief Send a CONFIG payload to all active clients.
*
* Also stores a copy as the cached CONFIG, which is automatically sent to
* any new CONNECT client.
*
* @param payload Pointer to fully-assembled CONFIG payload (caller-owned).
* @param payloadSize Byte count of payload.
* @return true if at least one send succeeded (or no clients are connected).
*/
bool SendConfig(const uint8 *payload, uint32 payloadSize);
/**
* @brief Send a DATA payload to all active clients.
*
* @param counter Per-update sequence counter (same for all fragments).
* @param payload Pointer to fully-assembled DATA payload (caller-owned).
* @param payloadSize Byte count of payload.
* @return true if all sends succeeded.
*/
bool SendData(uint32 counter, const uint8 *payload, uint32 payloadSize);
/**
* @brief Add a static unicast destination that never needs to send CONNECT.
*
* The entry is never evicted by the timeout mechanism. Duplicate
* (ip, port) pairs are silently ignored.
*
* @param ip Destination IPv4 address string.
* @param port Destination UDP port.
* @return true if the client was added (or was already present).
*/
bool AddStaticClient(const char8 *ip, uint16 port);
/** @return Number of currently active clients (unicast + TCP). */
uint32 GetClientCount() const;
/** @return true if at least one client is active. */
bool HasClients() const;
/** @return true if server is in multicast mode. */
bool IsMulticast() const;
/** @return Configured port number. */
uint16 GetPort() const;
/** @return Configured maximum payload size (excluding header). */
uint32 GetMaxPayloadSize() const;
private:
// -------------------------------------------------------------------------
// Per-client state (unicast)
// -------------------------------------------------------------------------
struct UDPSClientEntry {
char8 ipAddr[64]; ///< Client IPv4 address string
uint16 clientPort; ///< Client source port
uint64 lastSeenTicks; ///< HighResolutionTimer ticks at last contact
bool active; ///< Slot is in use
bool isStatic; ///< Never evicted by timeout; no CONNECT required
};
// -------------------------------------------------------------------------
// Private helpers
// -------------------------------------------------------------------------
/**
* @brief Send a fragmented UDPS packet via a UDP socket.
*
* @param sock Socket to write through.
* @param dest If non-NULL, SetDestination is called before each write
* (unicast unconnected socket). If NULL, assumes the socket
* is already connected (multicast dataSocket).
* @param type UDPS_TYPE_DATA or UDPS_TYPE_CONFIG.
* @param counter Sequence counter.
* @param payload Payload bytes.
* @param payloadSize Payload byte count.
* @return true if all fragments were written without error.
*/
bool SendFragmentedUDP(BasicUDPSocket &sock,
InternetHost *dest,
uint8 type,
uint32 counter,
const uint8 *payload,
uint32 payloadSize);
/**
* @brief Send a fragmented UDPS packet via a TCP socket.
*
* Used in multicast mode to push CONFIG to each TCP control client.
*/
bool SendFragmentedTCP(BasicTCPSocket &sock,
uint8 type,
uint32 counter,
const uint8 *payload,
uint32 payloadSize);
/** Evict unicast clients that have been silent longer than clientTimeoutTicks. */
void EvictStaleUnicastClients();
/** Handle a CONNECT datagram received on serverSocket. */
void HandleUnicastConnect(const InternetHost &src);
/** Handle a DISCONNECT datagram received on serverSocket. */
void HandleUnicastDisconnect(const InternetHost &src);
/** Handle an ACK datagram received on serverSocket. */
void HandleUnicastAck(const InternetHost &src);
/**
* @brief Find a unicast client slot by IP + port.
* @return Slot index, or UDPS_SERVER_MAX_UNICAST_CLIENTS if not found.
*/
uint32 FindUnicastClient(const char8 *ip, uint16 port) const;
/**
* @brief Find the oldest (lowest lastSeenTicks) non-static unicast client.
* @return Slot index, or UDPS_SERVER_MAX_UNICAST_CLIENTS if none.
*/
uint32 FindOldestUnicastClient() const;
/** Close slot @p idx and mark it inactive. */
void EvictUnicastClient(uint32 idx);
/** Accept a new multicast TCP connection and send cached CONFIG. */
void HandleMulticastTCPConnect(BasicTCPSocket *newClient, uint32 idx);
/** Close TCP client slot @p idx. */
void EvictTCPClient(uint32 idx);
/** Cache a copy of a CONFIG payload for future CONNECT clients. */
bool CacheConfig(const uint8 *payload, uint32 payloadSize);
// -------------------------------------------------------------------------
// Configuration
// -------------------------------------------------------------------------
uint16 port;
uint32 maxPayloadSize;
StreamString multicastGroup;
uint16 dataPort;
bool useMulticast;
uint64 clientTimeoutTicks; ///< 0 = disabled
// -------------------------------------------------------------------------
// Unicast state
// -------------------------------------------------------------------------
UDPSClientEntry unicastClients[UDPS_SERVER_MAX_UNICAST_CLIENTS];
uint32 numUnicastClients;
BasicUDPSocket serverSocket; ///< Bound to port; receives CONNECT/DISCONNECT/ACK
BasicUDPSocket uniSendSocket; ///< Unconnected; SetDestination before each Write
// -------------------------------------------------------------------------
// Multicast state
// -------------------------------------------------------------------------
BasicTCPSocket tcpListener;
BasicTCPSocket *tcpClients[UDPS_SERVER_MAX_TCP_CLIENTS];
uint32 numTCPClients;
BasicUDPSocket dataSocket; ///< Connected to multicastGroup:dataPort
// -------------------------------------------------------------------------
// Shared state
// -------------------------------------------------------------------------
uint8 *cachedConfig; ///< Last SendConfig() payload (heap-allocated)
uint32 cachedConfigSize;
uint8 *sendBuf; ///< Pre-allocated fragment TX buffer
uint32 sendBufCapacity; ///< UDPS_HEADER_SIZE + maxPayloadSize
uint32 configCounter; ///< Sequence counter for CONFIG packets
bool started;
};
} // namespace MARTe
#endif // UDPS_SERVER_H_