1 #include "UDPSocket.h"
2
3 #include "Utils/Utils.h"
4 #include "Utils/Settings/Settings.h"
5 #include "Utils/Logger/Logger.h"
6 #include "Utils/Algorithm.h"
7
8 #include <QUdpSocket>
9 #include <QNetworkDatagram>
10 #include <QHostInfo>
11
12 struct RemoteUDPSocket::Private
13 {
14 QUdpSocket* socket=nullptr;
15 };
16
RemoteUDPSocket(QObject * parent)17 RemoteUDPSocket::RemoteUDPSocket(QObject* parent) :
18 QObject(parent)
19 {
20 m = Pimpl::make<Private>();
21
22 ListenSetting(Set::Remote_Active, RemoteUDPSocket::remoteSettingsChanged);
23 ListenSetting(Set::Remote_Discoverable, RemoteUDPSocket::remoteSettingsChanged);
24 }
25
26 RemoteUDPSocket::~RemoteUDPSocket() = default;
27
dataReceived()28 void RemoteUDPSocket::dataReceived()
29 {
30 auto* socket = static_cast<QUdpSocket*>(sender());
31
32 while(socket->hasPendingDatagrams())
33 {
34 const QNetworkDatagram datagram = socket->receiveDatagram(32);
35
36 const QHostAddress address = datagram.senderAddress();
37 int port = datagram.senderPort();
38
39 const QByteArray raw_data = datagram.data();
40 const QString data = QString::fromLocal8Bit(raw_data);
41 if(data.size() >= 10 && data.startsWith("sayrc01req"))
42 {
43 QStringList ips = Util::ipAddresses();
44 Util::Algorithm::sort(ips, [&address](const QString& ip1, const QString& ip2)
45 {
46 auto ip4addr = address.toIPv4Address();
47 auto ip4addr1 = QHostAddress(ip1).toIPv4Address();
48 auto ip4addr2 = QHostAddress(ip2).toIPv4Address();
49
50 decltype(ip4addr) diff1, diff2;
51 if(ip4addr < ip4addr1){
52 diff1 = ip4addr1 - ip4addr;
53 }
54
55 else {
56 diff1 = ip4addr - ip4addr1;
57 }
58
59 if(ip4addr < ip4addr2){
60 diff2 = ip4addr2 - ip4addr;
61 }
62
63 else {
64 diff2 = ip4addr - ip4addr2;
65 }
66
67 return (diff1 < diff2);
68 });
69
70 const QString ip_string = ips.join(",") + QString("@%1").arg(GetSetting(Set::Remote_Port)) ;
71 const QString public_id = GetSetting(Set::Player_PublicId);
72
73 const QString str = QString("sayrc01%1/%2/%3/%4")
74 .arg("ips")
75 .arg(public_id)
76 .arg(QHostInfo::localHostName())
77 .arg(ip_string);
78
79 socket->writeDatagram
80 (
81 str.toLocal8Bit(),
82 address,
83 quint16(port)
84 );
85 }
86
87 else
88 {
89 spLog(Log::Warning, this) << "Illegal remote control request " << data.size() << ": " << data << " raw data: " << raw_data;
90 }
91
92 spLog(Log::Info, this) << data << " from " << address.toString() << ":" << port;
93 }
94 }
95
remoteSettingsChanged()96 void RemoteUDPSocket::remoteSettingsChanged()
97 {
98 setActive(GetSetting(Set::Remote_Active) && GetSetting(Set::Remote_Discoverable));
99 }
100
setActive(bool b)101 void RemoteUDPSocket::setActive(bool b)
102 {
103 if(b)
104 {
105 if(m->socket) {
106 return;
107 }
108
109 m->socket = new QUdpSocket(this);
110 m->socket->bind(QHostAddress::Any, 54056);
111
112 connect(m->socket, &QUdpSocket::readyRead, this, &RemoteUDPSocket::dataReceived);
113 }
114
115 else
116 {
117 if(m->socket)
118 {
119 m->socket->close();
120 m->socket->deleteLater();
121 m->socket = nullptr;
122 }
123 }
124 }
125