fixed issue #42: make 'client deprecated' message work for v13 client <-> v14 server
This commit is contained in:
parent
f7975d8ace
commit
b9087715bf
7 changed files with 81 additions and 47 deletions
|
@ -9,10 +9,10 @@
|
||||||
#include "pb/server_message.pb.h"
|
#include "pb/server_message.pb.h"
|
||||||
#include "pb/event_server_identification.pb.h"
|
#include "pb/event_server_identification.pb.h"
|
||||||
|
|
||||||
static const unsigned int protocolVersion = 13;
|
static const unsigned int protocolVersion = 14;
|
||||||
|
|
||||||
RemoteClient::RemoteClient(QObject *parent)
|
RemoteClient::RemoteClient(QObject *parent)
|
||||||
: AbstractClient(parent), timeRunning(0), lastDataReceived(0), messageInProgress(false), messageLength(0)
|
: AbstractClient(parent), timeRunning(0), lastDataReceived(0), messageInProgress(false), handshakeStarted(false), messageLength(0)
|
||||||
{
|
{
|
||||||
timer = new QTimer(this);
|
timer = new QTimer(this);
|
||||||
timer->setInterval(1000);
|
timer->setInterval(1000);
|
||||||
|
@ -47,6 +47,11 @@ void RemoteClient::slotConnected()
|
||||||
{
|
{
|
||||||
timeRunning = lastDataReceived = 0;
|
timeRunning = lastDataReceived = 0;
|
||||||
timer->start();
|
timer->start();
|
||||||
|
|
||||||
|
// dirty hack to be compatible with v14 server
|
||||||
|
sendCommandContainer(CommandContainer());
|
||||||
|
// end of hack
|
||||||
|
|
||||||
setStatus(StatusAwaitingWelcome);
|
setStatus(StatusAwaitingWelcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +59,7 @@ void RemoteClient::processServerIdentificationEvent(const Event_ServerIdentifica
|
||||||
{
|
{
|
||||||
if (event.protocol_version() != protocolVersion) {
|
if (event.protocol_version() != protocolVersion) {
|
||||||
emit protocolVersionMismatch(protocolVersion, event.protocol_version());
|
emit protocolVersionMismatch(protocolVersion, event.protocol_version());
|
||||||
setStatus(StatusDisconnected);
|
setStatus(StatusDisconnecting);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setStatus(StatusLoggingIn);
|
setStatus(StatusLoggingIn);
|
||||||
|
@ -105,12 +110,22 @@ void RemoteClient::readData()
|
||||||
do {
|
do {
|
||||||
if (!messageInProgress) {
|
if (!messageInProgress) {
|
||||||
if (inputBuffer.size() >= 4) {
|
if (inputBuffer.size() >= 4) {
|
||||||
|
// dirty hack to be compatible with v14 server that sends 60 bytes of garbage at the beginning
|
||||||
|
if (!handshakeStarted) {
|
||||||
|
handshakeStarted = true;
|
||||||
|
if (inputBuffer.startsWith("<?xm")) {
|
||||||
|
messageInProgress = true;
|
||||||
|
messageLength = 60;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// end of hack
|
||||||
messageLength = (((quint32) (unsigned char) inputBuffer[0]) << 24)
|
messageLength = (((quint32) (unsigned char) inputBuffer[0]) << 24)
|
||||||
+ (((quint32) (unsigned char) inputBuffer[1]) << 16)
|
+ (((quint32) (unsigned char) inputBuffer[1]) << 16)
|
||||||
+ (((quint32) (unsigned char) inputBuffer[2]) << 8)
|
+ (((quint32) (unsigned char) inputBuffer[2]) << 8)
|
||||||
+ ((quint32) (unsigned char) inputBuffer[3]);
|
+ ((quint32) (unsigned char) inputBuffer[3]);
|
||||||
inputBuffer.remove(0, 4);
|
inputBuffer.remove(0, 4);
|
||||||
messageInProgress = true;
|
messageInProgress = true;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -126,10 +141,10 @@ void RemoteClient::readData()
|
||||||
messageInProgress = false;
|
messageInProgress = false;
|
||||||
|
|
||||||
processProtocolItem(newServerMessage);
|
processProtocolItem(newServerMessage);
|
||||||
} while (!inputBuffer.isEmpty());
|
|
||||||
|
|
||||||
if (getStatus() == StatusDisconnecting) // use thread-safe getter
|
if (getStatus() == StatusDisconnecting) // use thread-safe getter
|
||||||
doDisconnectFromServer();
|
doDisconnectFromServer();
|
||||||
|
} while (!inputBuffer.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteClient::sendCommandContainer(const CommandContainer &cont)
|
void RemoteClient::sendCommandContainer(const CommandContainer &cont)
|
||||||
|
|
|
@ -33,6 +33,7 @@ private:
|
||||||
|
|
||||||
QByteArray inputBuffer;
|
QByteArray inputBuffer;
|
||||||
bool messageInProgress;
|
bool messageInProgress;
|
||||||
|
bool handshakeStarted;
|
||||||
int messageLength;
|
int messageLength;
|
||||||
|
|
||||||
QTimer *timer;
|
QTimer *timer;
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
[Dolphin]
|
|
||||||
Timestamp=2012,3,4,11,22,24
|
|
||||||
Version=2
|
|
||||||
ViewMode=1
|
|
|
@ -5,7 +5,7 @@ import "moderator_commands.proto";
|
||||||
import "admin_commands.proto";
|
import "admin_commands.proto";
|
||||||
|
|
||||||
message CommandContainer {
|
message CommandContainer {
|
||||||
required uint64 cmd_id = 1;
|
optional uint64 cmd_id = 1;
|
||||||
|
|
||||||
optional uint32 game_id = 10;
|
optional uint32 game_id = 10;
|
||||||
optional uint32 room_id = 20;
|
optional uint32 room_id = 20;
|
||||||
|
|
|
@ -43,10 +43,11 @@ void Servatrice_GameServer::incomingConnection(int socketDescriptor)
|
||||||
sst->start();
|
sst->start();
|
||||||
} else {
|
} else {
|
||||||
QTcpSocket *socket = new QTcpSocket;
|
QTcpSocket *socket = new QTcpSocket;
|
||||||
|
ServerSocketInterface *ssi = new ServerSocketInterface(server, socket);
|
||||||
socket->setSocketDescriptor(socketDescriptor);
|
socket->setSocketDescriptor(socketDescriptor);
|
||||||
socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
|
socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
|
||||||
ServerSocketInterface *ssi = new ServerSocketInterface(server, socket);
|
|
||||||
logger->logMessage(QString("incoming connection: %1").arg(socket->peerAddress().toString()), ssi);
|
logger->logMessage(QString("incoming connection: %1").arg(socket->peerAddress().toString()), ssi);
|
||||||
|
ssi->initSessionDeprecated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,40 +57,14 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
static const int protocolVersion = 13;
|
static const int protocolVersion = 14;
|
||||||
|
|
||||||
ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent)
|
ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent)
|
||||||
: Server_ProtocolHandler(_server, parent), servatrice(_server), socket(_socket), messageInProgress(false)
|
: Server_ProtocolHandler(_server, parent), servatrice(_server), socket(_socket), messageInProgress(false), handshakeStarted(false)
|
||||||
{
|
{
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
connect(socket, SIGNAL(readyRead()), this, SLOT(readClient()));
|
connect(socket, SIGNAL(readyRead()), this, SLOT(readClient()));
|
||||||
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(catchSocketError(QAbstractSocket::SocketError)));
|
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(catchSocketError(QAbstractSocket::SocketError)));
|
||||||
connect(this, SIGNAL(outputBufferChanged()), this, SLOT(flushOutputBuffer()), Qt::QueuedConnection);
|
connect(this, SIGNAL(outputBufferChanged()), this, SLOT(flushOutputBuffer()), Qt::QueuedConnection);
|
||||||
|
|
||||||
Event_ServerIdentification identEvent;
|
|
||||||
identEvent.set_server_name(servatrice->getServerName().toStdString());
|
|
||||||
identEvent.set_server_version(VERSION_STRING);
|
|
||||||
identEvent.set_protocol_version(protocolVersion);
|
|
||||||
SessionEvent *identSe = prepareSessionEvent(identEvent);
|
|
||||||
sendProtocolItem(*identSe);
|
|
||||||
delete identSe;
|
|
||||||
|
|
||||||
int maxUsers = _server->getMaxUsersPerAddress();
|
|
||||||
if ((maxUsers > 0) && (_server->getUsersWithAddress(socket->peerAddress()) >= maxUsers)) {
|
|
||||||
Event_ConnectionClosed event;
|
|
||||||
event.set_reason(Event_ConnectionClosed::TOO_MANY_CONNECTIONS);
|
|
||||||
SessionEvent *se = prepareSessionEvent(event);
|
|
||||||
sendProtocolItem(*se);
|
|
||||||
delete se;
|
|
||||||
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
server->addClient(this);
|
|
||||||
|
|
||||||
if (!success)
|
|
||||||
prepareDestroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerSocketInterface::~ServerSocketInterface()
|
ServerSocketInterface::~ServerSocketInterface()
|
||||||
|
@ -102,6 +76,42 @@ ServerSocketInterface::~ServerSocketInterface()
|
||||||
socket = 0;
|
socket = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerSocketInterface::initSessionDeprecated()
|
||||||
|
{
|
||||||
|
// dirty hack to make v13 client display the correct error message
|
||||||
|
|
||||||
|
outputBufferMutex.lock();
|
||||||
|
outputBuffer = "<?xml version=\"1.0\"?><cockatrice_server_stream version=\"14\">";
|
||||||
|
outputBufferMutex.unlock();
|
||||||
|
|
||||||
|
emit outputBufferChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ServerSocketInterface::initSession()
|
||||||
|
{
|
||||||
|
Event_ServerIdentification identEvent;
|
||||||
|
identEvent.set_server_name(servatrice->getServerName().toStdString());
|
||||||
|
identEvent.set_server_version(VERSION_STRING);
|
||||||
|
identEvent.set_protocol_version(protocolVersion);
|
||||||
|
SessionEvent *identSe = prepareSessionEvent(identEvent);
|
||||||
|
sendProtocolItem(*identSe);
|
||||||
|
delete identSe;
|
||||||
|
|
||||||
|
int maxUsers = servatrice->getMaxUsersPerAddress();
|
||||||
|
if ((maxUsers > 0) && (servatrice->getUsersWithAddress(socket->peerAddress()) >= maxUsers)) {
|
||||||
|
Event_ConnectionClosed event;
|
||||||
|
event.set_reason(Event_ConnectionClosed::TOO_MANY_CONNECTIONS);
|
||||||
|
SessionEvent *se = prepareSessionEvent(event);
|
||||||
|
sendProtocolItem(*se);
|
||||||
|
delete se;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
server->addClient(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void ServerSocketInterface::flushOutputBuffer()
|
void ServerSocketInterface::flushOutputBuffer()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&outputBufferMutex);
|
QMutexLocker locker(&outputBufferMutex);
|
||||||
|
@ -139,7 +149,15 @@ void ServerSocketInterface::readClient()
|
||||||
inputBuffer.remove(0, messageLength);
|
inputBuffer.remove(0, messageLength);
|
||||||
messageInProgress = false;
|
messageInProgress = false;
|
||||||
|
|
||||||
|
// dirty hack to make v13 client display the correct error message
|
||||||
|
if (handshakeStarted)
|
||||||
processCommandContainer(newCommandContainer);
|
processCommandContainer(newCommandContainer);
|
||||||
|
else if (!newCommandContainer.has_cmd_id()) {
|
||||||
|
handshakeStarted = true;
|
||||||
|
if (!initSession())
|
||||||
|
prepareDestroy();
|
||||||
|
}
|
||||||
|
// end of hack
|
||||||
} while (!inputBuffer.isEmpty());
|
} while (!inputBuffer.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ private:
|
||||||
|
|
||||||
QByteArray inputBuffer, outputBuffer;
|
QByteArray inputBuffer, outputBuffer;
|
||||||
bool messageInProgress;
|
bool messageInProgress;
|
||||||
|
bool handshakeStarted;
|
||||||
int messageLength;
|
int messageLength;
|
||||||
|
|
||||||
Response::ResponseCode cmdAddToList(const Command_AddToList &cmd, ResponseContainer &rc);
|
Response::ResponseCode cmdAddToList(const Command_AddToList &cmd, ResponseContainer &rc);
|
||||||
|
@ -92,6 +93,8 @@ private:
|
||||||
public:
|
public:
|
||||||
ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent = 0);
|
ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent = 0);
|
||||||
~ServerSocketInterface();
|
~ServerSocketInterface();
|
||||||
|
void initSessionDeprecated();
|
||||||
|
bool initSession();
|
||||||
QHostAddress getPeerAddress() const { return socket->peerAddress(); }
|
QHostAddress getPeerAddress() const { return socket->peerAddress(); }
|
||||||
QString getAddress() const { return socket->peerAddress().toString(); }
|
QString getAddress() const { return socket->peerAddress().toString(); }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue