Files
MARTe-Integrated-Components/Source/Components/Interfaces/TCPStreamService/TCPSServiceStream.h
T
Martino FerrariandClaude Opus 4.6 50d85363a3 feat(tcp): TCPStreamer DataSources, in-process TCPStreamService, stream multiplexing and TCPStreamJoin
Add TCPStreamer/TCPStreamerClient (TCP transport behind the UDPSServerI/UDPSClientI
seam), an optional single in-process TCPStreamService serving many streams over
worker threads, multiplexed SUBSCRIBE (comma list, stream index in fragmentIdx),
and TCPStreamJoin, which merges several streams into one sample-and-hold stream
paced by a master. StreamHub takes a comma list of streams over one connection.
Includes GTests, E2E scenarios s58-s73 and docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-11-06 13:41:27 +01:00

111 lines
4.0 KiB
C++

#ifndef TCPS_SERVICE_STREAM_H_
#define TCPS_SERVICE_STREAM_H_
/**
* @file TCPSServiceStream.h
* @brief UDPSServerI handle that publishes one named stream through a
* TCPStreamService instead of through a private listening socket.
*
* It is what a TCPStreamer uses when its `Service` key is set. All socket work
* (accept, handshake, flush, eviction) is done by the service's threads; the
* producer thread only builds the frame and copies it into the bounded queue of
* every subscribed connection (SendData never blocks on a socket).
*/
#include "FastPollingMutexSem.h"
#include "ReferenceT.h"
#include "StreamString.h"
#include "MutexSem.h"
#include "TCPSStreamTapI.h"
#include "TCPStreamService.h"
#include "UDPSProtocol.h"
#include "UDPSTransportI.h"
namespace MARTe {
struct TCPSConn;
class TCPSServiceStream : public UDPSServerI {
public:
/** Default maximum payload bytes per frame (matches TCPSServer). */
static const uint32 TCPSS_DEFAULT_MAX_PAYLOAD = 60000u;
TCPSServiceStream(const char8 *serviceObjectName, const char8 *streamName);
virtual ~TCPSServiceStream();
/** Keys: MaxPayloadSize (uint32, 1..1 MiB, default 60000). */
virtual bool Initialise(StructuredDataI &data);
/** Resolve the service by name and register the stream (fails on a duplicate name). */
virtual bool Start();
/** Unregister and drop every subscriber (idempotent). */
virtual bool Stop();
/** No-op: the service threads do the housekeeping. */
virtual void ServiceClients();
virtual bool SendConfig(const uint8 *payload, uint32 payloadSize);
virtual bool SendData(uint32 counter, const uint8 *payload, uint32 payloadSize);
virtual bool HasClients() const;
virtual bool IsMulticast() const;
/** @return the service's bound port (0 while the service is unresolved). */
virtual uint16 GetPort() const;
const char8 *GetStreamName() const;
uint32 GetClientCount() const;
/** @return DATA frames discarded for slow subscribers (all time). */
uint64 GetClientDrops() const;
uint32 GetMaxPayloadSize() const;
/** Most taps one stream can carry. */
static const uint32 TCPSS_MAX_TAPS = 4u;
/**
* Observe every CONFIG / DATA this stream publishes. The cached CONFIG (if any) is
* replayed to the new tap before AddTap returns. Taps run on the producer thread.
* @return false if the tap table is full.
*/
bool AddTap(TCPSStreamTapI *tap);
/** Remove a tap; once it returns no callback is running or will start. */
void RemoveTap(TCPSStreamTapI *tap);
/* ---- called by TCPStreamService with its topology lock held ---- */
/** Add a connection and prime it with the cached CONFIG. @return false if full. */
bool AttachConn(TCPSConn *c, uint16 streamIdx);
void DetachConn(TCPSConn *c);
/** Ask every subscriber to close and forget them. */
void DropAllConns();
private:
bool BuildFrame(uint8 *&buf, uint32 &cap, uint8 type, uint32 counter,
const uint8 *payload, uint32 payloadSize, uint32 &frameBytes);
void Distribute(bool isConfig, const uint8 *frame, uint32 frameBytes);
StreamString serviceName;
mutable StreamString streamName;
ReferenceT<TCPStreamService> service;
bool registered;
uint32 maxPayloadSize;
FastPollingMutexSem mutex; ///< guards subs, numSubs, cachedConfig*, drops
TCPSConn **subs;
uint16 *subIdx; ///< stream index each subscriber knows this stream by
uint32 capSubs;
volatile uint32 numSubs;
uint8 *cachedConfigFrame;
uint32 cachedConfigBytes;
uint32 cachedConfigCap;
uint32 configCounter;
uint64 drops;
FastPollingMutexSem tapMutex; ///< held while a tap callback runs
TCPSStreamTapI *taps[TCPSS_MAX_TAPS];
volatile uint32 numTaps;
uint8 *dataFrame; ///< producer-thread scratch
uint32 dataFrameCap;
TCPSServiceStream(const TCPSServiceStream &);
TCPSServiceStream &operator=(const TCPSServiceStream &);
};
} // namespace MARTe
#endif // TCPS_SERVICE_STREAM_H_