First commit
This commit is contained in:
commit
1dee5e84ae
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
bin
|
||||
QBERcon.pro.user
|
19
QBERcon.pro
Normal file
19
QBERcon.pro
Normal file
@ -0,0 +1,19 @@
|
||||
QT += core widgets network
|
||||
|
||||
TARGET = QBERcon
|
||||
|
||||
TEMPLATE = app
|
||||
|
||||
INCLUDEPATH += src example
|
||||
|
||||
SOURCES += \
|
||||
example/main.cpp \
|
||||
example/examplegui.cpp \
|
||||
src/QBERcon.cpp
|
||||
|
||||
HEADERS += \
|
||||
example/examplegui.h \
|
||||
src/QBERcon.h
|
||||
|
||||
FORMS += \
|
||||
example/examplegui.ui
|
29
README.md
Normal file
29
README.md
Normal file
@ -0,0 +1,29 @@
|
||||
QBERcon - BattlEye Rcon connector for Qt5 C++
|
||||
=============================================
|
||||
|
||||
## Public functions:
|
||||
```c++
|
||||
void connectToServer(QString password, QString hostname, quint16 port = 2302);
|
||||
void disconnectFromServer();
|
||||
bool isConnected() const;
|
||||
void setKeepAliveInterval(int value); // In milliseconds. Default interval is 5 seconds
|
||||
quint8 sendCommand(QString cmd); // Send command and return command sequence number
|
||||
```
|
||||
|
||||
## Signals:
|
||||
```c++
|
||||
void messageReceived(QString &message); // Emitted when server broadcasts message
|
||||
void commandReceived(QString message, quint8 seqNumber); // Emitted when server replies command with sequence number
|
||||
void connected(); // Emitted after successful login
|
||||
void disconnected(); // Emitted after disconnect, timeout, etc.
|
||||
void error(QBERcon::RconError err); // Emitted when error thrown
|
||||
```
|
||||
|
||||
## Errors:
|
||||
```c++
|
||||
QBERcon::ERROR_LOGIN_FAILED // Wrong password
|
||||
QBERcon::ERROR_KEEPALIVE_EXCEEDED // Timeout
|
||||
QBERcon::ERROR_MISSING_LOGIN_DATA // No login/password specified
|
||||
```
|
||||
|
||||
Not fully tested. Use at your own risk.
|
85
example/examplegui.cpp
Normal file
85
example/examplegui.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
#include "examplegui.h"
|
||||
#include "ui_examplegui.h"
|
||||
|
||||
#define Q(x) #x
|
||||
#define QUOTE(x) Q(x)
|
||||
|
||||
ExampleGui::ExampleGui(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::ExampleGui) {
|
||||
ui->setupUi(this);
|
||||
be = new QBERcon::Client(this);
|
||||
|
||||
|
||||
#ifdef PASSWORD
|
||||
ui->passwordInput->setText(QUOTE(PASSWORD));
|
||||
#endif
|
||||
#ifdef SERVER_IP
|
||||
ui->hostInput->setText(QUOTE(SERVER_IP));
|
||||
#endif
|
||||
#ifdef SERVER_PORT
|
||||
ui->portInput->setValue(SERVER_PORT);
|
||||
#endif
|
||||
|
||||
|
||||
connect(be, SIGNAL(connected()), this, SLOT(connected()));
|
||||
connect(be, SIGNAL(disconnected()), this, SLOT(disconnected()));
|
||||
connect(be, SIGNAL(error(QBERcon::RconError)), this, SLOT(error(QBERcon::RconError)));
|
||||
connect(be, SIGNAL(messageReceived(QString&)), this, SLOT(messageReceived(QString&)));
|
||||
connect(be, SIGNAL(commandReceived(QString, quint8)), this, SLOT(commandReceived(QString, quint8)));
|
||||
}
|
||||
|
||||
ExampleGui::~ExampleGui() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
void ExampleGui::messageReceived(QString &message) {
|
||||
ui->logOutput->append(QString("<font color=\"#67983E\">[MSG]: %1</font>")
|
||||
.arg(message));
|
||||
qDebug() << __PRETTY_FUNCTION__ << message;
|
||||
}
|
||||
|
||||
void ExampleGui::commandReceived(QString message, quint8 seqNumber) {
|
||||
ui->logOutput->append(QString("<font color=\"#E19B3E\">[CMD ID=%1]: %2</font>")
|
||||
.arg(QString::number(seqNumber), message));
|
||||
qDebug() << __PRETTY_FUNCTION__ << "number =" << seqNumber << "Data:" << message;
|
||||
}
|
||||
|
||||
void ExampleGui::connected() {
|
||||
ui->logOutput->append(QString("<font color=\"#42B555\">[CONNECTED]</font>"));
|
||||
qDebug() << __PRETTY_FUNCTION__;
|
||||
}
|
||||
|
||||
void ExampleGui::disconnected() {
|
||||
ui->logOutput->append(QString("<font color=\"#D82672\">[DISCONNECTED]</font>"));
|
||||
qDebug() << __PRETTY_FUNCTION__;
|
||||
ui->connectButton->setEnabled(true);
|
||||
ui->disconnectButton->setEnabled(false);
|
||||
}
|
||||
|
||||
void ExampleGui::error(QBERcon::RconError err) {
|
||||
ui->logOutput->append(QString("<font color=\"#8E1717\">[ERR]: %1</font>")
|
||||
.arg(QString::number(err)));
|
||||
qDebug() << __PRETTY_FUNCTION__ << err;
|
||||
}
|
||||
|
||||
void ExampleGui::on_connectButton_clicked() {
|
||||
be->connectToServer(ui->passwordInput->text(), ui->hostInput->text(), ui->portInput->value());
|
||||
ui->connectButton->setEnabled(false);
|
||||
ui->disconnectButton->setEnabled(true);
|
||||
ui->commandButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void ExampleGui::on_disconnectButton_clicked() {
|
||||
be->disconnectFromServer();
|
||||
ui->connectButton->setEnabled(true);
|
||||
ui->disconnectButton->setEnabled(false);
|
||||
}
|
||||
|
||||
void ExampleGui::on_commandButton_clicked() {
|
||||
QString command = ui->commandInput->text();
|
||||
quint8 number = be->sendCommand(command);
|
||||
ui->logOutput->append(QString("<font color=\"#5D5815\">[CMD]: Sent %1 with ID=%2</font>")
|
||||
.arg(command, QString::number(number)));
|
||||
}
|
38
example/examplegui.h
Normal file
38
example/examplegui.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef EXAMPLEGUI_H
|
||||
#define EXAMPLEGUI_H
|
||||
|
||||
#include "QBERcon.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class ExampleGui;
|
||||
}
|
||||
|
||||
class ExampleGui : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExampleGui(QWidget *parent = 0);
|
||||
~ExampleGui();
|
||||
|
||||
|
||||
public slots:
|
||||
void messageReceived(QString &message);
|
||||
void commandReceived(QString message, quint8 seqNumber);
|
||||
void connected();
|
||||
void disconnected();
|
||||
void error(QBERcon::RconError err);
|
||||
|
||||
private slots:
|
||||
void on_connectButton_clicked();
|
||||
void on_disconnectButton_clicked();
|
||||
void on_commandButton_clicked();
|
||||
|
||||
private:
|
||||
QBERcon::Client *be;
|
||||
Ui::ExampleGui *ui;
|
||||
};
|
||||
|
||||
#endif // EXAMPLEGUI_H
|
99
example/examplegui.ui
Normal file
99
example/examplegui.ui
Normal file
@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ExampleGui</class>
|
||||
<widget class="QWidget" name="ExampleGui">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>RCON Test</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="disconnectButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Disconnect</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="connectButton">
|
||||
<property name="text">
|
||||
<string>Connect</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="portInput">
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>2302</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="passwordInput">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QPushButton" name="commandButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Command</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>IP/Host</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="hostInput"/>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QLineEdit" name="commandInput">
|
||||
<property name="text">
|
||||
<string>players</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QTextBrowser" name="logOutput"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
12
example/main.cpp
Normal file
12
example/main.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include <QApplication>
|
||||
#include <QTimer>
|
||||
#include <examplegui.h>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
ExampleGui *example = new ExampleGui();
|
||||
example->show();
|
||||
return a.exec();
|
||||
}
|
253
src/QBERcon.cpp
Normal file
253
src/QBERcon.cpp
Normal file
@ -0,0 +1,253 @@
|
||||
#include "QBERcon.h"
|
||||
#include <QDebug>
|
||||
|
||||
QBERcon::Client::Client(QObject *parent) : QObject(parent) {
|
||||
this->port = 2302;
|
||||
commandSequenceNumber = 0;
|
||||
keepAliveInterval = 5000;
|
||||
keepAliveTimer = new QTimer(this);
|
||||
socket = new QUdpSocket(this);
|
||||
|
||||
dns = new QDnsLookup();
|
||||
dns->setType(QDnsLookup::A);
|
||||
|
||||
connect(socket, SIGNAL(connected()), SLOT(socketConnected()));
|
||||
connect(socket, SIGNAL(disconnected()), SLOT(socketDisconnected()));
|
||||
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketError(QAbstractSocket::SocketError)));
|
||||
connect(socket, SIGNAL(readyRead()), SLOT(read()));
|
||||
connect(keepAliveTimer, SIGNAL(timeout()), this, SLOT(keepAliveTimerTimeout()));
|
||||
connect(dns, SIGNAL(finished()), this, SLOT(hostLookupFinished()));
|
||||
}
|
||||
|
||||
QBERcon::Client::~Client() {
|
||||
if(isConnected())
|
||||
disconnectFromServer();
|
||||
}
|
||||
|
||||
void QBERcon::Client::connectToServer(QString password, QString hostname, quint16 port) {
|
||||
if(hostname.isEmpty() || password.isEmpty()) {
|
||||
emit error(QBERcon::ERROR_MISSING_LOGIN_DATA);
|
||||
return;
|
||||
}
|
||||
this->hostname = hostname;
|
||||
this->port = port;
|
||||
this->password = password;
|
||||
|
||||
dns->setName(hostname);
|
||||
dns->lookup();
|
||||
}
|
||||
|
||||
void QBERcon::Client::hostLookupFinished() {
|
||||
if (dns->error() != QDnsLookup::NoError) {
|
||||
qDebug() << "DNS Lookup failed" << dns->error() << dns->errorString();
|
||||
return;
|
||||
}
|
||||
if(dns->hostAddressRecords().size() > 0) {
|
||||
host = dns->hostAddressRecords().first().value();
|
||||
qDebug() << "DNS Lookup OK:" << host;
|
||||
socket->connectToHost(host, port, QAbstractSocket::ReadWrite);
|
||||
} else {
|
||||
qDebug() << "DNS Lookup failed, no records";
|
||||
}
|
||||
}
|
||||
|
||||
void QBERcon::Client::keepAliveTimerTimeout() {
|
||||
if(keepAliveReceived) {
|
||||
keepAliveReceived = false;
|
||||
sendCommand("");
|
||||
} else {
|
||||
emit error(QBERcon::ERROR_KEEPALIVE_EXCEEDED);
|
||||
disconnectFromServer();
|
||||
}
|
||||
}
|
||||
|
||||
void QBERcon::Client::read() {
|
||||
QByteArray data;
|
||||
data.resize(socket->pendingDatagramSize());
|
||||
socket->readDatagram(data.data(), data.size());
|
||||
handleData(data);
|
||||
}
|
||||
|
||||
void QBERcon::Client::socketConnected() {
|
||||
commandSequenceNumber = 0;
|
||||
keepAliveReceived = true;
|
||||
keepAliveTimer->start(keepAliveInterval);
|
||||
sendPacket(QBERcon::PACKET_LOGIN);
|
||||
}
|
||||
|
||||
void QBERcon::Client::disconnectFromServer() {
|
||||
connectedToServer = false;
|
||||
keepAliveTimer->stop();
|
||||
socket->disconnectFromHost();
|
||||
}
|
||||
|
||||
quint8 QBERcon::Client::sendCommand(QString cmd) {
|
||||
if(!connectedToServer) return 0;
|
||||
sendPacket(QBERcon::PACKET_COMMAND, cmd);
|
||||
return commandSequenceNumber - 1;
|
||||
}
|
||||
|
||||
void QBERcon::Client::socketDisconnected() {
|
||||
connectedToServer = false;
|
||||
emit disconnected();
|
||||
}
|
||||
|
||||
void QBERcon::Client::socketError(QAbstractSocket::SocketError err) {
|
||||
qDebug() << "QAbstractSocket::SocketError:" << err;
|
||||
disconnectFromServer();
|
||||
}
|
||||
|
||||
void QBERcon::Client::addHeaderToPacket(QByteArray &dst) {
|
||||
QByteArray result;
|
||||
quint32 crc = qcrc32(dst);
|
||||
result.append("BE");
|
||||
for(int i = 0; i < 4; ++i) {
|
||||
result.append((quint8)((crc >> (i * 8)) & 0xFF));
|
||||
}
|
||||
result.append(dst);
|
||||
dst = result;
|
||||
|
||||
}
|
||||
|
||||
void QBERcon::Client::handleData(QByteArray &data) {
|
||||
if(!(data.size() > 7 && data.at(0) == 'B' && data.at(1) == 'E')) {
|
||||
qDebug() << "Not a BE packet, ignoring";
|
||||
return;
|
||||
}
|
||||
|
||||
quint32 crc_msg = 0;
|
||||
for(int i = 0; i < 4; ++i) {
|
||||
quint8 b = data.at(2 + i);
|
||||
crc_msg |= b << (i * 8);
|
||||
}
|
||||
|
||||
data.remove(0, 6); // cut header and keep payload
|
||||
|
||||
quint32 crc_computed = qcrc32(data);
|
||||
|
||||
if(crc_msg != crc_computed) {
|
||||
qDebug() << "Packet CRC missmatch, ignoring";
|
||||
return;
|
||||
}
|
||||
|
||||
quint8 packetType = data.at(1);
|
||||
//qDebug() << "Packet type" << packetType;
|
||||
|
||||
switch (packetType) {
|
||||
case QBERcon::PACKET_LOGIN: {
|
||||
quint8 result = data.at(2);
|
||||
if(result == 0x01) {
|
||||
connectedToServer = true;
|
||||
emit connected();
|
||||
} else {
|
||||
emit error(QBERcon::ERROR_LOGIN_FAILED);
|
||||
disconnectFromServer();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QBERcon::PACKET_COMMAND: {
|
||||
quint8 seqNumber = data.at(2);
|
||||
if(data.length() < 4) { // ACK
|
||||
keepAliveReceived = true;
|
||||
} else {
|
||||
// 3 4 5
|
||||
// 0x00 | number of packets for this response | 0-based index of the current packet
|
||||
if(data.at(3) == 0x00) { // multipart
|
||||
//qDebug() << "Multipart";
|
||||
quint8 messages_total = data.at(4);
|
||||
quint8 message_current = data.at(5);
|
||||
if(message_current == 0x00) {
|
||||
multipartMessageData.clear();
|
||||
}
|
||||
if(messages_total > message_current) {
|
||||
multipartMessageData.append(QString::fromUtf8(data.remove(0, 6)));
|
||||
if((messages_total - 1) == message_current) {
|
||||
emit commandReceived(multipartMessageData, seqNumber);
|
||||
multipartMessageData.clear();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QString msg = QString::fromUtf8(data.remove(0, 3));
|
||||
emit commandReceived(msg, seqNumber);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QBERcon::PACKET_MESSAGE: {
|
||||
quint8 ret = data.at(2);
|
||||
QString msg = QString::fromUtf8(data.remove(0, 3));
|
||||
emit messageReceived(msg);
|
||||
sendPacket(QBERcon::PACKET_MESSAGE, ret);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QBERcon::Client::sendPacket(QBERcon::PacketType type, QVariant data) {
|
||||
QByteArray p;
|
||||
p.append(0xFF);
|
||||
p.append(type);
|
||||
//qDebug() << "Sending packet type" << type;
|
||||
switch (type) {
|
||||
case QBERcon::PACKET_LOGIN:
|
||||
p.append(password);
|
||||
break;
|
||||
case QBERcon::PACKET_MESSAGE:
|
||||
p.append(data.toChar());
|
||||
break;
|
||||
case QBERcon::PACKET_COMMAND:
|
||||
p.append(commandSequenceNumber++);
|
||||
p.append(data.toByteArray());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
addHeaderToPacket(p);
|
||||
socket->writeDatagram(p, host, port);
|
||||
}
|
||||
|
||||
bool QBERcon::Client::isConnected() const {
|
||||
return connectedToServer;
|
||||
}
|
||||
|
||||
void QBERcon::Client::setKeepAliveInterval(int value) {
|
||||
keepAliveInterval = value;
|
||||
}
|
||||
|
||||
|
||||
// http://www.hackersdelight.org/hdcodetxt/crc.c.txt
|
||||
/* This is derived from crc32b but does table lookup. First the table
|
||||
itself is calculated, if it has not yet been set up.
|
||||
Not counting the table setup (which would probably be a separate
|
||||
function), when compiled to Cyclops with GCC, this function executes in
|
||||
7 + 13n instructions, where n is the number of bytes in the input
|
||||
message. It should be doable in 4 + 9n instructions. In any case, two
|
||||
of the 13 or 9 instrucions are load byte.
|
||||
This is Figure 14-7 in the text. */
|
||||
quint32 QBERcon::Client::qcrc32(QByteArray data) {
|
||||
int j;
|
||||
quint32 byte, crc, mask;
|
||||
static quint32 table[256];
|
||||
/* Set up the table, if necessary. */
|
||||
if (table[1] == 0) {
|
||||
for (byte = 0; byte <= 255; byte++) {
|
||||
crc = byte;
|
||||
for (j = 7; j >= 0; j--) { // Do eight times.
|
||||
mask = -(crc & 1);
|
||||
crc = (crc >> 1) ^ (0xEDB88320 & mask);
|
||||
}
|
||||
table[byte] = crc;
|
||||
}
|
||||
}
|
||||
/* Through with table setup, now calculate the CRC. */
|
||||
crc = 0xFFFFFFFF;
|
||||
QByteArray::Iterator it = data.begin();
|
||||
while (it != data.end()) {
|
||||
byte = *it;
|
||||
crc = (crc >> 8) ^ table[(crc ^ byte) & 0xFF];
|
||||
++it;
|
||||
}
|
||||
return ~crc;
|
||||
}
|
72
src/QBERcon.h
Normal file
72
src/QBERcon.h
Normal file
@ -0,0 +1,72 @@
|
||||
#ifndef QTBERCON_H
|
||||
#define QTBERCON_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QUdpSocket>
|
||||
#include <QDnsLookup> // QHostInfo::lookupHost slow for me some reason, so QT5
|
||||
|
||||
namespace QBERcon {
|
||||
enum PacketType {
|
||||
PACKET_LOGIN = 0x00,
|
||||
PACKET_COMMAND = 0x01,
|
||||
PACKET_MESSAGE = 0x02,
|
||||
};
|
||||
|
||||
enum RconError {
|
||||
ERROR_NONE = 0,
|
||||
ERROR_LOGIN_FAILED,
|
||||
ERROR_KEEPALIVE_EXCEEDED,
|
||||
ERROR_MISSING_LOGIN_DATA,
|
||||
};
|
||||
|
||||
|
||||
class Client : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Client(QObject *parent = 0);
|
||||
~Client();
|
||||
void connectToServer(QString password, QString hostname, quint16 port = 2302);
|
||||
void disconnectFromServer();
|
||||
quint8 sendCommand(QString cmd);
|
||||
bool isConnected() const;
|
||||
void setKeepAliveInterval(int value);
|
||||
|
||||
signals:
|
||||
void messageReceived(QString &message);
|
||||
void commandReceived(QString message, quint8 seqNumber);
|
||||
void connected();
|
||||
void disconnected();
|
||||
void error(QBERcon::RconError err);
|
||||
|
||||
public slots:
|
||||
void keepAliveTimerTimeout();
|
||||
void read();
|
||||
void socketConnected();
|
||||
void socketDisconnected();
|
||||
void socketError(QAbstractSocket::SocketError err);
|
||||
void hostLookupFinished();
|
||||
private:
|
||||
void addHeaderToPacket(QByteArray &dst);
|
||||
void handleData(QByteArray &data);
|
||||
void sendPacket(QBERcon::PacketType type, QVariant data = QVariant());
|
||||
quint32 qcrc32(QByteArray data);
|
||||
|
||||
QTimer *keepAliveTimer;
|
||||
QUdpSocket *socket;
|
||||
QDnsLookup *dns;
|
||||
|
||||
QString password;
|
||||
quint16 port;
|
||||
QString hostname;
|
||||
QHostAddress host;
|
||||
|
||||
quint8 commandSequenceNumber;
|
||||
bool connectedToServer;
|
||||
int keepAliveInterval;
|
||||
bool keepAliveReceived;
|
||||
QString multipartMessageData;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // QTBERCON_H
|
Loading…
x
Reference in New Issue
Block a user