diff --git a/Configuration.cpp b/Configuration.cpp index a13dc2723..7bd94b5d4 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -443,7 +443,8 @@ private: void load_audio_devices (QAudio::Mode, QComboBox *, QAudioDeviceInfo *); void update_audio_channels (QComboBox const *, int, QComboBox *, bool); - void load_network_interfaces (CheckableItemComboBox *, QStringList const& current); + void load_network_interfaces (CheckableItemComboBox *, QStringList current); + void validate_network_interfaces (CheckableItemComboBox *); QStringList get_selected_network_interfaces (CheckableItemComboBox *); Q_SLOT void host_info_results (QHostInfo); void check_multicast (QHostAddress const&); @@ -656,6 +657,7 @@ private: int dns_lookup_id_; port_type udp_server_port_; QStringList udp_interface_names_; + QString loopback_interface_name_; int udp_TTL_; QString n1mm_server_name_; port_type n1mm_server_port_; @@ -1085,6 +1087,9 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network load_network_interfaces (ui_->udp_interfaces_combo_box, udp_interface_names_); QGuiApplication::restoreOverrideCursor (); }); + connect (ui_->udp_interfaces_combo_box, &QComboBox::currentTextChanged, [this] (QString const& /*text*/) { + validate_network_interfaces (ui_->udp_interfaces_combo_box); + }); // set up LoTW users CSV file fetching connect (&lotw_users_, &LotWUsers::load_finished, [this] () { @@ -2995,7 +3000,7 @@ void Configuration::impl::load_audio_devices (QAudio::Mode mode, QComboBox * com } // load the available network interfaces into the selection combo box -void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo_box, QStringList const& current) +void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo_box, QStringList current) { combo_box->clear (); for (auto const& net_if : QNetworkInterface::allInterfaces ()) @@ -3003,11 +3008,13 @@ void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo auto flags = QNetworkInterface::IsUp | QNetworkInterface::CanMulticast; if ((net_if.flags () & flags) == flags) { - auto is_loopback = net_if.flags () & QNetworkInterface::IsLoopBack; + if (net_if.flags () & QNetworkInterface::IsLoopBack) + { + loopback_interface_name_ = net_if.name (); + } auto item = combo_box->addCheckItem (net_if.humanReadableName () , net_if.name () - , is_loopback || current.contains (net_if.name ()) ? Qt::Checked : Qt::Unchecked); - item->setEnabled (!is_loopback); + , current.contains (net_if.name ()) ? Qt::Checked : Qt::Unchecked); auto tip = QString {"name(index): %1(%2) - %3"}.arg (net_if.name ()).arg (net_if.index ()) .arg (net_if.flags () & QNetworkInterface::IsUp ? "Up" : "Down"); auto hw_addr = net_if.hardwareAddress (); @@ -3029,6 +3036,33 @@ void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo } } +// get the select network interfaces from the selection combo box +void Configuration::impl::validate_network_interfaces (CheckableItemComboBox * combo_box) +{ + auto model = static_cast (combo_box->model ()); + bool has_checked {false}; + int loopback_row {-1}; + for (int row = 0; row < model->rowCount (); ++row) + { + if (model->item (row)->data ().toString () == loopback_interface_name_) + { + loopback_row = row; + } + else if (Qt::Checked == model->item (row)->checkState ()) + { + has_checked = true; + } + } + if (loopback_row >= 0) + { + if (!has_checked) + { + model->item (loopback_row)->setCheckState (Qt::Checked); + } + model->item (loopback_row)->setEnabled (has_checked); + } +} + // get the select network interfaces from the selection combo box QStringList Configuration::impl::get_selected_network_interfaces (CheckableItemComboBox * combo_box) { diff --git a/Configuration.ui b/Configuration.ui index 1b6ef8926..17fd1a326 100644 --- a/Configuration.ui +++ b/Configuration.ui @@ -1885,7 +1885,7 @@ and DX Grid fields when a 73 or free text message is sent. - <html><head/><body><p>Enter the service port number of the UDP server that WSJT-X should send updates to. If this is zero no updates will be broadcast.</p></body></html> + <html><head/><body><p>Enter the service port number of the UDP server that WSJT-X should send updates to. If this is zero no updates will be sent.</p></body></html> 65534 @@ -1903,10 +1903,17 @@ and DX Grid fields when a 73 or free text message is sent. - + + + <html><head/><body><p>When sending updates to a multicast group address it is necessary to specify which network interface(s) to send them to. If the loop-back interface is multicast capable then at least that one will be selected.</p><p>For most users the loop-back interface is all that is needed, that will allow multiple other applications on the same machine to interoperate with WSJT-X. If applications running on other hosts are to receive status updates then a suitable network interface should be used.</p><p>On some Linux systems it may be necessary to enable multicast on the loop-back network interface.</p></body></html> + + + + <html><head/><body><p>Sets the number or router hops that multicast datagrams are allowed to make. Almost everyone should set this to 1 to keep outgoing multicast traffic withn the local subnet.</p></body></html> + 255 diff --git a/Network/MessageClient.cpp b/Network/MessageClient.cpp index 5ac6a41c1..3cf00ee3b 100644 --- a/Network/MessageClient.cpp +++ b/Network/MessageClient.cpp @@ -103,6 +103,7 @@ public: void MessageClient::impl::set_server (QString const& server_name, QStringList const& network_interface_names) { + // qDebug () << "MessageClient server:" << server_name << "port:" << server_port_ << "interfaces:" << network_interface_names; server_.setAddress (server_name); network_interfaces_.clear (); for (auto const& net_if_name : network_interface_names) @@ -447,9 +448,19 @@ void MessageClient::impl::send_message (QByteArray const& message, bool queue_if { if (message != last_message_) // avoid duplicates { - for (auto const& net_if : network_interfaces_) + if (is_multicast_address (server_)) { - setMulticastInterface (net_if); + // send datagram on each selected network interface + std::for_each (network_interfaces_.begin (), network_interfaces_.end () + , [&] (QNetworkInterface const& net_if) { + setMulticastInterface (net_if); + // qDebug () << "Multicast UDP datagram sent to:" << server_ << "port:" << server_port_ << "on:" << multicastInterface ().humanReadableName (); + writeDatagram (message, server_, server_port_); + }); + } + else + { + // qDebug () << "Unicast UDP datagram sent to:" << server_ << "port:" << server_port_; writeDatagram (message, server_, server_port_); } last_message_ = message;