Add blocking mechanism for UDP message destinations and enforce for pskreporter addresses

Avoid fragmentation of pskreporter destined datagrams

Keep  datagram size  below  a  reasonable IPv4  MTU  size of  protocol
headers + 1400.

Thanks to Philip,  N1DQ, for the suggestion as with  FT8 mode datagram
payload sizes to Pskrepotrer are sometimes as big a 8kBytes.

Correct a factor of two error in Pskreporter UDP message sizing

Data is built  as a hexadecmal string,  so is twice the  length of the
message bytes it is encoded as.

Merged from trunk.



git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx-1.8@8345 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2017-12-18 23:13:17 +00:00
parent 87105ad563
commit 6a3fec129c
3 changed files with 58 additions and 24 deletions

View File

@ -1,6 +1,8 @@
#include "MessageClient.hpp" #include "MessageClient.hpp"
#include <stdexcept> #include <stdexcept>
#include <vector>
#include <algorithm>
#include <QUdpSocket> #include <QUdpSocket>
#include <QHostInfo> #include <QHostInfo>
@ -76,6 +78,7 @@ public:
QHostAddress server_; QHostAddress server_;
quint32 schema_; quint32 schema_;
QTimer * heartbeat_timer_; QTimer * heartbeat_timer_;
std::vector<QHostAddress> blocked_addresses_;
// hold messages sent before host lookup completes asynchronously // hold messages sent before host lookup completes asynchronously
QQueue<QByteArray> pending_messages_; QQueue<QByteArray> pending_messages_;
@ -93,15 +96,24 @@ void MessageClient::impl::host_info_results (QHostInfo host_info)
} }
else if (host_info.addresses ().size ()) else if (host_info.addresses ().size ())
{ {
server_ = host_info.addresses ()[0]; auto server = host_info.addresses ()[0];
if (blocked_addresses_.end () == std::find (blocked_addresses_.begin (), blocked_addresses_.end (), server))
// send initial heartbeat which allows schema negotiation
heartbeat ();
// clear any backlog
while (pending_messages_.size ())
{ {
send_message (pending_messages_.dequeue ()); server_ = server;
// send initial heartbeat which allows schema negotiation
heartbeat ();
// clear any backlog
while (pending_messages_.size ())
{
send_message (pending_messages_.dequeue ());
}
}
else
{
Q_EMIT self_->error ("UDP server blocked, please try another");
pending_messages_.clear (); // discard
} }
} }
} }
@ -349,6 +361,17 @@ void MessageClient::send_raw_datagram (QByteArray const& message, QHostAddress c
} }
} }
void MessageClient::add_blocked_destination (QHostAddress const& a)
{
m_->blocked_addresses_.push_back (a);
if (a == m_->server_)
{
m_->server_.clear ();
Q_EMIT error ("UDP server blocked, please try another");
m_->pending_messages_.clear (); // discard
}
}
void MessageClient::status_update (Frequency f, QString const& mode, QString const& dx_call void MessageClient::status_update (Frequency f, QString const& mode, QString const& dx_call
, QString const& report, QString const& tx_mode , QString const& report, QString const& tx_mode
, bool tx_enabled, bool transmitting, bool decoding , bool tx_enabled, bool transmitting, bool decoding

View File

@ -69,6 +69,10 @@ public:
// UDP messaging if desired // UDP messaging if desired
Q_SLOT void send_raw_datagram (QByteArray const&, QHostAddress const& dest_address, port_type dest_port); Q_SLOT void send_raw_datagram (QByteArray const&, QHostAddress const& dest_address, port_type dest_port);
// disallowed message destination (does not block datagrams sent
// with send_raw_datagram() above)
Q_SLOT void add_blocked_destination (QHostAddress const&);
// this signal is emitted if the server sends us a reply, the only // this signal is emitted if the server sends us a reply, the only
// reply supported is reply to a prior CQ or QRZ message // reply supported is reply to a prior CQ or QRZ message
Q_SIGNAL void reply (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode Q_SIGNAL void reply (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode

View File

@ -12,6 +12,11 @@
#include "moc_psk_reporter.cpp" #include "moc_psk_reporter.cpp"
namespace
{
int constexpr MAX_PAYLOAD_LENGTH {1400};
}
PSK_Reporter::PSK_Reporter(MessageClient * message_client, QObject *parent) : PSK_Reporter::PSK_Reporter(MessageClient * message_client, QObject *parent) :
QObject {parent}, QObject {parent},
m_messageClient {message_client}, m_messageClient {message_client},
@ -68,10 +73,7 @@ void PSK_Reporter::addRemoteStation(QString call, QString grid, QString freq, QS
void PSK_Reporter::sendReport() void PSK_Reporter::sendReport()
{ {
if (m_spotQueue.isEmpty()) { while (!m_spotQueue.isEmpty()) {
return;
}
QString report_h; QString report_h;
// Header // Header
@ -91,15 +93,16 @@ void PSK_Reporter::sendReport()
// Sender information // Sender information
QString txInfoData_h = "50E3llll"; QString txInfoData_h = "50E3llll";
while (!m_spotQueue.isEmpty()) { while (!m_spotQueue.isEmpty()
QHash<QString,QString> spot = m_spotQueue.dequeue(); && (header_h.size () + m_rxInfoDescriptor_h.size () + m_txInfoDescriptor_h.size () + rxInfoData_h.size () + txInfoData_h.size ()) / 2 < MAX_PAYLOAD_LENGTH) {
txInfoData_h += QString("%1").arg(spot["call"].length(),2,16,QChar('0')) + spot["call"].toUtf8().toHex(); QHash<QString,QString> spot = m_spotQueue.dequeue();
txInfoData_h += QString("%1").arg(spot["freq"].toLongLong(),8,16,QChar('0')); txInfoData_h += QString("%1").arg(spot["call"].length(),2,16,QChar('0')) + spot["call"].toUtf8().toHex();
txInfoData_h += QString("%1").arg(spot["snr"].toInt(),8,16,QChar('0')).right(2); txInfoData_h += QString("%1").arg(spot["freq"].toLongLong(),8,16,QChar('0'));
txInfoData_h += QString("%1").arg(spot["mode"].length(),2,16,QChar('0')) + spot["mode"].toUtf8().toHex(); txInfoData_h += QString("%1").arg(spot["snr"].toInt(),8,16,QChar('0')).right(2);
txInfoData_h += QString("%1").arg(spot["grid"].length(),2,16,QChar('0')) + spot["grid"].toUtf8().toHex(); txInfoData_h += QString("%1").arg(spot["mode"].length(),2,16,QChar('0')) + spot["mode"].toUtf8().toHex();
txInfoData_h += QString("%1").arg(1,2,16,QChar('0')); // REPORTER_SOURCE_AUTOMATIC txInfoData_h += QString("%1").arg(spot["grid"].length(),2,16,QChar('0')) + spot["grid"].toUtf8().toHex();
txInfoData_h += QString("%1").arg(spot["time"].toInt(),8,16,QChar('0')); txInfoData_h += QString("%1").arg(1,2,16,QChar('0')); // REPORTER_SOURCE_AUTOMATIC
txInfoData_h += QString("%1").arg(spot["time"].toInt(),8,16,QChar('0'));
} }
txInfoData_h += "0000"; txInfoData_h += "0000";
txInfoData_h.replace("50E3llll", "50E3" + QString("%1").arg(txInfoData_h.length()/2,4,16,QChar('0'))); txInfoData_h.replace("50E3llll", "50E3" + QString("%1").arg(txInfoData_h.length()/2,4,16,QChar('0')));
@ -113,14 +116,18 @@ void PSK_Reporter::sendReport()
if (!m_pskReporterAddress.isNull()) { if (!m_pskReporterAddress.isNull()) {
m_messageClient->send_raw_datagram (report, m_pskReporterAddress, 4739); m_messageClient->send_raw_datagram (report, m_pskReporterAddress, 4739);
} }
}
} }
void PSK_Reporter::dnsLookupResult(QHostInfo info) void PSK_Reporter::dnsLookupResult(QHostInfo info)
{ {
if (!info.addresses().isEmpty()) { if (!info.addresses().isEmpty()) {
m_pskReporterAddress = info.addresses().at(0); m_pskReporterAddress = info.addresses().at(0);
// qDebug() << "PSK Reporter IP: " << m_pskReporterAddress; // qDebug() << "PSK Reporter IP: " << m_pskReporterAddress;
// deal with miss-configured settings that attempt to set a
// Pskreporter Internet address for the WSJT-X UDP protocol
// server address
m_messageClient->add_blocked_destination (m_pskReporterAddress);
} }
} }