summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/example.mux40
-rw-r--r--src/DabMultiplexer.cpp61
-rw-r--r--src/DabMultiplexer.h1
-rw-r--r--src/DabMux.cpp31
-rw-r--r--src/dabOutput/dabOutput.h30
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<UdpSocket>();
+ 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<std::shared_ptr<DabOutput> >& 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<std::shared_ptr<DabOutput> >& 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<std::shared_ptr<DabOutput> >& 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<uint8_t> debug_iterator(edi_debug_file);
@@ -1882,12 +1888,13 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& 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<uint8_t> 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<string>("destination");
+ dest.ttl = pt_edi_dest.second.get<unsigned int>("ttl", 1);
- edi_conf.enabled = true;
+ dest.source_addr = pt_edi_dest.second.get<string>("source", "");
+ dest.source_port = pt_edi_dest.second.get<unsigned int>("sourceport");
+
+ edi_conf.destinations.push_back(dest);
+ }
- edi_conf.dest_addr = pt_edi.get<string>("destination");
edi_conf.dest_port = pt_edi.get<unsigned int>("port");
- edi_conf.source_addr = pt_edi.get<string>("source", "");
- edi_conf.source_port = pt_edi.get<unsigned int>("sourceport");
- edi_conf.ttl = pt_edi.get<unsigned int>("ttl", 1);
edi_conf.dump = pt_edi.get<bool>("dump");
edi_conf.enable_pft = pt_edi.get<bool>("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 <stdexcept>
#include <signal.h>
+#include <vector>
+#include <memory>
#ifdef _WIN32
# include <io.h>
# 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<UdpSocket> 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<edi_destination_t> destinations;
+ unsigned int dest_port; // common destination port, because it's encoded in the transport layer
+
+ bool enabled() { return destinations.size() > 0; }
};