1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
#include "syncclient.h"
void SyncClient::onSyncRead()
{
// reset timeout after receiving (any) data
_timeOut.start();
// read from tcp connection and append to buffer
QByteArray receiveBuffer = _tcpSocket.readAll();
_rxBuffer.append( receiveBuffer );
// prevent large heaps of text -- log only relevant message, not masterserver data
if ( receiveBuffer.length() > 30 )
{
// log size of data
_coreObject->Log.logEvent("tcp", QStringLiteral("%1 sent %2 characters")
.arg(_clientLabel, QString::number(receiveBuffer.length()) ) );
}
else
{
// log message
_coreObject->Log.logEvent("tcp", QStringLiteral("%1 sent '%2'")
.arg(_clientLabel, receiveBuffer.data()) );
}
// remote masterserver opens with secure challenge
if ( _rxBuffer.contains("secure") )
{
// parse to hash
QMultiHash<QString, QString> receiveData = parseGameSpy0Buffer(_rxBuffer.toLatin1());
// generate response
QStringList response = replyQuery(receiveData);
// return response
_tcpSocket.write(response.join("").toLatin1());
// sync request
QString request = QStringLiteral("\\sync\\%1\\msid\\%2")
.arg(_coreObject->Settings.SyncerSettings.syncGames,
_coreObject->masterserverIdentity);
_tcpSocket.write(request.toLatin1());
// all relevant information received. clear buffer for next interaction
_rxBuffer = "";
return;
}
if ( _rxBuffer.contains("final") )
{
// parse to hash: receivedData format is {gamename} => {string of addresses}
QMultiHash<QString, QString> receiveData = parseGameSpy0Buffer(_rxBuffer.toLatin1());
receiveData.remove("final"); // prevent "final" from registering as gamename
// count number of addresses for logging
int totalServerCount = 0;
// use transaction for SQLite
QSqlDatabase::database().transaction();
// parse to list of list of <ServerInfo>
QHashIterator<QString,QString> receiveDataIterator(receiveData);
while ( receiveDataIterator.hasNext() )
{
// {gamename} => {string of addresses}
receiveDataIterator.next();
QString gamename = receiveDataIterator.key();
QString addressBufferList = receiveDataIterator.value();
// split address list in single addresses
QStringListIterator listIterator( addressBufferList.split(" ", QString::SkipEmptyParts) );
while ( listIterator.hasNext() )
{
// address (ip:port)
QString addr = listIterator.next();
// older Qt5 masterservers sync in ::ffff:127.0.0.1 format, trim the '::ffff:'
addr.remove("::ffff:");
// (address cont.)
QStringList address = addr.split(':');
unsigned short remotePort = address.takeLast().toUShort();
QString remoteAddr = address.join(":"); // IPv4 has only 1 element, IPv6 has 4 that need joining with ':'
// valid address?
if ( ! QHostAddress(remoteAddr).isNull() and remotePort > 0 )
{
// if it does not exist in the db, insert
if ( ! updateSyncedServer(remoteAddr, remotePort) )
{
// add
insertServer(remoteAddr, remotePort, gamename, false);
}
}
totalServerCount++;
} // has next address
} // has next game
// commit SQLite
QSqlDatabase::database().commit();
// report in log
_coreObject->Log.logEvent("sync", QStringLiteral("received %1 servers in %2 games from %3")
.arg( QString::number(totalServerCount),
QString::number(receiveData.count()),
_clientLabel)
);
} // if final
// else keep appending data until \\final\\ is received
}
|