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