From 90cb5392cd7f6f623529d62988bc4afdde011820 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 5 Feb 2016 12:12:02 +0100 Subject: Change EDI configuration for multi-output --- doc/example.mux | 40 ++++++++++++++++++++----------- src/DabMultiplexer.cpp | 61 ++++++++++++++++++++++++++--------------------- src/DabMultiplexer.h | 1 - src/DabMux.cpp | 31 ++++++++++++++---------- src/dabOutput/dabOutput.h | 30 +++++++++++++++-------- 5 files changed, 99 insertions(+), 64 deletions(-) diff --git a/doc/example.mux b/doc/example.mux index 456e046..82c5685 100644 --- a/doc/example.mux +++ b/doc/example.mux @@ -321,22 +321,34 @@ outputs { ; The edi output has a different syntax edi { - ; example for unicast EDI - ;destination "192.168.23.23" - ; for unicast EDI, do not set source - - ; example for multicast EDI, the source IP is required - ; so that the data is sent on the correct ethernet interface - destination "232.20.10.1" - source "192.168.0.50" - ; The multicast TTL has to be adapted according to your network - ttl 1 - - ; The settings below apply to both unicast and multicast - ; EDI uses the UDP protocol + destinations { + ; The names you give to the destinations have no meaning, + ; but have to be unique. You can give them meaningful names to help + ; you identify the outputs. + example_unicast { + ; example for unicast EDI + ; for unicast EDI, do not set source + destination "192.168.23.23" + sourceport 13000 + } + example_multicast { + ; example for multicast EDI, the source IP is required + ; so that the data is sent on the correct ethernet interface + destination "232.20.10.1" + source "192.168.0.50" + ; The multicast TTL has to be adapted according to your network + ttl 1 + + sourceport 13000 + } + } + + ; The settings below apply to all destinations + ; The destination port cannot be set independently for + ; different outputs because it is encoded in the transport + ; header of the PFT layer. port 12000 - sourceport 13000 ; Enable the PFT subsystem. If false, AFPackets are sent. enable_pft true diff --git a/src/DabMultiplexer.cpp b/src/DabMultiplexer.cpp index d9ca495..47c0958 100644 --- a/src/DabMultiplexer.cpp +++ b/src/DabMultiplexer.cpp @@ -150,25 +150,30 @@ void DabMultiplexer::set_edi_config(const edi_configuration_t& new_edi_conf) edi_debug_file.open("./edi.debug"); } - if (edi_conf.enabled) { - int err = edi_output.create(edi_conf.source_port); + if (edi_conf.enabled()) { + for (auto& edi_destination : edi_conf.destinations) { + auto edi_output = std::make_shared(); + int err = edi_output->create(edi_destination.source_port); - if (err) { - etiLog.level(error) << "EDI socket creation failed!"; - throw MuxInitException(); - } - - if (not edi_conf.source_addr.empty()) { - err = edi_output.setMulticastSource(edi_conf.source_addr.c_str()); if (err) { - etiLog.level(error) << "EDI socket set source failed!"; + etiLog.level(error) << "EDI socket creation failed!"; throw MuxInitException(); } - err = edi_output.setMulticastTTL(edi_conf.ttl); - if (err) { - etiLog.level(error) << "EDI socket set TTL failed!"; - throw MuxInitException(); + + if (not edi_destination.source_addr.empty()) { + err = edi_output->setMulticastSource(edi_destination.source_addr.c_str()); + if (err) { + etiLog.level(error) << "EDI socket set source failed!"; + throw MuxInitException(); + } + err = edi_output->setMulticastTTL(edi_destination.ttl); + if (err) { + etiLog.level(error) << "EDI socket set TTL failed!"; + throw MuxInitException(); + } } + + edi_destination.socket = edi_output; } } @@ -248,7 +253,7 @@ void DabMultiplexer::prepare() bool tist_enabled = m_pt.get("general.tist", false); - if (tist_enabled and edi_conf.enabled) { + if (tist_enabled and edi_conf.enabled()) { try { m_clock_tai.get_offset(); } @@ -1782,7 +1787,7 @@ void DabMultiplexer::mux_frame(std::vector >& outputs try { bool tist_enabled = m_pt.get("general.tist", false); - if (tist_enabled and edi_conf.enabled) { + if (tist_enabled and edi_conf.enabled()) { edi_tagDETI.set_utco(m_clock_tai.get_offset()); edi_tagDETI.set_seconds(edi_time); } @@ -1843,7 +1848,7 @@ void DabMultiplexer::mux_frame(std::vector >& outputs *********** Finalise and send EDI ******************************** **********************************************************************/ - if (edi_conf.enabled) { + if (edi_conf.enabled()) { // put tags *ptr, DETI and all subchannels into one TagPacket edi_tagpacket.tag_items.push_back(&edi_tagStarPtr); edi_tagpacket.tag_items.push_back(&edi_tagDETI); @@ -1862,12 +1867,13 @@ void DabMultiplexer::mux_frame(std::vector >& outputs // Send over ethernet for (const auto& edi_frag : edi_fragments) { + for (auto& dest : edi_conf.destinations) { + InetAddress addr; + addr.setAddress(dest.dest_addr.c_str()); + addr.setPort(edi_conf.dest_port); - InetAddress addr; - addr.setAddress(edi_conf.dest_addr.c_str()); - addr.setPort(edi_conf.dest_port); - - edi_output.send(edi_frag, addr); + dest.socket->send(edi_frag, addr); + } if (edi_conf.dump) { std::ostream_iterator debug_iterator(edi_debug_file); @@ -1882,12 +1888,13 @@ void DabMultiplexer::mux_frame(std::vector >& outputs } else { // Send over ethernet + for (auto& dest : edi_conf.destinations) { + InetAddress addr; + addr.setAddress(dest.dest_addr.c_str()); + addr.setPort(edi_conf.dest_port); - InetAddress addr; - addr.setAddress(edi_conf.dest_addr.c_str()); - addr.setPort(edi_conf.dest_port); - - edi_output.send(edi_afpacket, addr); + dest.socket->send(edi_afpacket, addr); + } if (edi_conf.dump) { std::ostream_iterator debug_iterator(edi_debug_file); diff --git a/src/DabMultiplexer.h b/src/DabMultiplexer.h index e8b2a00..529b9ca 100644 --- a/src/DabMultiplexer.h +++ b/src/DabMultiplexer.h @@ -141,7 +141,6 @@ class DabMultiplexer : public RemoteControllable { ClockTAI m_clock_tai; std::ofstream edi_debug_file; - UdpSocket edi_output; // The TagPacket will then be placed into an AFPacket AFPacketiser edi_afPacketiser; diff --git a/src/DabMux.cpp b/src/DabMux.cpp index 18fee19..19f11fe 100644 --- a/src/DabMux.cpp +++ b/src/DabMux.cpp @@ -318,14 +318,18 @@ int main(int argc, char *argv[]) if (outputuid == "edi") { #if HAVE_OUTPUT_EDI ptree pt_edi = pt_outputs.get_child("edi"); + for (auto pt_edi_dest : pt_edi.get_child("destinations")) { + edi_destination_t dest; + dest.dest_addr = pt_edi_dest.second.get("destination"); + dest.ttl = pt_edi_dest.second.get("ttl", 1); - edi_conf.enabled = true; + dest.source_addr = pt_edi_dest.second.get("source", ""); + dest.source_port = pt_edi_dest.second.get("sourceport"); + + edi_conf.destinations.push_back(dest); + } - edi_conf.dest_addr = pt_edi.get("destination"); edi_conf.dest_port = pt_edi.get("port"); - edi_conf.source_addr = pt_edi.get("source", ""); - edi_conf.source_port = pt_edi.get("sourceport"); - edi_conf.ttl = pt_edi.get("ttl", 1); edi_conf.dump = pt_edi.get("dump"); edi_conf.enable_pft = pt_edi.get("enable_pft"); @@ -429,14 +433,17 @@ int main(int argc, char *argv[]) printOutputs(outputs); #if HAVE_OUTPUT_EDI - if (edi_conf.enabled) { - etiLog.level(info) << "EDI to " << edi_conf.dest_addr << ":" << edi_conf.dest_port; - if (not edi_conf.source_addr.empty()) { - etiLog.level(info) << " source " << edi_conf.source_addr; - etiLog.level(info) << " ttl " << edi_conf.ttl; - } - etiLog.level(info) << " source port " << edi_conf.source_port; + if (edi_conf.enabled()) { + etiLog.level(info) << "EDI"; etiLog.level(info) << " verbose " << edi_conf.verbose; + for (auto& edi_dest : edi_conf.destinations) { + etiLog.level(info) << " to " << edi_dest.dest_addr << ":" << edi_conf.dest_port; + if (not edi_dest.source_addr.empty()) { + etiLog.level(info) << " source " << edi_dest.source_addr; + etiLog.level(info) << " ttl " << edi_dest.ttl; + } + etiLog.level(info) << " source port " << edi_dest.source_port; + } } #endif diff --git a/src/dabOutput/dabOutput.h b/src/dabOutput/dabOutput.h index b2100ab..2c4d1ef 100644 --- a/src/dabOutput/dabOutput.h +++ b/src/dabOutput/dabOutput.h @@ -35,6 +35,8 @@ #include "string.h" #include #include +#include +#include #ifdef _WIN32 # include # ifdef __MINGW32__ @@ -53,23 +55,31 @@ # include "zmq.hpp" #endif -// Configuration for EDI output +/** Configuration for EDI output */ + +// Can represent both unicast and multicast destinations +struct edi_destination_t { + std::string dest_addr; + std::string source_addr; + unsigned int source_port; + unsigned int ttl; + + std::shared_ptr socket; +}; + struct edi_configuration_t { edi_configuration_t() : - enabled(false), verbose(false) {} unsigned chunk_len; // RSk, data length of each chunk unsigned fec; // number of fragments that can be recovered - bool enabled; - bool dump; + bool dump; // dump a file with the EDI packets bool verbose; - bool enable_pft; - std::string dest_addr; - std::string source_addr; - unsigned int source_port; - unsigned int dest_port; - unsigned int ttl; + bool enable_pft; // Enable protection and fragmentation unsigned int tagpacket_alignment; + std::vector destinations; + unsigned int dest_port; // common destination port, because it's encoded in the transport layer + + bool enabled() { return destinations.size() > 0; } }; -- cgit v1.2.3