mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-27 22:58:40 -05:00
Message Client allows sending multicast UDP on multiple interfaces
This commit is contained in:
parent
e61a1f969c
commit
780b1f74ee
@ -166,6 +166,7 @@
|
|||||||
#include <QNetworkInterface>
|
#include <QNetworkInterface>
|
||||||
#include <QHostInfo>
|
#include <QHostInfo>
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
|
#include <QStandardItem>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "pimpl_impl.hpp"
|
#include "pimpl_impl.hpp"
|
||||||
@ -442,7 +443,8 @@ private:
|
|||||||
void load_audio_devices (QAudio::Mode, QComboBox *, QAudioDeviceInfo *);
|
void load_audio_devices (QAudio::Mode, QComboBox *, QAudioDeviceInfo *);
|
||||||
void update_audio_channels (QComboBox const *, int, QComboBox *, bool);
|
void update_audio_channels (QComboBox const *, int, QComboBox *, bool);
|
||||||
|
|
||||||
void load_network_interfaces (QComboBox *, QString const& current);
|
void load_network_interfaces (CheckableItemComboBox *, QStringList const& current);
|
||||||
|
QStringList get_selected_network_interfaces (CheckableItemComboBox *);
|
||||||
Q_SLOT void host_info_results (QHostInfo);
|
Q_SLOT void host_info_results (QHostInfo);
|
||||||
void check_multicast (QHostAddress const&);
|
void check_multicast (QHostAddress const&);
|
||||||
|
|
||||||
@ -653,7 +655,7 @@ private:
|
|||||||
bool udp_server_name_edited_;
|
bool udp_server_name_edited_;
|
||||||
int dns_lookup_id_;
|
int dns_lookup_id_;
|
||||||
port_type udp_server_port_;
|
port_type udp_server_port_;
|
||||||
QString udp_interface_name_;
|
QStringList udp_interface_names_;
|
||||||
int udp_TTL_;
|
int udp_TTL_;
|
||||||
QString n1mm_server_name_;
|
QString n1mm_server_name_;
|
||||||
port_type n1mm_server_port_;
|
port_type n1mm_server_port_;
|
||||||
@ -754,7 +756,7 @@ QString Configuration::opCall() const {return m_->opCall_;}
|
|||||||
void Configuration::opCall (QString const& call) {m_->opCall_ = call;}
|
void Configuration::opCall (QString const& call) {m_->opCall_ = call;}
|
||||||
QString Configuration::udp_server_name () const {return m_->udp_server_name_;}
|
QString Configuration::udp_server_name () const {return m_->udp_server_name_;}
|
||||||
auto Configuration::udp_server_port () const -> port_type {return m_->udp_server_port_;}
|
auto Configuration::udp_server_port () const -> port_type {return m_->udp_server_port_;}
|
||||||
QString Configuration::udp_interface_name () const {return m_->udp_interface_name_;}
|
QStringList Configuration::udp_interface_names () const {return m_->udp_interface_names_;}
|
||||||
int Configuration::udp_TTL () const {return m_->udp_TTL_;}
|
int Configuration::udp_TTL () const {return m_->udp_TTL_;}
|
||||||
bool Configuration::accept_udp_requests () const {return m_->accept_udp_requests_;}
|
bool Configuration::accept_udp_requests () const {return m_->accept_udp_requests_;}
|
||||||
QString Configuration::n1mm_server_name () const {return m_->n1mm_server_name_;}
|
QString Configuration::n1mm_server_name () const {return m_->n1mm_server_name_;}
|
||||||
@ -1078,9 +1080,9 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network
|
|||||||
});
|
});
|
||||||
|
|
||||||
// set up dynamic loading of network interfaces
|
// set up dynamic loading of network interfaces
|
||||||
connect (ui_->udp_interface_combo_box, &LazyFillComboBox::about_to_show_popup, [this] () {
|
connect (ui_->udp_interfaces_combo_box, &LazyFillComboBox::about_to_show_popup, [this] () {
|
||||||
QGuiApplication::setOverrideCursor (QCursor {Qt::WaitCursor});
|
QGuiApplication::setOverrideCursor (QCursor {Qt::WaitCursor});
|
||||||
load_network_interfaces (ui_->udp_interface_combo_box, udp_interface_name_);
|
load_network_interfaces (ui_->udp_interfaces_combo_box, udp_interface_names_);
|
||||||
QGuiApplication::restoreOverrideCursor ();
|
QGuiApplication::restoreOverrideCursor ();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1362,10 +1364,10 @@ void Configuration::impl::initialize_models ()
|
|||||||
ui_->udp_server_line_edit->setText (udp_server_name_);
|
ui_->udp_server_line_edit->setText (udp_server_name_);
|
||||||
on_udp_server_line_edit_editingFinished ();
|
on_udp_server_line_edit_editingFinished ();
|
||||||
ui_->udp_server_port_spin_box->setValue (udp_server_port_);
|
ui_->udp_server_port_spin_box->setValue (udp_server_port_);
|
||||||
load_network_interfaces (ui_->udp_interface_combo_box, udp_interface_name_);
|
load_network_interfaces (ui_->udp_interfaces_combo_box, udp_interface_names_);
|
||||||
if (!udp_interface_name_.size ())
|
if (!udp_interface_names_.size ())
|
||||||
{
|
{
|
||||||
udp_interface_name_ = ui_->udp_interface_combo_box->currentData ().toString ();
|
udp_interface_names_ = get_selected_network_interfaces (ui_->udp_interfaces_combo_box);
|
||||||
}
|
}
|
||||||
ui_->udp_TTL_spin_box->setValue (udp_TTL_);
|
ui_->udp_TTL_spin_box->setValue (udp_TTL_);
|
||||||
ui_->accept_udp_requests_check_box->setChecked (accept_udp_requests_);
|
ui_->accept_udp_requests_check_box->setChecked (accept_udp_requests_);
|
||||||
@ -1545,7 +1547,7 @@ void Configuration::impl::read_settings ()
|
|||||||
rig_params_.split_mode = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value<TransceiverFactory::SplitMode> ();
|
rig_params_.split_mode = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value<TransceiverFactory::SplitMode> ();
|
||||||
opCall_ = settings_->value ("OpCall", "").toString ();
|
opCall_ = settings_->value ("OpCall", "").toString ();
|
||||||
udp_server_name_ = settings_->value ("UDPServer", "127.0.0.1").toString ();
|
udp_server_name_ = settings_->value ("UDPServer", "127.0.0.1").toString ();
|
||||||
udp_interface_name_ = settings_->value ("UDPInterface").toString ();
|
udp_interface_names_ = settings_->value ("UDPInterface").toStringList ();
|
||||||
udp_TTL_ = settings_->value ("UDPTTL", 1).toInt ();
|
udp_TTL_ = settings_->value ("UDPTTL", 1).toInt ();
|
||||||
udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt ();
|
udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt ();
|
||||||
n1mm_server_name_ = settings_->value ("N1MMServer", "127.0.0.1").toString ();
|
n1mm_server_name_ = settings_->value ("N1MMServer", "127.0.0.1").toString ();
|
||||||
@ -1675,7 +1677,7 @@ void Configuration::impl::write_settings ()
|
|||||||
settings_->setValue ("OpCall", opCall_);
|
settings_->setValue ("OpCall", opCall_);
|
||||||
settings_->setValue ("UDPServer", udp_server_name_);
|
settings_->setValue ("UDPServer", udp_server_name_);
|
||||||
settings_->setValue ("UDPServerPort", udp_server_port_);
|
settings_->setValue ("UDPServerPort", udp_server_port_);
|
||||||
settings_->setValue ("UDPInterface", udp_interface_name_);
|
settings_->setValue ("UDPInterface", QVariant::fromValue (udp_interface_names_));
|
||||||
settings_->setValue ("UDPTTL", udp_TTL_);
|
settings_->setValue ("UDPTTL", udp_TTL_);
|
||||||
settings_->setValue ("N1MMServer", n1mm_server_name_);
|
settings_->setValue ("N1MMServer", n1mm_server_name_);
|
||||||
settings_->setValue ("N1MMServerPort", n1mm_server_port_);
|
settings_->setValue ("N1MMServerPort", n1mm_server_port_);
|
||||||
@ -2105,12 +2107,12 @@ void Configuration::impl::accept ()
|
|||||||
opCall_=ui_->opCallEntry->text();
|
opCall_=ui_->opCallEntry->text();
|
||||||
|
|
||||||
auto new_server = ui_->udp_server_line_edit->text ().trimmed ();
|
auto new_server = ui_->udp_server_line_edit->text ().trimmed ();
|
||||||
auto new_interface = ui_->udp_interface_combo_box->currentData ().toString ();
|
auto new_interfaces = get_selected_network_interfaces (ui_->udp_interfaces_combo_box);
|
||||||
if (new_server != udp_server_name_ || new_interface != udp_interface_name_)
|
if (new_server != udp_server_name_ || new_interfaces != udp_interface_names_)
|
||||||
{
|
{
|
||||||
udp_server_name_ = new_server;
|
udp_server_name_ = new_server;
|
||||||
udp_interface_name_ = new_interface;
|
udp_interface_names_ = new_interfaces;
|
||||||
Q_EMIT self_->udp_server_changed (udp_server_name_, udp_interface_name_);
|
Q_EMIT self_->udp_server_changed (udp_server_name_, udp_interface_names_);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto new_port = ui_->udp_server_port_spin_box->value ();
|
auto new_port = ui_->udp_server_port_spin_box->value ();
|
||||||
@ -2452,8 +2454,8 @@ void Configuration::impl::host_info_results (QHostInfo host_info)
|
|||||||
void Configuration::impl::check_multicast (QHostAddress const& ha)
|
void Configuration::impl::check_multicast (QHostAddress const& ha)
|
||||||
{
|
{
|
||||||
auto is_multicast = is_multicast_address (ha);
|
auto is_multicast = is_multicast_address (ha);
|
||||||
ui_->udp_interface_label->setVisible (is_multicast);
|
ui_->udp_interfaces_label->setVisible (is_multicast);
|
||||||
ui_->udp_interface_combo_box->setVisible (is_multicast);
|
ui_->udp_interfaces_combo_box->setVisible (is_multicast);
|
||||||
ui_->udp_TTL_label->setVisible (is_multicast);
|
ui_->udp_TTL_label->setVisible (is_multicast);
|
||||||
ui_->udp_TTL_spin_box->setVisible (is_multicast);
|
ui_->udp_TTL_spin_box->setVisible (is_multicast);
|
||||||
if (isVisible ())
|
if (isVisible ())
|
||||||
@ -2993,28 +2995,53 @@ void Configuration::impl::load_audio_devices (QAudio::Mode mode, QComboBox * com
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load the available network interfaces into the selection combo box
|
// load the available network interfaces into the selection combo box
|
||||||
void Configuration::impl::load_network_interfaces (QComboBox * combo_box, QString const& current)
|
void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo_box, QStringList const& current)
|
||||||
{
|
{
|
||||||
combo_box->clear ();
|
combo_box->clear ();
|
||||||
int current_index = -1;
|
for (auto const& net_if : QNetworkInterface::allInterfaces ())
|
||||||
for (auto const& interface : QNetworkInterface::allInterfaces ())
|
|
||||||
{
|
{
|
||||||
if (interface.flags () & QNetworkInterface::IsUp)
|
auto flags = QNetworkInterface::IsUp | QNetworkInterface::CanMulticast;
|
||||||
|
if ((net_if.flags () & flags) == flags)
|
||||||
{
|
{
|
||||||
auto const& name = interface.name ();
|
auto is_loopback = net_if.flags () & QNetworkInterface::IsLoopBack;
|
||||||
combo_box->addItem (interface.humanReadableName (), name);
|
auto item = combo_box->addCheckItem (net_if.humanReadableName ()
|
||||||
// select the first loopback interface as a default to
|
, net_if.name ()
|
||||||
// discourage spamming the network (possibly the Internet),
|
, is_loopback || current.contains (net_if.name ()) ? Qt::Checked : Qt::Unchecked);
|
||||||
// particularly important with administratively scoped
|
item->setEnabled (!is_loopback);
|
||||||
// multicast UDP
|
auto tip = QString {"name(index): %1(%2) - %3"}.arg (net_if.name ()).arg (net_if.index ())
|
||||||
if (name == current
|
.arg (net_if.flags () & QNetworkInterface::IsUp ? "Up" : "Down");
|
||||||
|| (!current.size () && (interface.flags () & QNetworkInterface::IsLoopBack)))
|
auto hw_addr = net_if.hardwareAddress ();
|
||||||
|
if (hw_addr.size ())
|
||||||
{
|
{
|
||||||
current_index = combo_box->count () - 1;
|
tip += QString {"\nhw: %1"}.arg (net_if.hardwareAddress ());
|
||||||
|
}
|
||||||
|
auto aes = net_if.addressEntries ();
|
||||||
|
if (aes.size ())
|
||||||
|
{
|
||||||
|
tip += "\naddresses:";
|
||||||
|
for (auto const& ae : aes)
|
||||||
|
{
|
||||||
|
tip += QString {"\n ip: %1/%2"}.arg (ae.ip ().toString ()).arg (ae.prefixLength ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item->setToolTip (tip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
combo_box->setCurrentIndex (current_index);
|
|
||||||
|
// get the select network interfaces from the selection combo box
|
||||||
|
QStringList Configuration::impl::get_selected_network_interfaces (CheckableItemComboBox * combo_box)
|
||||||
|
{
|
||||||
|
QStringList interfaces;
|
||||||
|
auto model = static_cast<QStandardItemModel *> (combo_box->model ());
|
||||||
|
for (int row = 0; row < model->rowCount (); ++row)
|
||||||
|
{
|
||||||
|
if (Qt::Checked == model->item (row)->checkState ())
|
||||||
|
{
|
||||||
|
interfaces << model->item (row)->data ().toString ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return interfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
// enable only the channels that are supported by the selected audio device
|
// enable only the channels that are supported by the selected audio device
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#include "Radio.hpp"
|
#include "Radio.hpp"
|
||||||
#include "models/IARURegions.hpp"
|
#include "models/IARURegions.hpp"
|
||||||
@ -14,7 +15,6 @@
|
|||||||
class QSettings;
|
class QSettings;
|
||||||
class QWidget;
|
class QWidget;
|
||||||
class QAudioDeviceInfo;
|
class QAudioDeviceInfo;
|
||||||
class QString;
|
|
||||||
class QDir;
|
class QDir;
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
class Bands;
|
class Bands;
|
||||||
@ -151,7 +151,7 @@ public:
|
|||||||
void opCall (QString const&);
|
void opCall (QString const&);
|
||||||
QString udp_server_name () const;
|
QString udp_server_name () const;
|
||||||
port_type udp_server_port () const;
|
port_type udp_server_port () const;
|
||||||
QString udp_interface_name () const;
|
QStringList udp_interface_names () const;
|
||||||
int udp_TTL () const;
|
int udp_TTL () const;
|
||||||
QString n1mm_server_name () const;
|
QString n1mm_server_name () const;
|
||||||
port_type n1mm_server_port () const;
|
port_type n1mm_server_port () const;
|
||||||
@ -274,7 +274,7 @@ public:
|
|||||||
//
|
//
|
||||||
// This signal is emitted when the UDP server changes
|
// This signal is emitted when the UDP server changes
|
||||||
//
|
//
|
||||||
Q_SIGNAL void udp_server_changed (QString& udp_server_name, QString const& network_interface) const;
|
Q_SIGNAL void udp_server_changed (QString& udp_server_name, QStringList const& network_interfaces) const;
|
||||||
Q_SIGNAL void udp_server_port_changed (port_type server_port) const;
|
Q_SIGNAL void udp_server_port_changed (port_type server_port) const;
|
||||||
Q_SIGNAL void udp_TTL_changed (int TTL) const;
|
Q_SIGNAL void udp_TTL_changed (int TTL) const;
|
||||||
Q_SIGNAL void accept_udp_requests_changed (bool checked) const;
|
Q_SIGNAL void accept_udp_requests_changed (bool checked) const;
|
||||||
|
@ -1893,17 +1893,17 @@ and DX Grid fields when a 73 or free text message is sent.</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="udp_interface_label">
|
<widget class="QLabel" name="udp_interfaces_label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Outgoing interface:</string>
|
<string>Outgoing interfaces:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>udp_interface_combo_box</cstring>
|
<cstring>udp_interfaces_combo_box</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="LazyFillComboBox" name="udp_interface_combo_box"/>
|
<widget class="CheckableItemComboBox" name="udp_interfaces_combo_box"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QSpinBox" name="udp_TTL_spin_box">
|
<widget class="QSpinBox" name="udp_TTL_spin_box">
|
||||||
@ -3029,6 +3029,11 @@ Right click for insert and delete options.</string>
|
|||||||
<extends>QComboBox</extends>
|
<extends>QComboBox</extends>
|
||||||
<header>widgets/LazyFillComboBox.hpp</header>
|
<header>widgets/LazyFillComboBox.hpp</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>CheckableItemComboBox</class>
|
||||||
|
<extends>QComboBox</extends>
|
||||||
|
<header>widgets/CheckableItemComboBox.hpp</header>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>configuration_tabs</tabstop>
|
<tabstop>configuration_tabs</tabstop>
|
||||||
@ -3111,7 +3116,7 @@ Right click for insert and delete options.</string>
|
|||||||
<tabstop>psk_reporter_tcpip_check_box</tabstop>
|
<tabstop>psk_reporter_tcpip_check_box</tabstop>
|
||||||
<tabstop>udp_server_line_edit</tabstop>
|
<tabstop>udp_server_line_edit</tabstop>
|
||||||
<tabstop>udp_server_port_spin_box</tabstop>
|
<tabstop>udp_server_port_spin_box</tabstop>
|
||||||
<tabstop>udp_interface_combo_box</tabstop>
|
<tabstop>udp_interfaces_combo_box</tabstop>
|
||||||
<tabstop>udp_TTL_spin_box</tabstop>
|
<tabstop>udp_TTL_spin_box</tabstop>
|
||||||
<tabstop>accept_udp_requests_check_box</tabstop>
|
<tabstop>accept_udp_requests_check_box</tabstop>
|
||||||
<tabstop>udpWindowToFront</tabstop>
|
<tabstop>udpWindowToFront</tabstop>
|
||||||
@ -3221,13 +3226,13 @@ Right click for insert and delete options.</string>
|
|||||||
</connection>
|
</connection>
|
||||||
</connections>
|
</connections>
|
||||||
<buttongroups>
|
<buttongroups>
|
||||||
<buttongroup name="split_mode_button_group"/>
|
<buttongroup name="TX_audio_source_button_group"/>
|
||||||
<buttongroup name="CAT_stop_bits_button_group"/>
|
<buttongroup name="CAT_stop_bits_button_group"/>
|
||||||
<buttongroup name="special_op_activity_button_group"/>
|
|
||||||
<buttongroup name="CAT_handshake_button_group"/>
|
<buttongroup name="CAT_handshake_button_group"/>
|
||||||
<buttongroup name="CAT_data_bits_button_group"/>
|
<buttongroup name="CAT_data_bits_button_group"/>
|
||||||
<buttongroup name="TX_mode_button_group"/>
|
<buttongroup name="TX_mode_button_group"/>
|
||||||
|
<buttongroup name="special_op_activity_button_group"/>
|
||||||
<buttongroup name="PTT_method_button_group"/>
|
<buttongroup name="PTT_method_button_group"/>
|
||||||
<buttongroup name="TX_audio_source_button_group"/>
|
<buttongroup name="split_mode_button_group"/>
|
||||||
</buttongroups>
|
</buttongroups>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -59,7 +59,7 @@ public:
|
|||||||
|
|
||||||
enum StreamStatus {Fail, Short, OK};
|
enum StreamStatus {Fail, Short, OK};
|
||||||
|
|
||||||
void set_server (QString const& server_name, QString const& network_interface_name);
|
void set_server (QString const& server_name, QStringList const& network_interface_names);
|
||||||
Q_SLOT void host_info_results (QHostInfo);
|
Q_SLOT void host_info_results (QHostInfo);
|
||||||
void start ();
|
void start ();
|
||||||
void parse_message (QByteArray const&);
|
void parse_message (QByteArray const&);
|
||||||
@ -67,12 +67,12 @@ public:
|
|||||||
void heartbeat ();
|
void heartbeat ();
|
||||||
void closedown ();
|
void closedown ();
|
||||||
StreamStatus check_status (QDataStream const&) const;
|
StreamStatus check_status (QDataStream const&) const;
|
||||||
void send_message (QByteArray const&);
|
void send_message (QByteArray const&, bool queue_if_pending = true);
|
||||||
void send_message (QDataStream const& out, QByteArray const& message)
|
void send_message (QDataStream const& out, QByteArray const& message, bool queue_if_pending = true)
|
||||||
{
|
{
|
||||||
if (OK == check_status (out))
|
if (OK == check_status (out))
|
||||||
{
|
{
|
||||||
send_message (message);
|
send_message (message, queue_if_pending);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -89,7 +89,7 @@ public:
|
|||||||
QHostAddress server_;
|
QHostAddress server_;
|
||||||
port_type server_port_;
|
port_type server_port_;
|
||||||
int TTL_;
|
int TTL_;
|
||||||
QNetworkInterface network_interface_;
|
std::vector<QNetworkInterface> network_interfaces_;
|
||||||
quint32 schema_;
|
quint32 schema_;
|
||||||
QTimer * heartbeat_timer_;
|
QTimer * heartbeat_timer_;
|
||||||
std::vector<QHostAddress> blocked_addresses_;
|
std::vector<QHostAddress> blocked_addresses_;
|
||||||
@ -101,10 +101,15 @@ public:
|
|||||||
|
|
||||||
#include "MessageClient.moc"
|
#include "MessageClient.moc"
|
||||||
|
|
||||||
void MessageClient::impl::set_server (QString const& server_name, QString const& network_interface_name)
|
void MessageClient::impl::set_server (QString const& server_name, QStringList const& network_interface_names)
|
||||||
{
|
{
|
||||||
server_.setAddress (server_name);
|
server_.setAddress (server_name);
|
||||||
network_interface_ = QNetworkInterface::interfaceFromName (network_interface_name);
|
network_interfaces_.clear ();
|
||||||
|
for (auto const& net_if_name : network_interface_names)
|
||||||
|
{
|
||||||
|
network_interfaces_.push_back (QNetworkInterface::interfaceFromName (net_if_name));
|
||||||
|
}
|
||||||
|
|
||||||
if (server_.isNull () && server_name.size ()) // DNS lookup required
|
if (server_.isNull () && server_name.size ()) // DNS lookup required
|
||||||
{
|
{
|
||||||
// queue a host address lookup
|
// queue a host address lookup
|
||||||
@ -162,33 +167,10 @@ void MessageClient::impl::start ()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE_UDP ("Trying server:" << server_.toString () << "on interface:" << network_interface_.humanReadableName ());
|
TRACE_UDP ("Trying server:" << server_.toString ());
|
||||||
QHostAddress interface_ip {QHostAddress::Any};
|
QHostAddress interface_addr {IPv6Protocol == server_.protocol () ? QHostAddress::AnyIPv6 : QHostAddress::AnyIPv4};
|
||||||
if (network_interface_.isValid ())
|
|
||||||
{
|
|
||||||
if (is_multicast_address (server_) && !(network_interface_.flags () & QNetworkInterface::CanMulticast))
|
|
||||||
{
|
|
||||||
Q_EMIT self_->error ("Network interface is not multicast capable, please try another");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (auto const& ae : network_interface_.addressEntries ())
|
|
||||||
{
|
|
||||||
auto const& ip = ae.ip ();
|
|
||||||
if (server_.protocol () == ip.protocol ())
|
|
||||||
{
|
|
||||||
interface_ip = ip;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (QHostAddress {QHostAddress::Any} == interface_ip)
|
|
||||||
{
|
|
||||||
Q_EMIT self_->error ("Network interface has no suitable address for server IP protocol, please try another");
|
|
||||||
pending_messages_.clear (); // discard
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (localAddress () != interface_ip)
|
if (localAddress () != interface_addr)
|
||||||
{
|
{
|
||||||
if (UnconnectedState != state () || state ())
|
if (UnconnectedState != state () || state ())
|
||||||
{
|
{
|
||||||
@ -196,8 +178,8 @@ void MessageClient::impl::start ()
|
|||||||
}
|
}
|
||||||
// bind to an ephemeral port on the selected interface and set
|
// bind to an ephemeral port on the selected interface and set
|
||||||
// up for sending datagrams
|
// up for sending datagrams
|
||||||
bind (interface_ip);
|
bind (interface_addr);
|
||||||
setMulticastInterface (network_interface_);
|
qDebug () << "Bound to UDP port:" << localPort () << "on:" << localAddress ();
|
||||||
|
|
||||||
// set multicast TTL to limit scope when sending to multicast
|
// set multicast TTL to limit scope when sending to multicast
|
||||||
// group addresses
|
// group addresses
|
||||||
@ -210,7 +192,7 @@ void MessageClient::impl::start ()
|
|||||||
// clear any backlog
|
// clear any backlog
|
||||||
while (pending_messages_.size ())
|
while (pending_messages_.size ())
|
||||||
{
|
{
|
||||||
send_message (pending_messages_.dequeue ());
|
send_message (pending_messages_.dequeue (), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,14 +420,11 @@ void MessageClient::impl::heartbeat ()
|
|||||||
if (server_port_ && !server_.isNull ())
|
if (server_port_ && !server_.isNull ())
|
||||||
{
|
{
|
||||||
QByteArray message;
|
QByteArray message;
|
||||||
NetworkMessage::Builder hb {&message, NetworkMessage::Heartbeat, id_, schema_};
|
NetworkMessage::Builder out {&message, NetworkMessage::Heartbeat, id_, schema_};
|
||||||
hb << NetworkMessage::Builder::schema_number // maximum schema number accepted
|
out << NetworkMessage::Builder::schema_number // maximum schema number accepted
|
||||||
<< version_.toUtf8 () << revision_.toUtf8 ();
|
<< version_.toUtf8 () << revision_.toUtf8 ();
|
||||||
if (OK == check_status (hb))
|
|
||||||
{
|
|
||||||
TRACE_UDP ("schema:" << schema_ << "max schema:" << NetworkMessage::Builder::schema_number << "version:" << version_ << "revision:" << revision_);
|
TRACE_UDP ("schema:" << schema_ << "max schema:" << NetworkMessage::Builder::schema_number << "version:" << version_ << "revision:" << revision_);
|
||||||
writeDatagram (message, server_, server_port_);
|
send_message (out, message, false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,15 +434,12 @@ void MessageClient::impl::closedown ()
|
|||||||
{
|
{
|
||||||
QByteArray message;
|
QByteArray message;
|
||||||
NetworkMessage::Builder out {&message, NetworkMessage::Close, id_, schema_};
|
NetworkMessage::Builder out {&message, NetworkMessage::Close, id_, schema_};
|
||||||
if (OK == check_status (out))
|
|
||||||
{
|
|
||||||
TRACE_UDP ("");
|
TRACE_UDP ("");
|
||||||
writeDatagram (message, server_, server_port_);
|
send_message (out, message, false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageClient::impl::send_message (QByteArray const& message)
|
void MessageClient::impl::send_message (QByteArray const& message, bool queue_if_pending)
|
||||||
{
|
{
|
||||||
if (server_port_)
|
if (server_port_)
|
||||||
{
|
{
|
||||||
@ -471,11 +447,15 @@ void MessageClient::impl::send_message (QByteArray const& message)
|
|||||||
{
|
{
|
||||||
if (message != last_message_) // avoid duplicates
|
if (message != last_message_) // avoid duplicates
|
||||||
{
|
{
|
||||||
|
for (auto const& net_if : network_interfaces_)
|
||||||
|
{
|
||||||
|
setMulticastInterface (net_if);
|
||||||
writeDatagram (message, server_, server_port_);
|
writeDatagram (message, server_, server_port_);
|
||||||
|
}
|
||||||
last_message_ = message;
|
last_message_ = message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (queue_if_pending)
|
||||||
{
|
{
|
||||||
pending_messages_.enqueue (message);
|
pending_messages_.enqueue (message);
|
||||||
}
|
}
|
||||||
@ -509,7 +489,7 @@ auto MessageClient::impl::check_status (QDataStream const& stream) const -> Stre
|
|||||||
|
|
||||||
MessageClient::MessageClient (QString const& id, QString const& version, QString const& revision,
|
MessageClient::MessageClient (QString const& id, QString const& version, QString const& revision,
|
||||||
QString const& server_name, port_type server_port,
|
QString const& server_name, port_type server_port,
|
||||||
QString const& network_interface_name,
|
QStringList const& network_interface_names,
|
||||||
int TTL, QObject * self)
|
int TTL, QObject * self)
|
||||||
: QObject {self}
|
: QObject {self}
|
||||||
, m_ {id, version, revision, server_port, TTL, this}
|
, m_ {id, version, revision, server_port, TTL, this}
|
||||||
@ -532,7 +512,7 @@ MessageClient::MessageClient (QString const& id, QString const& version, QString
|
|||||||
Q_EMIT error (m_->errorString ());
|
Q_EMIT error (m_->errorString ());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
m_->set_server (server_name, network_interface_name);
|
m_->set_server (server_name, network_interface_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
QHostAddress MessageClient::server_address () const
|
QHostAddress MessageClient::server_address () const
|
||||||
@ -545,9 +525,9 @@ auto MessageClient::server_port () const -> port_type
|
|||||||
return m_->server_port_;
|
return m_->server_port_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageClient::set_server (QString const& server_name, QString const& network_interface_name)
|
void MessageClient::set_server (QString const& server_name, QStringList const& network_interface_names)
|
||||||
{
|
{
|
||||||
m_->set_server (server_name, network_interface_name);
|
m_->set_server (server_name, network_interface_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageClient::set_server_port (port_type server_port)
|
void MessageClient::set_server_port (port_type server_port)
|
||||||
|
@ -36,7 +36,7 @@ public:
|
|||||||
// messages will be silently dropped until a server host lookup is complete
|
// messages will be silently dropped until a server host lookup is complete
|
||||||
MessageClient (QString const& id, QString const& version, QString const& revision,
|
MessageClient (QString const& id, QString const& version, QString const& revision,
|
||||||
QString const& server_name, port_type server_port,
|
QString const& server_name, port_type server_port,
|
||||||
QString const& network_interface_name,
|
QStringList const& network_interface_names,
|
||||||
int TTL, QObject * parent = nullptr);
|
int TTL, QObject * parent = nullptr);
|
||||||
|
|
||||||
// query server details
|
// query server details
|
||||||
@ -46,7 +46,7 @@ public:
|
|||||||
// initiate a new server host lookup or if the server name is empty
|
// initiate a new server host lookup or if the server name is empty
|
||||||
// the sending of messages is disabled, if an interface is specified
|
// the sending of messages is disabled, if an interface is specified
|
||||||
// then that interface is used for outgoing datagrams
|
// then that interface is used for outgoing datagrams
|
||||||
Q_SLOT void set_server (QString const& server_name, QString const& network_interface_name);
|
Q_SLOT void set_server (QString const& server_name, QStringList const& network_interface_names);
|
||||||
|
|
||||||
// change the server port messages are sent to
|
// change the server port messages are sent to
|
||||||
Q_SLOT void set_server_port (port_type server_port = 0u);
|
Q_SLOT void set_server_port (port_type server_port = 0u);
|
||||||
|
@ -65,14 +65,14 @@ public:
|
|||||||
{
|
{
|
||||||
if (f != dial_frequency_)
|
if (f != dial_frequency_)
|
||||||
{
|
{
|
||||||
std::cout << tr ("%1(%2): Dial frequency changed to %3")
|
std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString ()
|
||||||
.arg (key_.second).arg (key_.first.toString ()).arg (f).toStdString () << std::endl;
|
<< QString {"Dial frequency changed to %1"}.arg (f).toStdString () << std::endl;
|
||||||
dial_frequency_ = f;
|
dial_frequency_ = f;
|
||||||
}
|
}
|
||||||
if (mode + sub_mode != mode_)
|
if (mode + sub_mode != mode_)
|
||||||
{
|
{
|
||||||
std::cout << tr ("%1(%2): Mode changed to %3")
|
std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString ()
|
||||||
.arg (key_.second).arg (key_.first.toString ()).arg (mode + sub_mode).toStdString () << std::endl;
|
<< QString {"Mode changed to %1"}.arg (mode + sub_mode).toStdString () << std::endl;
|
||||||
mode_ = mode + sub_mode;
|
mode_ = mode + sub_mode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,8 +88,8 @@ public:
|
|||||||
<< "Dt:" << delta_time << "Df:" << delta_frequency
|
<< "Dt:" << delta_time << "Df:" << delta_frequency
|
||||||
<< "mode:" << mode << "Confidence:" << (low_confidence ? "low" : "high")
|
<< "mode:" << mode << "Confidence:" << (low_confidence ? "low" : "high")
|
||||||
<< "On air:" << !off_air;
|
<< "On air:" << !off_air;
|
||||||
std::cout << tr ("%1(%2): Decoded %3")
|
std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString ()
|
||||||
.arg (key_.second).arg (key_.first.toString ()).arg (message).toStdString () << std::endl;
|
<< QString {"Decoded %1"}.arg (message).toStdString () << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,8 +102,9 @@ public:
|
|||||||
qDebug () << "new:" << is_new << "t:" << time << "snr:" << snr
|
qDebug () << "new:" << is_new << "t:" << time << "snr:" << snr
|
||||||
<< "Dt:" << delta_time << "Df:" << delta_frequency
|
<< "Dt:" << delta_time << "Df:" << delta_frequency
|
||||||
<< "drift:" << drift;
|
<< "drift:" << drift;
|
||||||
std::cout << tr ("%1(%2): WSPR decode %3 grid %4 power: %5")
|
std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString ()
|
||||||
.arg (key_.second).arg (key_.first.toString ()).arg (callsign).arg (grid).arg (power).toStdString ()
|
<< QString {"WSPR decode %1 grid %2 power: %3"}
|
||||||
|
.arg (callsign).arg (grid).arg (power).toStdString ()
|
||||||
<< "On air:" << !off_air << std::endl;
|
<< "On air:" << !off_air << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,8 +126,9 @@ public:
|
|||||||
<< "my_grid:" << my_grid << "exchange_sent:" << exchange_sent
|
<< "my_grid:" << my_grid << "exchange_sent:" << exchange_sent
|
||||||
<< "exchange_rcvd:" << exchange_rcvd << "prop_mode:" << prop_mode;
|
<< "exchange_rcvd:" << exchange_rcvd << "prop_mode:" << prop_mode;
|
||||||
std::cout << QByteArray {80, '-'}.data () << '\n';
|
std::cout << QByteArray {80, '-'}.data () << '\n';
|
||||||
std::cout << tr ("%1(%2): Logged %3 grid: %4 power: %5 sent: %6 recd: %7 freq: %8 time_off: %9 op: %10 my_call: %11 my_grid: %12 exchange_sent: %13 exchange_rcvd: %14 comments: %15 prop_mode: %16")
|
std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString ()
|
||||||
.arg (key_.second).arg (key.first.toString ()).arg (dx_call).arg (dx_grid).arg (tx_power)
|
<< QString {"Logged %1 grid: %2 power: %3 sent: %4 recd: %5 freq: %6 time_off: %7 op: %8 my_call: %9 my_grid: %10 exchange_sent: %11 exchange_rcvd: %12 comments: %13 prop_mode: %14"}
|
||||||
|
.arg (dx_call).arg (dx_grid).arg (tx_power)
|
||||||
.arg (report_sent).arg (report_received)
|
.arg (report_sent).arg (report_received)
|
||||||
.arg (dial_frequency).arg (time_off.toString("yyyy-MM-dd hh:mm:ss.z")).arg (operator_call)
|
.arg (dial_frequency).arg (time_off.toString("yyyy-MM-dd hh:mm:ss.z")).arg (operator_call)
|
||||||
.arg (my_call).arg (my_grid).arg (exchange_sent).arg (exchange_rcvd)
|
.arg (my_call).arg (my_grid).arg (exchange_sent).arg (exchange_rcvd)
|
||||||
|
@ -25,7 +25,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
CheckableItemComboBox::CheckableItemComboBox (QWidget * parent)
|
CheckableItemComboBox::CheckableItemComboBox (QWidget * parent)
|
||||||
: QComboBox {parent}
|
: LazyFillComboBox {parent}
|
||||||
, model_ {new QStandardItemModel()}
|
, model_ {new QStandardItemModel()}
|
||||||
{
|
{
|
||||||
setModel (model_.data ());
|
setModel (model_.data ());
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#ifndef CHECKABLE_ITEM_COMBO_BOX_HPP__
|
#ifndef CHECKABLE_ITEM_COMBO_BOX_HPP__
|
||||||
#define CHECKABLE_ITEM_COMBO_BOX_HPP__
|
#define CHECKABLE_ITEM_COMBO_BOX_HPP__
|
||||||
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
|
|
||||||
|
#include "LazyFillComboBox.hpp"
|
||||||
|
|
||||||
class QStandardItemModel;
|
class QStandardItemModel;
|
||||||
class QStandardItem;
|
class QStandardItem;
|
||||||
|
|
||||||
@ -12,7 +13,7 @@ class QStandardItem;
|
|||||||
* http://stackoverflow.com/questions/8422760/combobox-of-checkboxes
|
* http://stackoverflow.com/questions/8422760/combobox-of-checkboxes
|
||||||
*/
|
*/
|
||||||
class CheckableItemComboBox
|
class CheckableItemComboBox
|
||||||
: public QComboBox
|
: public LazyFillComboBox
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ class QWidget;
|
|||||||
//
|
//
|
||||||
// QComboBox derivative that signals show and hide of the pop up list.
|
// QComboBox derivative that signals show and hide of the pop up list.
|
||||||
//
|
//
|
||||||
class LazyFillComboBox final
|
class LazyFillComboBox
|
||||||
: public QComboBox
|
: public QComboBox
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -417,7 +417,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
m_messageClient {new MessageClient {QApplication::applicationName (),
|
m_messageClient {new MessageClient {QApplication::applicationName (),
|
||||||
version (), revision (),
|
version (), revision (),
|
||||||
m_config.udp_server_name (), m_config.udp_server_port (),
|
m_config.udp_server_name (), m_config.udp_server_port (),
|
||||||
m_config.udp_interface_name (), m_config.udp_TTL (),
|
m_config.udp_interface_names (), m_config.udp_TTL (),
|
||||||
this}},
|
this}},
|
||||||
m_psk_Reporter {&m_config, QString {"WSJT-X v" + version () + " " + m_revision}.simplified ()},
|
m_psk_Reporter {&m_config, QString {"WSJT-X v" + version () + " " + m_revision}.simplified ()},
|
||||||
m_manual {&m_network_manager},
|
m_manual {&m_network_manager},
|
||||||
@ -7837,7 +7837,7 @@ void MainWindow::networkError (QString const& e)
|
|||||||
, MessageBox::Cancel))
|
, MessageBox::Cancel))
|
||||||
{
|
{
|
||||||
// retry server lookup
|
// retry server lookup
|
||||||
m_messageClient->set_server (m_config.udp_server_name (), m_config.udp_interface_name ());
|
m_messageClient->set_server (m_config.udp_server_name (), m_config.udp_interface_names ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user