| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | #include "MessageServer.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  | #include <stdexcept>
 | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  | #include <limits>
 | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-11 23:17:43 +00:00
										 |  |  | #include <QNetworkInterface>
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | #include <QUdpSocket>
 | 
					
						
							|  |  |  | #include <QTimer>
 | 
					
						
							| 
									
										
										
										
											2015-04-15 19:24:41 +00:00
										 |  |  | #include <QHash>
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-24 10:08:35 +00:00
										 |  |  | #include "Radio.hpp"
 | 
					
						
							| 
									
										
										
										
											2019-07-02 13:00:32 -05:00
										 |  |  | #include "Network/NetworkMessage.hpp"
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | #include "qt_helpers.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "pimpl_impl.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "moc_MessageServer.cpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  | namespace | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   auto quint32_max = std::numeric_limits<quint32>::max (); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | class MessageServer::impl | 
					
						
							|  |  |  |   : public QUdpSocket | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Q_OBJECT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |   impl (MessageServer * self, QString const& version, QString const& revision) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     : self_ {self} | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |     , version_ {version} | 
					
						
							|  |  |  |     , revision_ {revision} | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     , clock_ {new QTimer {this}} | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2016-05-24 10:08:35 +00:00
										 |  |  |     // register the required types with Qt
 | 
					
						
							|  |  |  |     Radio::register_types (); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     connect (this, &QIODevice::readyRead, this, &MessageServer::impl::pending_datagrams); | 
					
						
							| 
									
										
										
										
											2020-06-13 16:04:41 +01:00
										 |  |  | #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     connect (this, static_cast<void (impl::*) (SocketError)> (&impl::error) | 
					
						
							|  |  |  |              , [this] (SocketError /* e */) | 
					
						
							|  |  |  |              { | 
					
						
							|  |  |  |                Q_EMIT self_->error (errorString ()); | 
					
						
							|  |  |  |              }); | 
					
						
							| 
									
										
										
										
											2020-06-13 16:04:41 +01:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     connect (this, &impl::errorOccurred, [this] (SocketError /* e */) | 
					
						
							|  |  |  |                                  { | 
					
						
							|  |  |  |                                    Q_EMIT self_->error (errorString ()); | 
					
						
							|  |  |  |                                  }); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     connect (clock_, &QTimer::timeout, this, &impl::tick); | 
					
						
							|  |  |  |     clock_->start (NetworkMessage::pulse * 1000); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |   enum StreamStatus {Fail, Short, OK}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   void leave_multicast_group (); | 
					
						
							|  |  |  |   void join_multicast_group (); | 
					
						
							|  |  |  |   void parse_message (QHostAddress const& sender, port_type sender_port, QByteArray const& msg); | 
					
						
							|  |  |  |   void tick (); | 
					
						
							|  |  |  |   void pending_datagrams (); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |   StreamStatus check_status (QDataStream const&) const; | 
					
						
							| 
									
										
										
										
											2015-11-13 15:44:11 +00:00
										 |  |  |   void send_message (QDataStream const& out, QByteArray const& message, QHostAddress const& address, port_type port) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |       if (OK == check_status (out)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           writeDatagram (message, address, port); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           Q_EMIT self_->error ("Error creating UDP message"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   MessageServer * self_; | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |   QString version_; | 
					
						
							|  |  |  |   QString revision_; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   QHostAddress multicast_group_address_; | 
					
						
							| 
									
										
										
										
											2020-11-03 20:31:11 +00:00
										 |  |  |   QSet<QString> network_interfaces_; | 
					
						
							| 
									
										
										
										
											2016-05-01 00:40:51 +00:00
										 |  |  |   static BindMode constexpr bind_mode_ = ShareAddress | ReuseAddressHint; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   struct Client | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |     Client () = default; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |     Client (port_type const& sender_port) | 
					
						
							|  |  |  |       : sender_port_ {sender_port} | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |       , negotiated_schema_number_ {2} // not 1 because it's broken
 | 
					
						
							|  |  |  |       , last_activity_ {QDateTime::currentDateTime ()} | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Client (Client const&) = default; | 
					
						
							|  |  |  |     Client& operator= (Client const&) = default; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     port_type sender_port_; | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |     quint32 negotiated_schema_number_; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     QDateTime last_activity_; | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |   QHash<ClientKey, Client> clients_; // maps id to Client
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   QTimer * clock_; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-01 00:40:51 +00:00
										 |  |  | MessageServer::impl::BindMode constexpr MessageServer::impl::bind_mode_; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-01 00:40:51 +00:00
										 |  |  | #include "MessageServer.moc"
 | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void MessageServer::impl::leave_multicast_group () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  |   if (BoundState == state () && is_multicast_address (multicast_group_address_)) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  |       for (auto const& if_name : network_interfaces_) | 
					
						
							| 
									
										
										
										
											2019-01-11 23:17:43 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  |           leaveMulticastGroup (multicast_group_address_, QNetworkInterface::interfaceFromName (if_name)); | 
					
						
							| 
									
										
										
										
											2019-01-11 23:17:43 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MessageServer::impl::join_multicast_group () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  |   if (BoundState == state () && is_multicast_address (multicast_group_address_)) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  |       if (network_interfaces_.size ()) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  |           for (auto const& if_name : network_interfaces_) | 
					
						
							| 
									
										
										
										
											2019-01-11 23:17:43 +00:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  |               joinMulticastGroup (multicast_group_address_, QNetworkInterface::interfaceFromName (if_name)); | 
					
						
							| 
									
										
										
										
											2019-01-11 23:17:43 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  |           // find the loop-back interface and join on that
 | 
					
						
							|  |  |  |           for (auto const& net_if : QNetworkInterface::allInterfaces ()) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               auto flags = QNetworkInterface::IsUp | QNetworkInterface::IsLoopBack | QNetworkInterface::CanMulticast; | 
					
						
							|  |  |  |               if ((net_if.flags () & flags) == flags) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                   joinMulticastGroup (multicast_group_address_, net_if); | 
					
						
							|  |  |  |                   break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MessageServer::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)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           parse_message (sender_address, sender_port, datagram); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MessageServer::impl::parse_message (QHostAddress const& sender, port_type sender_port, QByteArray const& msg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |   try | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |       //
 | 
					
						
							|  |  |  |       // message format is described in NetworkMessage.hpp
 | 
					
						
							|  |  |  |       //
 | 
					
						
							|  |  |  |       NetworkMessage::Reader in {msg}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       auto id = in.id (); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |       if (OK == check_status (in)) | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |           auto client_key = ClientKey {sender, id}; | 
					
						
							|  |  |  |           if (!clients_.contains (client_key)) | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |               auto& client = (clients_[client_key] = {sender_port}); | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |               QByteArray client_version; | 
					
						
							|  |  |  |               QByteArray client_revision; | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |               if (NetworkMessage::Heartbeat == in.type ()) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                   // negotiate a working schema number
 | 
					
						
							|  |  |  |                   in >> client.negotiated_schema_number_; | 
					
						
							|  |  |  |                   if (OK == check_status (in)) | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                       auto sn = NetworkMessage::Builder::schema_number; | 
					
						
							|  |  |  |                       client.negotiated_schema_number_ = std::min (sn, client.negotiated_schema_number_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                       // reply to the new client informing it of the
 | 
					
						
							|  |  |  |                       // negotiated schema number
 | 
					
						
							|  |  |  |                       QByteArray message; | 
					
						
							|  |  |  |                       NetworkMessage::Builder hb {&message, NetworkMessage::Heartbeat, id, client.negotiated_schema_number_}; | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |                       hb << NetworkMessage::Builder::schema_number // maximum schema number accepted
 | 
					
						
							|  |  |  |                          << version_.toUtf8 () << revision_.toUtf8 (); | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |                       if (impl::OK == check_status (hb)) | 
					
						
							|  |  |  |                         { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |                           writeDatagram (message, client_key.first, sender_port); | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |                         } | 
					
						
							|  |  |  |                       else | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                           Q_EMIT self_->error ("Error creating UDP message"); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |                   // we don't care if this fails to read
 | 
					
						
							|  |  |  |                   in >> client_version >> client_revision; | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |               Q_EMIT self_->client_opened (client_key, QString::fromUtf8 (client_version), | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |                                            QString::fromUtf8 (client_revision)); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |           clients_[client_key].last_activity_ = QDateTime::currentDateTime (); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |           //
 | 
					
						
							|  |  |  |           // message format is described in NetworkMessage.hpp
 | 
					
						
							|  |  |  |           //
 | 
					
						
							|  |  |  |           switch (in.type ()) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |             case NetworkMessage::Heartbeat: | 
					
						
							|  |  |  |               //nothing to do here as time out handling deals with lifetime
 | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case NetworkMessage::Clear: | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |               Q_EMIT self_->decodes_cleared (client_key); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case NetworkMessage::Status: | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |               { | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |                 // unpack message
 | 
					
						
							|  |  |  |                 Frequency f; | 
					
						
							|  |  |  |                 QByteArray mode; | 
					
						
							|  |  |  |                 QByteArray dx_call; | 
					
						
							|  |  |  |                 QByteArray report; | 
					
						
							|  |  |  |                 QByteArray tx_mode; | 
					
						
							|  |  |  |                 bool tx_enabled {false}; | 
					
						
							|  |  |  |                 bool transmitting {false}; | 
					
						
							| 
									
										
										
										
											2015-11-13 15:44:11 +00:00
										 |  |  |                 bool decoding {false}; | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |                 quint32 rx_df {quint32_max}; | 
					
						
							|  |  |  |                 quint32 tx_df {quint32_max}; | 
					
						
							| 
									
										
										
										
											2016-05-24 10:08:35 +00:00
										 |  |  |                 QByteArray de_call; | 
					
						
							|  |  |  |                 QByteArray de_grid; | 
					
						
							|  |  |  |                 QByteArray dx_grid; | 
					
						
							| 
									
										
										
										
											2016-07-08 10:25:21 +00:00
										 |  |  |                 bool watchdog_timeout {false}; | 
					
						
							| 
									
										
										
										
											2016-12-16 19:36:21 +00:00
										 |  |  |                 QByteArray sub_mode; | 
					
						
							|  |  |  |                 bool fast_mode {false}; | 
					
						
							| 
									
										
										
										
											2018-12-02 23:19:08 +00:00
										 |  |  |                 quint8 special_op_mode {0}; | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |                 quint32 frequency_tolerance {quint32_max}; | 
					
						
							|  |  |  |                 quint32 tr_period {quint32_max}; | 
					
						
							| 
									
										
										
										
											2019-06-13 01:44:28 +01:00
										 |  |  |                 QByteArray configuration_name; | 
					
						
							| 
									
										
										
										
											2020-12-21 01:31:57 +00:00
										 |  |  |                 QByteArray tx_message; | 
					
						
							| 
									
										
										
										
											2016-05-24 10:08:35 +00:00
										 |  |  |                 in >> f >> mode >> dx_call >> report >> tx_mode >> tx_enabled >> transmitting >> decoding | 
					
						
							| 
									
										
										
										
											2016-12-16 19:36:21 +00:00
										 |  |  |                    >> rx_df >> tx_df >> de_call >> de_grid >> dx_grid >> watchdog_timeout >> sub_mode | 
					
						
							| 
									
										
										
										
											2020-12-21 01:31:57 +00:00
										 |  |  |                    >> fast_mode >> special_op_mode >> frequency_tolerance >> tr_period >> configuration_name | 
					
						
							|  |  |  |                    >> tx_message; | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |                 if (check_status (in) != Fail) | 
					
						
							|  |  |  |                   { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |                     Q_EMIT self_->status_update (client_key, f, QString::fromUtf8 (mode) | 
					
						
							|  |  |  |                                                  , QString::fromUtf8 (dx_call) | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |                                                  , QString::fromUtf8 (report), QString::fromUtf8 (tx_mode) | 
					
						
							| 
									
										
										
										
											2016-05-24 10:08:35 +00:00
										 |  |  |                                                  , tx_enabled, transmitting, decoding, rx_df, tx_df | 
					
						
							|  |  |  |                                                  , QString::fromUtf8 (de_call), QString::fromUtf8 (de_grid) | 
					
						
							| 
									
										
										
										
											2016-12-16 19:36:21 +00:00
										 |  |  |                                                  , QString::fromUtf8 (dx_grid), watchdog_timeout | 
					
						
							| 
									
										
										
										
											2018-12-02 23:19:08 +00:00
										 |  |  |                                                  , QString::fromUtf8 (sub_mode), fast_mode | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |                                                  , special_op_mode, frequency_tolerance, tr_period | 
					
						
							| 
									
										
										
										
											2020-12-21 01:31:57 +00:00
										 |  |  |                                                  , QString::fromUtf8 (configuration_name) | 
					
						
							|  |  |  |                                                  , QString::fromUtf8 (tx_message)); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |                   } | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |               } | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case NetworkMessage::Decode: | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |               { | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |                 // unpack message
 | 
					
						
							|  |  |  |                 bool is_new {true}; | 
					
						
							|  |  |  |                 QTime time; | 
					
						
							|  |  |  |                 qint32 snr; | 
					
						
							|  |  |  |                 float delta_time; | 
					
						
							|  |  |  |                 quint32 delta_frequency; | 
					
						
							|  |  |  |                 QByteArray mode; | 
					
						
							|  |  |  |                 QByteArray message; | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  |                 bool low_confidence {false}; | 
					
						
							|  |  |  |                 bool off_air {false}; | 
					
						
							| 
									
										
										
										
											2017-07-26 21:18:59 +00:00
										 |  |  |                 in >> is_new >> time >> snr >> delta_time >> delta_frequency >> mode | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  |                    >> message >> low_confidence >> off_air; | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |                 if (check_status (in) != Fail) | 
					
						
							|  |  |  |                   { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |                     Q_EMIT self_->decode (is_new, client_key, time, snr, delta_time, delta_frequency | 
					
						
							| 
									
										
										
										
											2017-07-26 21:18:59 +00:00
										 |  |  |                                           , QString::fromUtf8 (mode), QString::fromUtf8 (message) | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  |                                           , low_confidence, off_air); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |                   } | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |               } | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-15 23:03:11 +00:00
										 |  |  |             case NetworkMessage::WSPRDecode: | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 // unpack message
 | 
					
						
							|  |  |  |                 bool is_new {true}; | 
					
						
							|  |  |  |                 QTime time; | 
					
						
							|  |  |  |                 qint32 snr; | 
					
						
							|  |  |  |                 float delta_time; | 
					
						
							|  |  |  |                 Frequency frequency; | 
					
						
							|  |  |  |                 qint32 drift; | 
					
						
							|  |  |  |                 QByteArray callsign; | 
					
						
							|  |  |  |                 QByteArray grid; | 
					
						
							|  |  |  |                 qint32 power; | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  |                 bool off_air {false}; | 
					
						
							|  |  |  |                 in >> is_new >> time >> snr >> delta_time >> frequency >> drift >> callsign >> grid >> power | 
					
						
							|  |  |  |                    >> off_air; | 
					
						
							| 
									
										
										
										
											2015-11-15 23:03:11 +00:00
										 |  |  |                 if (check_status (in) != Fail) | 
					
						
							|  |  |  |                   { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |                     Q_EMIT self_->WSPR_decode (is_new, client_key, time, snr, delta_time, frequency, drift | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  |                                                , QString::fromUtf8 (callsign), QString::fromUtf8 (grid) | 
					
						
							|  |  |  |                                                , power, off_air); | 
					
						
							| 
									
										
										
										
											2015-11-15 23:03:11 +00:00
										 |  |  |                   } | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |             case NetworkMessage::QSOLogged: | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |               { | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  |                 QDateTime time_off; | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |                 QByteArray dx_call; | 
					
						
							|  |  |  |                 QByteArray dx_grid; | 
					
						
							|  |  |  |                 Frequency dial_frequency; | 
					
						
							|  |  |  |                 QByteArray mode; | 
					
						
							|  |  |  |                 QByteArray report_sent; | 
					
						
							|  |  |  |                 QByteArray report_received; | 
					
						
							|  |  |  |                 QByteArray tx_power; | 
					
						
							|  |  |  |                 QByteArray comments; | 
					
						
							|  |  |  |                 QByteArray name; | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  |                 QDateTime time_on; // Note: LOTW uses TIME_ON for their +/- 30-minute time window
 | 
					
						
							| 
									
										
										
										
											2018-01-25 21:57:21 +00:00
										 |  |  |                 QByteArray operator_call; | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  |                 QByteArray my_call; | 
					
						
							|  |  |  |                 QByteArray my_grid; | 
					
						
							| 
									
										
										
										
											2018-12-02 10:09:37 -05:00
										 |  |  |                 QByteArray exchange_sent; | 
					
						
							|  |  |  |                 QByteArray exchange_rcvd; | 
					
						
							| 
									
										
										
										
											2020-06-27 00:17:03 +02:00
										 |  |  |                 QByteArray prop_mode; | 
					
						
							| 
									
										
										
										
											2017-09-16 22:20:59 +00:00
										 |  |  |                 in >> time_off >> dx_call >> dx_grid >> dial_frequency >> mode >> report_sent >> report_received | 
					
						
							| 
									
										
										
										
											2018-12-02 10:09:37 -05:00
										 |  |  |                    >> tx_power >> comments >> name >> time_on >> operator_call >> my_call >> my_grid | 
					
						
							| 
									
										
										
										
											2020-06-27 00:17:03 +02:00
										 |  |  |                    >> exchange_sent >> exchange_rcvd >> prop_mode; | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |                 if (check_status (in) != Fail) | 
					
						
							|  |  |  |                   { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |                     Q_EMIT self_->qso_logged (client_key, time_off, QString::fromUtf8 (dx_call) | 
					
						
							|  |  |  |                                               , QString::fromUtf8 (dx_grid) | 
					
						
							|  |  |  |                                               , dial_frequency, QString::fromUtf8 (mode) | 
					
						
							|  |  |  |                                               , QString::fromUtf8 (report_sent) | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |                                               , QString::fromUtf8 (report_received), QString::fromUtf8 (tx_power) | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  |                                               , QString::fromUtf8 (comments), QString::fromUtf8 (name), time_on | 
					
						
							|  |  |  |                                               , QString::fromUtf8 (operator_call), QString::fromUtf8 (my_call) | 
					
						
							| 
									
										
										
										
											2018-12-02 10:09:37 -05:00
										 |  |  |                                               , QString::fromUtf8 (my_grid), QString::fromUtf8 (exchange_sent) | 
					
						
							| 
									
										
										
										
											2020-06-27 00:17:03 +02:00
										 |  |  |                                               , QString::fromUtf8 (exchange_rcvd), QString::fromUtf8 (prop_mode)); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |                   } | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |               } | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case NetworkMessage::Close: | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |               Q_EMIT self_->client_closed (client_key); | 
					
						
							|  |  |  |               clients_.remove (client_key); | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  |             case NetworkMessage::LoggedADIF: | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 QByteArray ADIF; | 
					
						
							|  |  |  |                 in >> ADIF; | 
					
						
							|  |  |  |                 if (check_status (in) != Fail) | 
					
						
							|  |  |  |                   { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |                     Q_EMIT self_->logged_ADIF (client_key, ADIF); | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  |                   } | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |             default: | 
					
						
							|  |  |  |               // Ignore
 | 
					
						
							|  |  |  |               break; | 
					
						
							| 
									
										
										
										
											2015-04-20 17:47:32 +00:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           Q_EMIT self_->error ("MessageServer warning: invalid UDP message received"); | 
					
						
							| 
									
										
										
										
											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 {"MessageServer exception: %1"}.arg (e.what ())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   catch (...) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       Q_EMIT self_->error ("Unexpected exception in MessageServer"); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MessageServer::impl::tick () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   auto now = QDateTime::currentDateTime (); | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |   auto iter = std::begin (clients_); | 
					
						
							|  |  |  |   while (iter != std::end (clients_)) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-04-15 19:24:41 +00:00
										 |  |  |       if (now > (*iter).last_activity_.addSecs (NetworkMessage::pulse)) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |           Q_EMIT self_->decodes_cleared (iter.key ()); | 
					
						
							| 
									
										
										
										
											2015-04-15 19:24:41 +00:00
										 |  |  |           Q_EMIT self_->client_closed (iter.key ()); | 
					
						
							| 
									
										
										
										
											2015-10-21 18:56:29 +00:00
										 |  |  |           iter = clients_.erase (iter); // safe while iterating as doesn't rehash
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           ++iter; | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-07 11:31:24 +00:00
										 |  |  | auto MessageServer::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
										 |  |  | MessageServer::MessageServer (QObject * parent, QString const& version, QString const& revision) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   : QObject {parent} | 
					
						
							| 
									
										
										
										
											2016-12-04 00:55:15 +00:00
										 |  |  |   , m_ {this, version, revision} | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  | void MessageServer::start (port_type port, QHostAddress const& multicast_group_address | 
					
						
							| 
									
										
										
										
											2020-11-03 20:31:11 +00:00
										 |  |  |                            , QSet<QString> const& network_interface_names) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-05 11:30:48 +00:00
										 |  |  |   // qDebug () << "MessageServer::start port:" << port << "multicast addr:" << multicast_group_address.toString () << "network interfaces:" << network_interface_names;
 | 
					
						
							| 
									
										
										
										
											2020-11-03 20:31:11 +00:00
										 |  |  |   if (port != m_->localPort () | 
					
						
							|  |  |  |       || multicast_group_address != m_->multicast_group_address_ | 
					
						
							|  |  |  |       || network_interface_names != m_->network_interfaces_) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       m_->leave_multicast_group (); | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  |       if (impl::UnconnectedState != m_->state ()) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |           m_->close (); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  |       if (!(multicast_group_address.isNull () || is_multicast_address (multicast_group_address))) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  |           Q_EMIT error ("Invalid multicast group address"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       else if (is_MAC_ambiguous_multicast_address (multicast_group_address)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           Q_EMIT error ("MAC-ambiguous IPv4 multicast group address not supported"); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-11-02 15:33:44 +00:00
										 |  |  |           m_->multicast_group_address_ = multicast_group_address; | 
					
						
							|  |  |  |           m_->network_interfaces_ = network_interface_names; | 
					
						
							|  |  |  |           QHostAddress local_addr {is_multicast_address (multicast_group_address) | 
					
						
							|  |  |  |                                    && impl::IPv4Protocol == multicast_group_address.protocol () ? QHostAddress::AnyIPv4 : QHostAddress::Any}; | 
					
						
							|  |  |  |           if (port && m_->bind (local_addr, port, m_->bind_mode_)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               m_->join_multicast_group (); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  | void MessageServer::clear_decodes (ClientKey const& key, quint8 window) | 
					
						
							| 
									
										
										
										
											2019-02-03 00:49:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |   auto iter = m_->clients_.find (key); | 
					
						
							| 
									
										
										
										
											2019-02-03 00:49:35 +00:00
										 |  |  |   if (iter != std::end (m_->clients_)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |       NetworkMessage::Builder out {&message, NetworkMessage::Clear, key.second, (*iter).negotiated_schema_number_}; | 
					
						
							| 
									
										
										
										
											2019-02-03 00:49:35 +00:00
										 |  |  |       out << window; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |       m_->send_message (out, message, key.first, (*iter).sender_port_); | 
					
						
							| 
									
										
										
										
											2019-02-03 00:49:35 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  | void MessageServer::reply (ClientKey const& key, QTime time, qint32 snr, float delta_time | 
					
						
							| 
									
										
										
										
											2017-09-22 15:36:24 +00:00
										 |  |  |                            , quint32 delta_frequency, QString const& mode | 
					
						
							|  |  |  |                            , QString const& message_text, bool low_confidence, quint8 modifiers) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |   auto iter = m_->clients_.find (key); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   if (iter != std::end (m_->clients_)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |       NetworkMessage::Builder out {&message, NetworkMessage::Reply, key.second, (*iter).negotiated_schema_number_}; | 
					
						
							| 
									
										
										
										
											2017-07-26 21:18:59 +00:00
										 |  |  |       out << time << snr << delta_time << delta_frequency << mode.toUtf8 () | 
					
						
							| 
									
										
										
										
											2017-09-22 15:36:24 +00:00
										 |  |  |           << message_text.toUtf8 () << low_confidence << modifiers; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |       m_->send_message (out, message, key.first, (*iter).sender_port_); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  | void MessageServer::replay (ClientKey const& key) | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |   auto iter = m_->clients_.find (key); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |   if (iter != std::end (m_->clients_)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |       NetworkMessage::Builder out {&message, NetworkMessage::Replay, key.second, (*iter).negotiated_schema_number_}; | 
					
						
							|  |  |  |       m_->send_message (out, message, key.first, (*iter).sender_port_); | 
					
						
							| 
									
										
										
										
											2015-04-15 16:40:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-05-06 20:30:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  | void MessageServer::close (ClientKey const& key) | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |   auto iter = m_->clients_.find (key); | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |   if (iter != std::end (m_->clients_)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |       NetworkMessage::Builder out {&message, NetworkMessage::Close, key.second, (*iter).negotiated_schema_number_}; | 
					
						
							|  |  |  |       m_->send_message (out, message, key.first, (*iter).sender_port_); | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  | void MessageServer::halt_tx (ClientKey const& key, bool auto_only) | 
					
						
							| 
									
										
										
										
											2015-05-06 20:30:29 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |   auto iter = m_->clients_.find (key); | 
					
						
							| 
									
										
										
										
											2015-05-06 20:30:29 +00:00
										 |  |  |   if (iter != std::end (m_->clients_)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |       NetworkMessage::Builder out {&message, NetworkMessage::HaltTx, key.second, (*iter).negotiated_schema_number_}; | 
					
						
							| 
									
										
										
										
											2015-05-06 22:25:56 +00:00
										 |  |  |       out << auto_only; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |       m_->send_message (out, message, key.first, (*iter).sender_port_); | 
					
						
							| 
									
										
										
										
											2015-05-06 20:30:29 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  | void MessageServer::free_text (ClientKey const& key, QString const& text, bool send) | 
					
						
							| 
									
										
										
										
											2015-05-06 20:30:29 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |   auto iter = m_->clients_.find (key); | 
					
						
							| 
									
										
										
										
											2015-05-06 20:30:29 +00:00
										 |  |  |   if (iter != std::end (m_->clients_)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QByteArray message; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |       NetworkMessage::Builder out {&message, NetworkMessage::FreeText, key.second, (*iter).negotiated_schema_number_}; | 
					
						
							| 
									
										
										
										
											2015-05-28 17:33:39 +00:00
										 |  |  |       out << text.toUtf8 () << send; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |       m_->send_message (out, message, key.first, (*iter).sender_port_); | 
					
						
							| 
									
										
										
										
											2015-05-06 20:30:29 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  | void MessageServer::location (ClientKey const& key, QString const& loc) | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |   auto iter = m_->clients_.find (key); | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  |   if (iter != std::end (m_->clients_)) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     QByteArray message; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |     NetworkMessage::Builder out {&message, NetworkMessage::Location, key.second, (*iter).negotiated_schema_number_}; | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  |     out << loc.toUtf8 (); | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |     m_->send_message (out, message, key.first, (*iter).sender_port_); | 
					
						
							| 
									
										
										
										
											2018-02-04 22:42:35 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-28 22:25:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  | void MessageServer::highlight_callsign (ClientKey const& key, QString const& callsign | 
					
						
							| 
									
										
										
										
											2018-03-28 22:25:46 +00:00
										 |  |  |                                         , QColor const& bg, QColor const& fg, bool last_only) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |   auto iter = m_->clients_.find (key); | 
					
						
							| 
									
										
										
										
											2018-03-28 22:25:46 +00:00
										 |  |  |   if (iter != std::end (m_->clients_)) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     QByteArray message; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |     NetworkMessage::Builder out {&message, NetworkMessage::HighlightCallsign, key.second, (*iter).negotiated_schema_number_}; | 
					
						
							| 
									
										
										
										
											2018-03-28 22:25:46 +00:00
										 |  |  |     out << callsign.toUtf8 () << bg << fg << last_only; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |     m_->send_message (out, message, key.first, (*iter).sender_port_); | 
					
						
							| 
									
										
										
										
											2018-03-28 22:25:46 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-06-13 01:44:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  | void MessageServer::switch_configuration (ClientKey const& key, QString const& configuration_name) | 
					
						
							| 
									
										
										
										
											2019-06-13 01:44:28 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |   auto iter = m_->clients_.find (key); | 
					
						
							| 
									
										
										
										
											2019-06-13 01:44:28 +01:00
										 |  |  |   if (iter != std::end (m_->clients_)) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     QByteArray message; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |     NetworkMessage::Builder out {&message, NetworkMessage::SwitchConfiguration, key.second, (*iter).negotiated_schema_number_}; | 
					
						
							| 
									
										
										
										
											2019-06-13 01:44:28 +01:00
										 |  |  |     out << configuration_name.toUtf8 (); | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |     m_->send_message (out, message, key.first, (*iter).sender_port_); | 
					
						
							| 
									
										
										
										
											2019-06-13 01:44:28 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  | void MessageServer::configure (ClientKey const& key, QString const& mode, quint32 frequency_tolerance | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |                                , QString const& submode, bool fast_mode, quint32 tr_period, quint32 rx_df | 
					
						
							|  |  |  |                                , QString const& dx_call, QString const& dx_grid, bool generate_messages) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |   auto iter = m_->clients_.find (key); | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |   if (iter != std::end (m_->clients_)) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     QByteArray message; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |     NetworkMessage::Builder out {&message, NetworkMessage::Configure, key.second, (*iter).negotiated_schema_number_}; | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |     out << mode.toUtf8 () << frequency_tolerance << submode.toUtf8 () << fast_mode << tr_period << rx_df | 
					
						
							|  |  |  |         << dx_call.toUtf8 () << dx_grid.toUtf8 () << generate_messages; | 
					
						
							| 
									
										
										
										
											2020-11-02 21:35:48 +00:00
										 |  |  |     m_->send_message (out, message, key.first, (*iter).sender_port_); | 
					
						
							| 
									
										
										
										
											2019-06-25 14:35:58 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | } |