| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | #include "MessageClient.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  | #include <stdexcept>
 | 
					
						
							| 
									
										
										
										
											2017-12-17 22:44:05 +00:00
										 |  |  | #include <vector>
 | 
					
						
							|  |  |  | #include <algorithm>
 | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  | #include <limits>
 | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | #include <QUdpSocket>
 | 
					
						
							|  |  |  | #include <QHostInfo>
 | 
					
						
							|  |  |  | #include <QTimer>
 | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  | #include <QQueue>
 | 
					
						
							|  |  |  | #include <QByteArray>
 | 
					
						
							|  |  |  | #include <QHostAddress>
 | 
					
						
							| 
									
										
										
										
											2018-03-28 22:25:46 +00:00
										 |  |  | #include <QColor>
 | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  | #include <QDebug>
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "NetworkMessage.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "pimpl_impl.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "moc_MessageClient.cpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  | // some trace macros
 | 
					
						
							|  |  |  | #if WSJT_TRACE_UDP
 | 
					
						
							|  |  |  | #define TRACE_UDP(MSG) qDebug () << QString {"MessageClient::%1:"}.arg (__func__) << MSG
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define TRACE_UDP(MSG)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | class MessageClient::impl | 
					
						
							|  |  |  |   : public QUdpSocket | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Q_OBJECT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |   impl (QString const& id, QString const& version, QString const& revision, | 
					
						
							|  |  |  |         port_type server_port, MessageClient * self) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     : self_ {self} | 
					
						
							| 
									
										
										
										
											2020-06-21 01:36:30 +01:00
										 |  |  |     , dns_lookup_id_ {0} | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |     , enabled_ {false} | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     , id_ {id} | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |     , version_ {version} | 
					
						
							|  |  |  |     , revision_ {revision} | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     , server_port_ {server_port} | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |     , schema_ {2}  // use 2 prior to negotiation not 1 which is broken
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     , heartbeat_timer_ {new QTimer {this}} | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     connect (heartbeat_timer_, &QTimer::timeout, this, &impl::heartbeat); | 
					
						
							|  |  |  |     connect (this, &QIODevice::readyRead, this, &impl::pending_datagrams); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     heartbeat_timer_->start (NetworkMessage::pulse * 1000); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // bind to an ephemeral port
 | 
					
						
							|  |  |  |     bind (); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ~impl () | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     closedown (); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |   enum StreamStatus {Fail, Short, OK}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   void parse_message (QByteArray const& msg); | 
					
						
							|  |  |  |   void pending_datagrams (); | 
					
						
							|  |  |  |   void heartbeat (); | 
					
						
							|  |  |  |   void closedown (); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |   StreamStatus check_status (QDataStream const&) const; | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  |   void send_message (QByteArray const&); | 
					
						
							| 
									
										
										
										
											2015-11-13 15:44:11 +00:00
										 |  |  |   void send_message (QDataStream const& out, QByteArray const& message) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |       if (OK == check_status (out)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           send_message (message); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           Q_EMIT self_->error ("Error creating UDP message"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Q_SLOT void host_info_results (QHostInfo); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MessageClient * self_; | 
					
						
							| 
									
										
										
										
											2020-06-21 01:36:30 +01:00
										 |  |  |   int dns_lookup_id_; | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |   bool enabled_; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   QString id_; | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |   QString version_; | 
					
						
							|  |  |  |   QString revision_; | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  |   QString server_string_; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   port_type server_port_; | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  |   QHostAddress server_; | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |   quint32 schema_; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   QTimer * heartbeat_timer_; | 
					
						
							| 
									
										
										
										
											2017-12-17 22:44:05 +00:00
										 |  |  |   std::vector<QHostAddress> blocked_addresses_; | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // hold messages sent before host lookup completes asynchronously
 | 
					
						
							|  |  |  |   QQueue<QByteArray> pending_messages_; | 
					
						
							| 
									
										
										
										
											2015-12-24 21:37:16 +00:00
										 |  |  |   QByteArray last_message_; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MessageClient.moc"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MessageClient::impl::host_info_results (QHostInfo host_info) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-21 01:36:30 +01:00
										 |  |  |   if (host_info.lookupId () != dns_lookup_id_) return; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   if (QHostInfo::NoError != host_info.error ()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       Q_EMIT self_->error ("UDP server lookup failed:\n" + host_info.errorString ()); | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  |       pending_messages_.clear (); // discard
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   else if (host_info.addresses ().size ()) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-12-17 22:44:05 +00:00
										 |  |  |       auto server = host_info.addresses ()[0]; | 
					
						
							|  |  |  |       if (blocked_addresses_.end () == std::find (blocked_addresses_.begin (), blocked_addresses_.end (), server)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           server_ = server; | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |           TRACE_UDP ("resulting server:" << server); | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 22:44:05 +00:00
										 |  |  |           // send initial heartbeat which allows schema negotiation
 | 
					
						
							|  |  |  |           heartbeat (); | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 22:44:05 +00:00
										 |  |  |           // clear any backlog
 | 
					
						
							|  |  |  |           while (pending_messages_.size ()) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               send_message (pending_messages_.dequeue ()); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2017-12-17 22:44:05 +00:00
										 |  |  |           Q_EMIT self_->error ("UDP server blocked, please try another"); | 
					
						
							|  |  |  |           pending_messages_.clear (); // discard
 | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MessageClient::impl::pending_datagrams () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   while (hasPendingDatagrams ()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QByteArray datagram; | 
					
						
							|  |  |  |       datagram.resize (pendingDatagramSize ()); | 
					
						
							|  |  |  |       QHostAddress sender_address; | 
					
						
							|  |  |  |       port_type sender_port; | 
					
						
							|  |  |  |       if (0 <= readDatagram (datagram.data (), datagram.size (), &sender_address, &sender_port)) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |           TRACE_UDP ("message received from:" << sender_address << "port:" << sender_port); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |           parse_message (datagram); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MessageClient::impl::parse_message (QByteArray const& msg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |   try | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       // 
 | 
					
						
							|  |  |  |       // message format is described in NetworkMessage.hpp
 | 
					
						
							|  |  |  |       // 
 | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |       NetworkMessage::Reader in {msg}; | 
					
						
							| 
									
										
										
										
											2019-04-01 11:01:39 +01:00
										 |  |  |       if (OK == check_status (in)) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |           if (schema_ < in.schema ()) // one time record of server's
 | 
					
						
							|  |  |  |                                       // negotiated schema
 | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               schema_ = in.schema (); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |           if (!enabled_) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               TRACE_UDP ("message processing disabled for id:" << in.id ()); | 
					
						
							|  |  |  |               return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |           //
 | 
					
						
							|  |  |  |           // message format is described in NetworkMessage.hpp
 | 
					
						
							|  |  |  |           //
 | 
					
						
							|  |  |  |           switch (in.type ()) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |             case NetworkMessage::Reply: | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |               { | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |                 // unpack message
 | 
					
						
							|  |  |  |                 QTime time; | 
					
						
							|  |  |  |                 qint32 snr; | 
					
						
							|  |  |  |                 float delta_time; | 
					
						
							|  |  |  |                 quint32 delta_frequency; | 
					
						
							|  |  |  |                 QByteArray mode; | 
					
						
							|  |  |  |                 QByteArray message; | 
					
						
							| 
									
										
										
										
											2017-07-26 21:18:59 +00:00
										 |  |  |                 bool low_confidence {false}; | 
					
						
							| 
									
										
										
										
											2017-09-22 15:36:24 +00:00
										 |  |  |                 quint8 modifiers {0}; | 
					
						
							|  |  |  |                 in >> time >> snr >> delta_time >> delta_frequency >> mode >> message | 
					
						
							|  |  |  |                    >> low_confidence >> modifiers; | 
					
						
							| 
									
										
										
										
											2020-08-19 12:32:27 +01:00
										 |  |  |                 TRACE_UDP ("Reply: time:" << time << "snr:" << snr << "dt:" << delta_time << "df:" << delta_frequency << "mode:" << mode << "message:" << message << "low confidence:" << low_confidence << "modifiers: 0x" | 
					
						
							|  |  |  | #if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
 | 
					
						
							|  |  |  |                            << Qt::hex | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |                            << hex | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |                            << modifiers); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |                 if (check_status (in) != Fail) | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |                   { | 
					
						
							|  |  |  |                     Q_EMIT self_->reply (time, snr, delta_time, delta_frequency | 
					
						
							| 
									
										
										
										
											2017-07-26 21:18:59 +00:00
										 |  |  |                                          , QString::fromUtf8 (mode), QString::fromUtf8 (message) | 
					
						
							| 
									
										
										
										
											2017-09-22 15:36:24 +00:00
										 |  |  |                                          , low_confidence, modifiers); | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |                   } | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |               } | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-03 00:49:35 +00:00
										 |  |  |             case NetworkMessage::Clear: | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 quint8 window {0}; | 
					
						
							|  |  |  |                 in >> window; | 
					
						
							|  |  |  |                 TRACE_UDP ("Clear window:" << window); | 
					
						
							|  |  |  |                 if (check_status (in) != Fail) | 
					
						
							|  |  |  |                   { | 
					
						
							|  |  |  |                     Q_EMIT self_->clear_decodes (window); | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |             case NetworkMessage::Close: | 
					
						
							|  |  |  |               TRACE_UDP ("Close"); | 
					
						
							|  |  |  |               if (check_status (in) != Fail) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                   last_message_.clear (); | 
					
						
							|  |  |  |                   Q_EMIT self_->close (); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |             case NetworkMessage::Replay: | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |               TRACE_UDP ("Replay"); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |               if (check_status (in) != Fail) | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2016-02-02 01:48:08 +00:00
										 |  |  |                   last_message_.clear (); | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |                   Q_EMIT self_->replay (); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-06 20:30:29 +00:00
										 |  |  |             case NetworkMessage::HaltTx: | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |               { | 
					
						
							|  |  |  |                 bool auto_only {false}; | 
					
						
							|  |  |  |                 in >> auto_only; | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |                 TRACE_UDP ("Halt Tx auto_only:" << auto_only); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |                 if (check_status (in) != Fail) | 
					
						
							|  |  |  |                   { | 
					
						
							|  |  |  |                     Q_EMIT self_->halt_tx (auto_only); | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2015-05-06 20:30:29 +00:00
										 |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case NetworkMessage::FreeText: | 
					
						
							| 
									
										
										
										
											2015-05-28 17:33:39 +00:00
										 |  |  |               { | 
					
						
							|  |  |  |                 QByteArray message; | 
					
						
							|  |  |  |                 bool send {true}; | 
					
						
							|  |  |  |                 in >> message >> send; | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |                 TRACE_UDP ("FreeText message:" << message << "send:" << send); | 
					
						
							| 
									
										
										
										
											2015-05-28 17:33:39 +00:00
										 |  |  |                 if (check_status (in) != Fail) | 
					
						
							|  |  |  |                   { | 
					
						
							|  |  |  |                     Q_EMIT self_->free_text (QString::fromUtf8 (message), send); | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2015-05-06 20:30:29 +00:00
										 |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  |             case NetworkMessage::Location: | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 QByteArray location; | 
					
						
							|  |  |  |                 in >> location; | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |                 TRACE_UDP ("Location location:" << location); | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  |                 if (check_status (in) != Fail) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     Q_EMIT self_->location (QString::fromUtf8 (location)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 22:25:46 +00:00
										 |  |  |             case NetworkMessage::HighlightCallsign: | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 QByteArray call; | 
					
						
							|  |  |  |                 QColor bg;      // default invalid color
 | 
					
						
							|  |  |  |                 QColor fg;      // default invalid color
 | 
					
						
							|  |  |  |                 bool last_only {false}; | 
					
						
							|  |  |  |                 in >> call >> bg >> fg >> last_only; | 
					
						
							| 
									
										
										
										
											2019-01-02 01:54:56 +00:00
										 |  |  |                 TRACE_UDP ("HighlightCallsign call:" << call << "bg:" << bg << "fg:" << fg << "last only:" << last_only); | 
					
						
							| 
									
										
										
										
											2018-03-28 22:25:46 +00:00
										 |  |  |                 if (check_status (in) != Fail && call.size ()) | 
					
						
							|  |  |  |                   { | 
					
						
							|  |  |  |                     Q_EMIT self_->highlight_callsign (QString::fromUtf8 (call), bg, fg, last_only); | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-13 01:44:28 +01:00
										 |  |  |             case NetworkMessage::SwitchConfiguration: | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 QByteArray configuration_name; | 
					
						
							|  |  |  |                 in >> configuration_name; | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |                 TRACE_UDP ("Switch Configuration name:" << configuration_name); | 
					
						
							|  |  |  |                 if (check_status (in) != Fail) | 
					
						
							| 
									
										
										
										
											2019-06-13 01:44:28 +01:00
										 |  |  |                   { | 
					
						
							|  |  |  |                     Q_EMIT self_->switch_configuration (QString::fromUtf8 (configuration_name)); | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |             case NetworkMessage::Configure: | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 QByteArray mode; | 
					
						
							|  |  |  |                 quint32 frequency_tolerance; | 
					
						
							|  |  |  |                 QByteArray submode; | 
					
						
							|  |  |  |                 bool fast_mode {false}; | 
					
						
							|  |  |  |                 quint32 tr_period {std::numeric_limits<quint32>::max ()}; | 
					
						
							|  |  |  |                 quint32 rx_df {std::numeric_limits<quint32>::max ()}; | 
					
						
							|  |  |  |                 QByteArray dx_call; | 
					
						
							|  |  |  |                 QByteArray dx_grid; | 
					
						
							|  |  |  |                 bool generate_messages {false}; | 
					
						
							|  |  |  |                 in >> mode >> frequency_tolerance >> submode >> fast_mode >> tr_period >> rx_df | 
					
						
							|  |  |  |                    >> dx_call >> dx_grid >> generate_messages; | 
					
						
							|  |  |  |                 TRACE_UDP ("Configure mode:" << mode << "frequency tolerance:" << frequency_tolerance << "submode:" << submode << "fast mode:" << fast_mode << "T/R period:" << tr_period << "rx df:" << rx_df << "dx call:" << dx_call << "dx grid:" << dx_grid << "generate messages:" << generate_messages); | 
					
						
							|  |  |  |                 if (check_status (in) != Fail) | 
					
						
							|  |  |  |                   { | 
					
						
							|  |  |  |                     Q_EMIT self_->configure (QString::fromUtf8 (mode), frequency_tolerance | 
					
						
							|  |  |  |                                              , QString::fromUtf8 (submode), fast_mode, tr_period, rx_df | 
					
						
							|  |  |  |                                              , QString::fromUtf8 (dx_call), QString::fromUtf8 (dx_grid) | 
					
						
							|  |  |  |                                              , generate_messages); | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |             default: | 
					
						
							|  |  |  |               // Ignore
 | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |               //
 | 
					
						
							|  |  |  |               // Note that although server  heartbeat messages are not
 | 
					
						
							|  |  |  |               // parsed here  they are  still partially parsed  in the
 | 
					
						
							|  |  |  |               // message reader class to  negotiate the maximum schema
 | 
					
						
							|  |  |  |               // number being used on the network.
 | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |               if (NetworkMessage::Heartbeat != in.type ()) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                   TRACE_UDP ("ignoring message type:" << in.type ()); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |               break; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |       else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           TRACE_UDP ("ignored message for id:" << in.id ()); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |   catch (std::exception const& e) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       Q_EMIT self_->error (QString {"MessageClient exception: %1"}.arg (e.what ())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   catch (...) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       Q_EMIT self_->error ("Unexpected exception in MessageClient"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MessageClient::impl::heartbeat () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |    if (server_port_ && !server_.isNull ()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |       NetworkMessage::Builder hb {&message, NetworkMessage::Heartbeat, id_, schema_}; | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |       hb << NetworkMessage::Builder::schema_number // maximum schema number accepted
 | 
					
						
							|  |  |  |          << version_.toUtf8 () << revision_.toUtf8 (); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |       if (OK == check_status (hb)) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |           TRACE_UDP ("schema:" << schema_ << "max schema:" << NetworkMessage::Builder::schema_number << "version:" << version_ << "revision:" << revision_); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |           writeDatagram (message, server_, server_port_); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MessageClient::impl::closedown () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |    if (server_port_ && !server_.isNull ()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |       NetworkMessage::Builder out {&message, NetworkMessage::Close, id_, schema_}; | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |       if (OK == check_status (out)) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |           TRACE_UDP (""); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |           writeDatagram (message, server_, server_port_); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  | void MessageClient::impl::send_message (QByteArray const& message) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (server_port_) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (!server_.isNull ()) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2015-12-24 21:37:16 +00:00
										 |  |  |           if (message != last_message_) // avoid duplicates
 | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               writeDatagram (message, server_, server_port_); | 
					
						
							|  |  |  |               last_message_ = message; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           pending_messages_.enqueue (message); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  | auto MessageClient::impl::check_status (QDataStream const& stream) const -> StreamStatus | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   auto stat = stream.status (); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |   StreamStatus result {Fail}; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   switch (stat) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case QDataStream::ReadPastEnd: | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |       result = Short; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QDataStream::ReadCorruptData: | 
					
						
							|  |  |  |       Q_EMIT self_->error ("Message serialization error: read corrupt data"); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case QDataStream::WriteFailed: | 
					
						
							|  |  |  |       Q_EMIT self_->error ("Message serialization error: write error"); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |       result = OK; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |   return result; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  | MessageClient::MessageClient (QString const& id, QString const& version, QString const& revision, | 
					
						
							|  |  |  |                               QString const& server, port_type server_port, QObject * self) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   : QObject {self} | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |   , m_ {id, version, revision, server_port, this} | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-21 01:36:30 +01:00
										 |  |  |   connect (&*m_ | 
					
						
							| 
									
										
										
										
											2020-06-13 16:04:41 +01:00
										 |  |  | #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
 | 
					
						
							| 
									
										
										
										
											2020-07-26 15:55:17 +01:00
										 |  |  |            , static_cast<void (impl::*) (impl::SocketError)> (&impl::error), [this] (impl::SocketError e) | 
					
						
							| 
									
										
										
										
											2015-11-16 09:04:48 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2020-07-26 15:55:17 +01:00
										 |  |  |            , &impl::errorOccurred, [this] (impl::SocketError e) | 
					
						
							| 
									
										
										
										
											2015-11-15 23:03:11 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-07-26 15:55:17 +01:00
										 |  |  |                                    { | 
					
						
							| 
									
										
										
										
											2020-06-21 01:36:30 +01:00
										 |  |  | #if defined (Q_OS_WIN)
 | 
					
						
							| 
									
										
										
										
											2020-07-26 15:55:17 +01:00
										 |  |  |                                      if (e != impl::NetworkError // take this out when Qt 5.5 stops doing this spuriously
 | 
					
						
							|  |  |  |                                          && e != impl::ConnectionRefusedError) // not interested in this with UDP socket
 | 
					
						
							|  |  |  |                                        { | 
					
						
							| 
									
										
										
										
											2020-06-13 16:04:41 +01:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2020-07-26 15:55:17 +01:00
										 |  |  |                                        { | 
					
						
							|  |  |  |                                          Q_UNUSED (e); | 
					
						
							| 
									
										
										
										
											2020-06-13 16:04:41 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-07-26 15:55:17 +01:00
										 |  |  |                                          Q_EMIT error (m_->errorString ()); | 
					
						
							|  |  |  |                                        } | 
					
						
							|  |  |  |                                    }); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   set_server (server); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QHostAddress MessageClient::server_address () const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return m_->server_; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | auto MessageClient::server_port () const -> port_type | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return m_->server_port_; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MessageClient::set_server (QString const& server) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   m_->server_.clear (); | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  |   m_->server_string_ = server; | 
					
						
							| 
									
										
										
										
											2020-06-21 01:36:30 +01:00
										 |  |  |   if (server.size ()) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       // queue a host address lookup
 | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |       TRACE_UDP ("server host DNS lookup:" << server); | 
					
						
							| 
									
										
										
										
											2020-08-07 22:40:15 +01:00
										 |  |  | #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
 | 
					
						
							| 
									
										
										
										
											2020-06-21 01:36:30 +01:00
										 |  |  |       m_->dns_lookup_id_ = QHostInfo::lookupHost (server, &*m_, &MessageClient::impl::host_info_results); | 
					
						
							| 
									
										
										
										
											2020-08-07 22:40:15 +01:00
										 |  |  | #else
 | 
					
						
							|  |  |  |       m_->dns_lookup_id_ = QHostInfo::lookupHost (server, &*m_, SLOT (host_info_results (QHostInfo))); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MessageClient::set_server_port (port_type server_port) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   m_->server_port_ = server_port; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  | void MessageClient::enable (bool flag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   m_->enabled_ = flag; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | void MessageClient::status_update (Frequency f, QString const& mode, QString const& dx_call | 
					
						
							| 
									
										
										
										
											2015-05-06 22:25:56 +00:00
										 |  |  |                                    , QString const& report, QString const& tx_mode | 
					
						
							| 
									
										
										
										
											2016-05-24 10:08:35 +00:00
										 |  |  |                                    , bool tx_enabled, bool transmitting, bool decoding | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |                                    , quint32 rx_df, quint32 tx_df, QString const& de_call | 
					
						
							| 
									
										
										
										
											2016-07-08 10:25:21 +00:00
										 |  |  |                                    , QString const& de_grid, QString const& dx_grid | 
					
						
							| 
									
										
										
										
											2016-12-16 19:36:21 +00:00
										 |  |  |                                    , bool watchdog_timeout, QString const& sub_mode | 
					
						
							| 
									
										
										
										
											2019-06-13 01:44:28 +01:00
										 |  |  |                                    , bool fast_mode, quint8 special_op_mode | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |                                    , quint32 frequency_tolerance, quint32 tr_period | 
					
						
							| 
									
										
										
										
											2019-06-13 01:44:28 +01:00
										 |  |  |                                    , QString const& configuration_name) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  |   if (m_->server_port_ && !m_->server_string_.isEmpty ()) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |       NetworkMessage::Builder out {&message, NetworkMessage::Status, m_->id_, m_->schema_}; | 
					
						
							| 
									
										
										
										
											2015-05-06 20:30:29 +00:00
										 |  |  |       out << f << mode.toUtf8 () << dx_call.toUtf8 () << report.toUtf8 () << tx_mode.toUtf8 () | 
					
						
							| 
									
										
										
										
											2016-05-24 10:08:35 +00:00
										 |  |  |           << tx_enabled << transmitting << decoding << rx_df << tx_df << de_call.toUtf8 () | 
					
						
							| 
									
										
										
										
											2016-12-16 19:36:21 +00:00
										 |  |  |           << de_grid.toUtf8 () << dx_grid.toUtf8 () << watchdog_timeout << sub_mode.toUtf8 () | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |           << fast_mode << special_op_mode << frequency_tolerance << tr_period << configuration_name.toUtf8 (); | 
					
						
							|  |  |  |       TRACE_UDP ("frequency:" << f << "mode:" << mode << "DX:" << dx_call << "report:" << report << "Tx mode:" << tx_mode << "tx_enabled:" << tx_enabled << "Tx:" << transmitting << "decoding:" << decoding << "Rx df:" << rx_df << "Tx df:" << tx_df << "DE:" << de_call << "DE grid:" << de_grid << "DX grid:" << dx_grid << "w/d t/o:" << watchdog_timeout << "sub_mode:" << sub_mode << "fast mode:" << fast_mode << "spec op mode:" << special_op_mode << "frequency tolerance:" << frequency_tolerance << "T/R period:" << tr_period << "configuration name:" << configuration_name); | 
					
						
							| 
									
										
										
										
											2015-11-13 15:44:11 +00:00
										 |  |  |       m_->send_message (out, message); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MessageClient::decode (bool is_new, QTime time, qint32 snr, float delta_time, quint32 delta_frequency | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  |                             , QString const& mode, QString const& message_text, bool low_confidence | 
					
						
							|  |  |  |                             , bool off_air) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  |    if (m_->server_port_ && !m_->server_string_.isEmpty ()) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |       NetworkMessage::Builder out {&message, NetworkMessage::Decode, m_->id_, m_->schema_}; | 
					
						
							| 
									
										
										
										
											2017-07-26 21:18:59 +00:00
										 |  |  |       out << is_new << time << snr << delta_time << delta_frequency << mode.toUtf8 () | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  |           << message_text.toUtf8 () << low_confidence << off_air; | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |       TRACE_UDP ("new" << is_new << "time:" << time << "snr:" << snr << "dt:" << delta_time << "df:" << delta_frequency << "mode:" << mode << "text:" << message_text << "low conf:" << low_confidence << "off air:" << off_air); | 
					
						
							| 
									
										
										
										
											2015-11-13 15:44:11 +00:00
										 |  |  |       m_->send_message (out, message); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-15 23:03:11 +00:00
										 |  |  | void MessageClient::WSPR_decode (bool is_new, QTime time, qint32 snr, float delta_time, Frequency frequency | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  |                                  , qint32 drift, QString const& callsign, QString const& grid, qint32 power | 
					
						
							|  |  |  |                                  , bool off_air) | 
					
						
							| 
									
										
										
										
											2015-11-15 23:03:11 +00:00
										 |  |  | { | 
					
						
							|  |  |  |    if (m_->server_port_ && !m_->server_string_.isEmpty ()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							|  |  |  |       NetworkMessage::Builder out {&message, NetworkMessage::WSPRDecode, m_->id_, m_->schema_}; | 
					
						
							|  |  |  |       out << is_new << time << snr << delta_time << frequency << drift << callsign.toUtf8 () | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  |           << grid.toUtf8 () << power << off_air; | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |       TRACE_UDP ("new:" << is_new << "time:" << time << "snr:" << snr << "dt:" << delta_time << "frequency:" << frequency << "drift:" << drift << "call:" << callsign << "grid:" << grid << "pwr:" << power << "off air:" << off_air); | 
					
						
							| 
									
										
										
										
											2015-11-15 23:03:11 +00:00
										 |  |  |       m_->send_message (out, message); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-03 00:49:35 +00:00
										 |  |  | void MessageClient::decodes_cleared () | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  |    if (m_->server_port_ && !m_->server_string_.isEmpty ()) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |       NetworkMessage::Builder out {&message, NetworkMessage::Clear, m_->id_, m_->schema_}; | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |       TRACE_UDP (""); | 
					
						
							| 
									
										
										
										
											2015-11-13 15:44:11 +00:00
										 |  |  |       m_->send_message (out, message); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  | void MessageClient::qso_logged (QDateTime time_off, QString const& dx_call, QString const& dx_grid | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |                                 , Frequency dial_frequency, QString const& mode, QString const& report_sent | 
					
						
							|  |  |  |                                 , QString const& report_received, QString const& tx_power | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  |                                 , QString const& comments, QString const& name, QDateTime time_on | 
					
						
							|  |  |  |                                 , QString const& operator_call, QString const& my_call | 
					
						
							| 
									
										
										
										
											2018-12-02 10:09:37 -05:00
										 |  |  |                                 , QString const& my_grid, QString const& exchange_sent | 
					
						
							| 
									
										
										
										
											2020-06-25 19:58:47 +02:00
										 |  |  |                                 , QString const& exchange_rcvd, QString const& propmode) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-06-18 22:01:40 +00:00
										 |  |  |    if (m_->server_port_ && !m_->server_string_.isEmpty ()) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |       NetworkMessage::Builder out {&message, NetworkMessage::QSOLogged, m_->id_, m_->schema_}; | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  |       out << time_off << dx_call.toUtf8 () << dx_grid.toUtf8 () << dial_frequency << mode.toUtf8 () | 
					
						
							|  |  |  |           << report_sent.toUtf8 () << report_received.toUtf8 () << tx_power.toUtf8 () << comments.toUtf8 () | 
					
						
							| 
									
										
										
										
											2018-12-02 10:09:37 -05:00
										 |  |  |           << name.toUtf8 () << time_on << operator_call.toUtf8 () << my_call.toUtf8 () << my_grid.toUtf8 () | 
					
						
							| 
									
										
										
										
											2020-06-25 19:58:47 +02:00
										 |  |  |           << exchange_sent.toUtf8 () << exchange_rcvd.toUtf8 () << propmode.toUtf8 (); | 
					
						
							|  |  |  |       TRACE_UDP ("time off:" << time_off << "DX:" << dx_call << "DX grid:" << dx_grid << "dial:" << dial_frequency << "mode:" << mode << "sent:" << report_sent << "rcvd:" << report_received << "pwr:" << tx_power << "comments:" << comments << "name:" << name << "time on:" << time_on << "op:" << operator_call << "DE:" << my_call << "DE grid:" << my_grid << "exch sent:" << exchange_sent << "exch rcvd:" << exchange_rcvd  << "prop_mode:" << propmode); | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  |       m_->send_message (out, message); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MessageClient::logged_ADIF (QByteArray const& ADIF_record) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |    if (m_->server_port_ && !m_->server_string_.isEmpty ()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							|  |  |  |       NetworkMessage::Builder out {&message, NetworkMessage::LoggedADIF, m_->id_, m_->schema_}; | 
					
						
							| 
									
										
										
										
											2019-05-28 12:54:57 +01:00
										 |  |  |       QByteArray ADIF {"\n<adif_ver:5>3.1.0\n<programid:6>WSJT-X\n<EOH>\n" + ADIF_record + " <EOR>"}; | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  |       out << ADIF; | 
					
						
							| 
									
										
										
										
											2019-01-01 23:38:14 +00:00
										 |  |  |       TRACE_UDP ("ADIF:" << ADIF); | 
					
						
							| 
									
										
										
										
											2015-11-13 15:44:11 +00:00
										 |  |  |       m_->send_message (out, message); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } |