diff options
Diffstat (limited to 'src/UdpTasks/StatusChecker/oncheckerresponseread.cpp')
| -rw-r--r-- | src/UdpTasks/StatusChecker/oncheckerresponseread.cpp | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/UdpTasks/StatusChecker/oncheckerresponseread.cpp b/src/UdpTasks/StatusChecker/oncheckerresponseread.cpp new file mode 100644 index 0000000..098058a --- /dev/null +++ b/src/UdpTasks/StatusChecker/oncheckerresponseread.cpp @@ -0,0 +1,112 @@ +#include "statuschecker.h" + +void StatusChecker::onUdpResponseRead() +{ + // read now called, reset workaround counter + _missedReadCalls = 0; + + while ( _udpSocket.hasPendingDatagrams() ) + { + // get sender and payload + QNetworkDatagram datagram = _udpSocket.receiveDatagram(); + QString senderAddress = QHostAddress( datagram.senderAddress().toIPv4Address() ).toString(); + unsigned short senderPort = datagram.senderPort(); + QString receiveBuffer = datagram.data(); + receiveBuffer = receiveBuffer.toLatin1(); + + // shorthand label + QString senderAddressLabel = QStringLiteral("%1:%2").arg(senderAddress, QString::number(senderPort)); + _coreObject->Log.logEvent("udp", QStringLiteral("%1 sent '%2'").arg(senderAddressLabel, receiveBuffer ) ); + + // ignore empty data packets (query port forwarded to a game port) + if (receiveBuffer.length() <= 0) + continue; + + // determine protocol and response based on the first character (backslash, byte value, ... ) + unsigned short protocol_chooser = receiveBuffer.at(0).unicode(); + if (protocol_chooser != 92) + continue; + + // buffer complete? else wait for data to be complete + _dataBuffer[senderAddressLabel] += receiveBuffer; + + // status response or validate response? (either status or secure, not both) + if ( receiveBuffer.contains("\\validate\\") ) + { + // parse key/value pairs and QHash label + QMultiHash<QString, QString> receiveData = parseGameSpy0Buffer(_dataBuffer[senderAddressLabel]); + + // load existing information + QString secure = _secureBuffer.value(senderAddressLabel).secure; + QString gamename = _secureBuffer.value(senderAddressLabel).gamename; + + // if entry, secure, gamename and/or cipher do not exist, AuthResult will be false+invalid + AuthResult authResult = validateGamename(false, // this is not a beacon + gamename, + receiveData.value("validate",""), + _coreObject->SupportedGames.value(gamename).cipher, + secure, + receiveData.value("enctype", "0").toInt() ); + + // compare with received response + if ( authResult.auth ) + { + // server authenticated - log and add to database + _coreObject->Log.logEvent("secure", QStringLiteral("successful validate from %1 for %2") + .arg(senderAddressLabel, gamename)); + + // update the existing entry + updateServer(senderAddress, senderPort, gamename, false, true); + + // remove from secure buffer + _secureBuffer.remove(senderAddressLabel); + } + else // log failed validate + { + // set validate false (but update last response time) + updateServer(senderAddress, senderPort, gamename, false, false); + _coreObject->Log.logEvent("secure", QStringLiteral("failed validate from %1 for %2") + .arg(senderAddressLabel, gamename)); + _coreObject->Log.logEvent("secure", QStringLiteral("secure: '%1', gamename: '%2', validate: '%3', expected: '%4'") + .arg(secure, gamename, receiveData.value("validate", "null"), authResult.validate )); + } + + // clear receive buffer + _dataBuffer.remove(senderAddressLabel); + + // there should be no further data (ignore) + continue; + } + + // all status query data received? + if (receiveBuffer.contains("\\final\\")) + { + + // parse key/value pairs and QHash label + QMultiHash<QString, QString> receiveData = parseGameSpy0Buffer(_dataBuffer[senderAddressLabel]); + + // update or insert primary details + if ( ! updateServer(senderAddress, senderPort, receiveData.value("gamename", "unknown"), false, false) ) + { + // add to database + insertServer(senderAddress, senderPort, receiveData.value("gamename", "unknown"), false); + } + + // then update detailed information + if ( ! updateServerInfo(senderAddress, senderPort, receiveData) ) + { + // insert and update new entry (this does NOT insert to the serverlist, only info) + // this assumes that an entry with this ip/port exists in the serverlist (fails silently) + insertServerInfo(senderAddress, senderPort); + updateServerInfo(senderAddress, senderPort, receiveData); + } + + // update player info (removes old playerdata entries) + insertPlayerInfo(senderAddress, senderPort, receiveData); + + // clear receive buffer + _dataBuffer.remove(senderAddressLabel); + + } // if final + } +} |
