Topology: Master1 ↔ Master2 via Twin (shared LOCAL_PREFIX), Master2 has a Satellite attached. Client connected via Satellite.
Observed:
Sat-client RX works fine: he hears traffic from both Master1 and Master2
Sat-client TX is asymmetric: Master2 hears him and forwards to its trunk peers, but Master1 receives nothing (no audio, no MsgTwinExtTalkerStart log entry on Master1)
Root cause in SatelliteLink::handleMsgPeerTalkerStart (and the related stop/audio handlers):
cppm_reflector->forwardSatelliteAudioToTrunks(tg, msg.callsign()); // OK
// missing: m_reflector->notifyExternalTrunkTalkerStart(tg, m_satellite_id, msg.callsign());
Compare with TrunkLink::handleMsgPeerTalkerStart which correctly calls both notifyExternalTrunkTalkerStart (twin) AND forwardTrunkTalkerStartToOtherTrunks (trunks).
The asymmetry causes Twin partner not to be informed of satellite-originated talker activity. Reverse direction (Twin→Satellite) works because the Twin handler properly informs all local clients incl. those connected through Satellite.
Workaround!?
// In Reflector.h (private section, near forwardSatellite*ToTrunks):
void forwardSatelliteAudioToTwin(uint32_t tg, const std::string& callsign);
void forwardSatelliteStopToTwin(uint32_t tg);
void forwardSatelliteRawAudioToTwin(uint32_t tg, const std::vector<uint8_t>& audio);
void forwardSatelliteFlushToTwin(uint32_t tg);
// In Reflector.cpp:
void Reflector::forwardSatelliteAudioToTwin(uint32_t tg, const std::string& callsign)
{
if (m_twin_link) m_twin_link->onLocalTalkerStart(tg, callsign);
}
void Reflector::forwardSatelliteStopToTwin(uint32_t tg)
{
if (m_twin_link) m_twin_link->onLocalTalkerStop(tg);
}
void Reflector::forwardSatelliteRawAudioToTwin(uint32_t tg,
const std::vector<uint8_t>& audio)
{
if (m_twin_link) m_twin_link->onLocalAudio(tg, audio);
}
void Reflector::forwardSatelliteFlushToTwin(uint32_t tg)
{
if (m_twin_link) m_twin_link->onLocalFlush(tg);
}
SatelliteLink.cpp
// handleMsgPeerTalkerStart:
m_reflector->forwardSatelliteAudioToTrunks(tg, msg.callsign());
m_reflector->forwardSatelliteAudioToTwin(tg, msg.callsign()); // FIX
// handleMsgPeerTalkerStop:
m_reflector->forwardSatelliteStopToTrunks(tg);
m_reflector->forwardSatelliteStopToTwin(tg); // FIX
// handleMsgPeerAudio:
m_reflector->forwardSatelliteRawAudioToTrunks(tg, msg.audio());
m_reflector->forwardSatelliteRawAudioToTwin(tg, msg.audio()); // FIX
// handleMsgPeerFlush:
m_reflector->forwardSatelliteFlushToTrunks(tg);
m_reflector->forwardSatelliteFlushToTwin(tg); // FIX
Topology: Master1 ↔ Master2 via Twin (shared LOCAL_PREFIX), Master2 has a Satellite attached. Client connected via Satellite.
Observed:
Sat-client RX works fine: he hears traffic from both Master1 and Master2
Sat-client TX is asymmetric: Master2 hears him and forwards to its trunk peers, but Master1 receives nothing (no audio, no MsgTwinExtTalkerStart log entry on Master1)
Root cause in SatelliteLink::handleMsgPeerTalkerStart (and the related stop/audio handlers):
cppm_reflector->forwardSatelliteAudioToTrunks(tg, msg.callsign()); // OK
// missing: m_reflector->notifyExternalTrunkTalkerStart(tg, m_satellite_id, msg.callsign());
Compare with TrunkLink::handleMsgPeerTalkerStart which correctly calls both notifyExternalTrunkTalkerStart (twin) AND forwardTrunkTalkerStartToOtherTrunks (trunks).
The asymmetry causes Twin partner not to be informed of satellite-originated talker activity. Reverse direction (Twin→Satellite) works because the Twin handler properly informs all local clients incl. those connected through Satellite.
Workaround!?
// In Reflector.h (private section, near forwardSatellite*ToTrunks):
void forwardSatelliteAudioToTwin(uint32_t tg, const std::string& callsign);
void forwardSatelliteStopToTwin(uint32_t tg);
void forwardSatelliteRawAudioToTwin(uint32_t tg, const std::vector<uint8_t>& audio);
void forwardSatelliteFlushToTwin(uint32_t tg);
// In Reflector.cpp:
void Reflector::forwardSatelliteAudioToTwin(uint32_t tg, const std::string& callsign)
{
if (m_twin_link) m_twin_link->onLocalTalkerStart(tg, callsign);
}
void Reflector::forwardSatelliteStopToTwin(uint32_t tg)
{
if (m_twin_link) m_twin_link->onLocalTalkerStop(tg);
}
void Reflector::forwardSatelliteRawAudioToTwin(uint32_t tg,
const std::vector<uint8_t>& audio)
{
if (m_twin_link) m_twin_link->onLocalAudio(tg, audio);
}
void Reflector::forwardSatelliteFlushToTwin(uint32_t tg)
{
if (m_twin_link) m_twin_link->onLocalFlush(tg);
}
SatelliteLink.cpp
// handleMsgPeerTalkerStart:
m_reflector->forwardSatelliteAudioToTrunks(tg, msg.callsign());
m_reflector->forwardSatelliteAudioToTwin(tg, msg.callsign()); // FIX
// handleMsgPeerTalkerStop:
m_reflector->forwardSatelliteStopToTrunks(tg);
m_reflector->forwardSatelliteStopToTwin(tg); // FIX
// handleMsgPeerAudio:
m_reflector->forwardSatelliteRawAudioToTrunks(tg, msg.audio());
m_reflector->forwardSatelliteRawAudioToTwin(tg, msg.audio()); // FIX
// handleMsgPeerFlush:
m_reflector->forwardSatelliteFlushToTrunks(tg);
m_reflector->forwardSatelliteFlushToTwin(tg); // FIX