Implemented new C++ logic
This commit is contained in:
@@ -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_
|
||||
Reference in New Issue
Block a user