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>
This commit is contained in:
1 parent
5562877c99
commit
50d85363a3
79 files changed
+12348
-138
No files matched your search
@@ -131,7 +131,8 @@ static float64 DequantValue(float64 raw, uint8 quantType,
|
||||
UDPStreamerClient::UDPStreamerClient() :
|
||||
MemoryDataSourceI(),
|
||||
UDPSClientListener(),
|
||||
client() {
|
||||
client(NULL_PTR(UDPSClientI *)) {
|
||||
client = new UDPSClient();
|
||||
serverAddress = UDPS_CLIENT_DEFAULT_ADDR;
|
||||
port = UDPS_CLIENT_DEFAULT_PORT;
|
||||
maxPayloadSize = UDPS_CLIENT_DEFAULT_MAX_PAYLOAD;
|
||||
@@ -160,9 +161,13 @@ UDPStreamerClient::UDPStreamerClient() :
|
||||
UDPStreamerClient::~UDPStreamerClient() {
|
||||
(void) dataSem.Post();
|
||||
|
||||
if (receiverUp) {
|
||||
(void) client.Stop();
|
||||
receiverUp = false;
|
||||
if (client != NULL_PTR(UDPSClientI *)) {
|
||||
if (receiverUp) {
|
||||
(void) client->Stop();
|
||||
receiverUp = false;
|
||||
}
|
||||
delete client;
|
||||
client = NULL_PTR(UDPSClientI *);
|
||||
}
|
||||
|
||||
HeapI *heap = GlobalObjectsDatabase::Instance()->GetStandardHeap();
|
||||
@@ -258,36 +263,49 @@ bool UDPStreamerClient::Initialise(StructuredDataI &data) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Forward the transport parameters to the shared UDPSClient receiver,
|
||||
* translating the DataSource parameter names to the UDPSClient keys. */
|
||||
if (ok) {
|
||||
ConfigurationDatabase cdb;
|
||||
ok = cdb.Write("ServerAddr", serverAddress);
|
||||
if (ok) { ok = cdb.Write("Port", static_cast<uint32>(port)); }
|
||||
if (ok && useMulticast) {
|
||||
ok = cdb.Write("MulticastGroup", multicastGroup);
|
||||
if (ok) { ok = cdb.Write("DataPort", static_cast<uint32>(dataPort)); }
|
||||
if (ok && (multicastInterface.Size() > 0u)) {
|
||||
ok = cdb.Write("Interface", multicastInterface);
|
||||
}
|
||||
}
|
||||
if (ok) { ok = cdb.Write("MaxPayloadSize", maxPayloadSize); }
|
||||
if (ok) { ok = cdb.Write("KeepAliveInterval", keepAliveInterval); }
|
||||
if (ok) { ok = cdb.Write("SilenceTimeout", silenceTimeout); }
|
||||
if (ok) { ok = cdb.Write("CPUMask", cpuMask); }
|
||||
if (ok) { ok = cdb.Write("StackSize", stackSize); }
|
||||
if (ok) { ok = cdb.MoveToRoot(); }
|
||||
if (ok) { ok = client.Initialise(cdb); }
|
||||
if (!ok) {
|
||||
REPORT_ERROR(ErrorManagement::ParametersError,
|
||||
"Could not configure the UDPSClient receiver.");
|
||||
}
|
||||
client.SetListener(this);
|
||||
ok = InitialiseTransport(data);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool UDPStreamerClient::InitialiseTransport(StructuredDataI &data) {
|
||||
/* Forward the transport parameters to the shared UDPSClient receiver,
|
||||
* translating the DataSource parameter names to the UDPSClient keys. */
|
||||
bool ok = true;
|
||||
ConfigurationDatabase cdb;
|
||||
ok = cdb.Write("ServerAddr", serverAddress);
|
||||
if (ok) { ok = cdb.Write("Port", static_cast<uint32>(port)); }
|
||||
if (ok && useMulticast) {
|
||||
ok = cdb.Write("MulticastGroup", multicastGroup);
|
||||
if (ok) { ok = cdb.Write("DataPort", static_cast<uint32>(dataPort)); }
|
||||
if (ok && (multicastInterface.Size() > 0u)) {
|
||||
ok = cdb.Write("Interface", multicastInterface);
|
||||
}
|
||||
}
|
||||
if (ok) { ok = cdb.Write("MaxPayloadSize", maxPayloadSize); }
|
||||
if (ok) { ok = cdb.Write("KeepAliveInterval", keepAliveInterval); }
|
||||
if (ok) { ok = cdb.Write("SilenceTimeout", silenceTimeout); }
|
||||
if (ok) { ok = cdb.Write("CPUMask", cpuMask); }
|
||||
if (ok) { ok = cdb.Write("StackSize", stackSize); }
|
||||
if (ok) { ok = cdb.MoveToRoot(); }
|
||||
if (ok) { ok = client->Initialise(cdb); }
|
||||
if (!ok) {
|
||||
REPORT_ERROR(ErrorManagement::ParametersError,
|
||||
"Could not configure the UDPSClient receiver.");
|
||||
}
|
||||
client->SetListener(this);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void UDPStreamerClient::SetClient(UDPSClientI *newClient) {
|
||||
if (client != NULL_PTR(UDPSClientI *)) {
|
||||
delete client;
|
||||
}
|
||||
client = newClient;
|
||||
}
|
||||
|
||||
bool UDPStreamerClient::SetConfiguredDatabase(StructuredDataI &data) {
|
||||
bool ok = MemoryDataSourceI::SetConfiguredDatabase(data);
|
||||
if (!ok) {
|
||||
@@ -377,7 +395,7 @@ bool UDPStreamerClient::PrepareNextState(const char8 *const currentStateName,
|
||||
const char8 *const nextStateName) {
|
||||
bool ok = true;
|
||||
if (!receiverUp) {
|
||||
ok = client.Start();
|
||||
ok = client->Start();
|
||||
if (ok) {
|
||||
receiverUp = true;
|
||||
}
|
||||
|
||||
@@ -160,6 +160,27 @@ public:
|
||||
*/
|
||||
virtual void OnUDPSDisconnected();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Configures the transport from the already-parsed members and
|
||||
* registers this object as its listener.
|
||||
* @details The default implementation configures the UDPSClient (unicast /
|
||||
* multicast). A subclass that installs another transport with SetClient()
|
||||
* overrides this to configure it instead.
|
||||
*/
|
||||
virtual bool InitialiseTransport(StructuredDataI &data);
|
||||
|
||||
/**
|
||||
* @brief Replaces the transport. Takes ownership; only valid before Start().
|
||||
*/
|
||||
void SetClient(UDPSClientI *newClient);
|
||||
|
||||
/* Configuration parameters shared with transport subclasses */
|
||||
StreamString serverAddress; /**< Server IP address. */
|
||||
uint16 port; /**< Server port. */
|
||||
uint32 cpuMask; /**< Background thread CPU affinity. */
|
||||
uint32 stackSize; /**< Background thread stack size. */
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Decodes a single snapshot from a DATA payload into @p dst.
|
||||
@@ -171,13 +192,9 @@ private:
|
||||
void DecodeSnapshot(const uint8 *payload, uint32 size, uint8 *dst);
|
||||
|
||||
/* Configuration parameters */
|
||||
StreamString serverAddress; /**< Server IP address. */
|
||||
uint16 port; /**< Server port. */
|
||||
uint32 maxPayloadSize; /**< Max payload bytes per datagram. */
|
||||
uint32 keepAliveInterval; /**< Seconds between unicast keepalive ACKs (0 disables). */
|
||||
float32 silenceTimeout; /**< Seconds of no data before reconnect (sub-second allowed, 0 disables). */
|
||||
uint32 cpuMask; /**< Background thread CPU affinity. */
|
||||
uint32 stackSize; /**< Background thread stack size. */
|
||||
StreamString multicastGroup; /**< Multicast group IP; empty = unicast. */
|
||||
StreamString multicastInterface; /**< Local IPv4 address for multicast join; empty = INADDR_ANY. */
|
||||
uint16 dataPort; /**< UDP port for DATA datagrams (multicast). */
|
||||
@@ -191,7 +208,7 @@ private:
|
||||
uint8 publishMode; /**< UDPS_PUBLISH_* from CONFIG. */
|
||||
|
||||
/* Shared receiver (same code base as the StreamHub hub) */
|
||||
UDPSClient client; /**< Transport, reassembly and reconnect. */
|
||||
UDPSClientI *client; /**< Owned transport (UDPSClient by default); see SetClient(). */
|
||||
bool receiverUp; /**< True once the receiver thread is started. */
|
||||
|
||||
/* Double-buffering for RT safety */
|
||||
|
||||
@@ -136,4 +136,5 @@
|
||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
|
||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderT.h \
|
||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
|
||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThread.h
|
||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThread.h \
|
||||
../../../..//Source/Components/Interfaces/UDPStream/UDPSTransportI.h
|
||||
@@ -136,4 +136,5 @@ UDPStreamerClient.o: UDPStreamerClient.cpp \
|
||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
|
||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderT.h \
|
||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
|
||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThread.h
|
||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThread.h \
|
||||
../../../..//Source/Components/Interfaces/UDPStream/UDPSTransportI.h
|
||||
Reference in new issue
Block a user