fixed issue #42: make 'client deprecated' message work for v13 client <-> v14 server

This commit is contained in:
Max-Wilhelm Bruker 2012-05-09 23:13:23 +02:00
parent f7975d8ace
commit b9087715bf
7 changed files with 81 additions and 47 deletions

View file

@ -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) {
messageLength = (((quint32) (unsigned char) inputBuffer[0]) << 24) // dirty hack to be compatible with v14 server that sends 60 bytes of garbage at the beginning
+ (((quint32) (unsigned char) inputBuffer[1]) << 16) if (!handshakeStarted) {
+ (((quint32) (unsigned char) inputBuffer[2]) << 8) handshakeStarted = true;
+ ((quint32) (unsigned char) inputBuffer[3]); if (inputBuffer.startsWith("<?xm")) {
inputBuffer.remove(0, 4); messageInProgress = true;
messageInProgress = true; messageLength = 60;
}
} else {
// end of hack
messageLength = (((quint32) (unsigned char) inputBuffer[0]) << 24)
+ (((quint32) (unsigned char) inputBuffer[1]) << 16)
+ (((quint32) (unsigned char) inputBuffer[2]) << 8)
+ ((quint32) (unsigned char) inputBuffer[3]);
inputBuffer.remove(0, 4);
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)

View file

@ -33,6 +33,7 @@ private:
QByteArray inputBuffer; QByteArray inputBuffer;
bool messageInProgress; bool messageInProgress;
bool handshakeStarted;
int messageLength; int messageLength;
QTimer *timer; QTimer *timer;

View file

@ -1,4 +0,0 @@
[Dolphin]
Timestamp=2012,3,4,11,22,24
Version=2
ViewMode=1

View file

@ -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;

View file

@ -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();
} }
} }

View file

@ -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;
processCommandContainer(newCommandContainer); // dirty hack to make v13 client display the correct error message
if (handshakeStarted)
processCommandContainer(newCommandContainer);
else if (!newCommandContainer.has_cmd_id()) {
handshakeStarted = true;
if (!initSession())
prepareDestroy();
}
// end of hack
} while (!inputBuffer.isEmpty()); } while (!inputBuffer.isEmpty());
} }

View file

@ -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(); }