Merge pull request #1344 from woogerboy21/clientid_commit_res

Commit to resolve requests made by @Daenyth discussed after the commit.
This commit is contained in:
woogerboy21 2015-08-08 09:23:21 -04:00
commit c64bc3fb81
10 changed files with 109 additions and 94 deletions

View file

@ -35,7 +35,6 @@
#include "QtNetwork/QNetworkInterface"
#include <QCryptographicHash>
#include "main.h"
#include "window_main.h"
#include "dlg_settings.h"
@ -100,7 +99,7 @@ bool settingsValid()
!settingsCache->getPicsPath().isEmpty();
}
void generateClientID()
QString const generateClientID()
{
QString macList;
foreach(QNetworkInterface interface, QNetworkInterface::allInterfaces())
@ -110,7 +109,7 @@ void generateClientID()
macList += interface.hardwareAddress() + ".";
}
QString strClientID = QCryptographicHash::hash(macList.toUtf8(), QCryptographicHash::Sha1).toHex().right(15);
settingsCache->setClientID(strClientID);
return strClientID;
}
int main(int argc, char *argv[])
@ -220,7 +219,7 @@ int main(int argc, char *argv[])
QIcon icon(":/resources/appicon.svg");
ui.setWindowIcon(icon);
generateClientID(); //generate the users client id
settingsCache->setClientID(generateClientID());
qDebug() << "ClientID In Cache: " << settingsCache->getClientID();
ui.showMaximized();

View file

@ -7,14 +7,14 @@ class QSystemTrayIcon;
class SoundEngine;
extern CardDatabase *db;
extern QSystemTrayIcon *trayIcon;
extern QTranslator *translator;
extern const QString translationPrefix;
extern QString translationPath;
void installNewTranslator();
void generateClientID();
QString const generateClientID();
bool settingsValid();

View file

@ -316,6 +316,9 @@ void MainWindow::loginError(Response::ResponseCode r, QString reasonStr, quint32
actRegister();
}
break;
case Response::RespClientIdRequired:
QMessageBox::critical(this, tr("Error"), tr("This server requires client ID's. Your client is either failing to generate an ID or you are running a modified client.\nPlease close and reopen your client to try again."));
break;
case Response::RespAccountNotActivated: {
bool ok = false;
QString token = QInputDialog::getText(this, tr("Account activation"), tr("Your account has not been activated yet.\nYou need to provide the activation token received in the activation email"), QLineEdit::Normal, QString(), &ok);

View file

@ -35,7 +35,7 @@ message Response {
RespActivationAccepted = 31; // Server accepted a reg user activation token
RespActivationFailed = 32; // Server didn't accept a reg user activation token
RespRegistrationAcceptedNeedsActivation = 33; // Server accepted cient registration, but it will need token activation
RespClientIDRequired = 34; // Server require's client to generate and send its client id before allowing access
RespClientIdRequired = 34; // Server requires client to generate and send its client id before allowing access
}
enum ResponseType {
JOIN_ROOM = 1000;

View file

@ -170,9 +170,10 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString
event.mutable_user_info()->CopyFrom(session->copyUserInfo(true, true, true));
locker.unlock();
// check if client id exists (older client compatibility)
if (clientid.isEmpty()){
// client id is empty, either out dated client or client has been modified
if (getClientIdRequired())
return ClientIdRequired;
}
else {
// update users database table with client id

View file

@ -28,7 +28,7 @@ class GameEventContainer;
class CommandContainer;
class Command_JoinGame;
enum AuthenticationResult { NotLoggedIn, PasswordRight, UnknownUser, WouldOverwriteOldSession, UserIsBanned, UsernameInvalid, RegistrationRequired, UserIsInactive };
enum AuthenticationResult { NotLoggedIn, PasswordRight, UnknownUser, WouldOverwriteOldSession, UserIsBanned, UsernameInvalid, RegistrationRequired, UserIsInactive, ClientIdRequired };
class Server : public QObject
{
@ -56,6 +56,7 @@ public:
virtual QString getLoginMessage() const { return QString(); }
virtual bool getGameShouldPing() const { return false; }
virtual bool getClientIdRequired() const { return false; }
virtual int getPingClockInterval() const { return 0; }
virtual int getMaxGameInactivityTime() const { return 9999999; }
virtual int getMaxPlayerInactivityTime() const { return 9999999; }

View file

@ -381,12 +381,16 @@ Response::ResponseCode Server_ProtocolHandler::cmdPing(const Command_Ping & /*cm
Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd, ResponseContainer &rc)
{
QString userName = QString::fromStdString(cmd.user_name()).simplified();
QString clientid = QString::fromStdString(cmd.clientid()).simplified();
QString clientId = QString::fromStdString(cmd.clientid()).simplified();
if (userName.isEmpty() || (userInfo != 0))
return Response::RespContextError;
if (clientId.isEmpty())
return Response::RespContextError;
QString reasonStr;
int banSecondsLeft = 0;
AuthenticationResult res = server->loginUser(this, userName, QString::fromStdString(cmd.password()), reasonStr, banSecondsLeft, clientid);
AuthenticationResult res = server->loginUser(this, userName, QString::fromStdString(cmd.password()), reasonStr, banSecondsLeft, clientId);
switch (res) {
case UserIsBanned: {
Response_Login *re = new Response_Login;
@ -405,6 +409,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
return Response::RespUsernameInvalid;
}
case RegistrationRequired: return Response::RespRegistrationRequired;
case ClientIdRequired: return Response::RespClientIdRequired;
case UserIsInactive: return Response::RespAccountNotActivated;
default: authState = res;
}

View file

@ -46,6 +46,9 @@ clientkeepalive=1
; considered disconnected; default is 15
max_player_inactivity_time=15
; More modern clients generate client IDs based on specific client side information. Enable this option to
' require that clients report the client ID in order to log into the server. Default is false
requireclientid=false
[authentication]

View file

@ -142,6 +142,7 @@ bool Servatrice::initServer()
{
serverName = settingsCache->value("server/name", "My Cockatrice server").toString();
serverId = settingsCache->value("server/id", 0).toInt();
clientIdRequired = settingsCache->value("server/requireclientid",0).toBool();
bool regServerOnly = settingsCache->value("authentication/regonly", 0).toBool();
const QString authenticationMethodStr = settingsCache->value("authentication/method").toString();
@ -161,6 +162,7 @@ bool Servatrice::initServer()
authenticationMethod = AuthenticationNone;
}
qDebug() << "Client ID Required: " << clientIdRequired;
bool maxUserLimitEnabled = settingsCache->value("security/enable_max_user_limit", false).toBool();
qDebug() << "Maximum user limit enabled: " << maxUserLimitEnabled;

View file

@ -43,125 +43,126 @@ class ServerSocketInterface;
class IslInterface;
class Servatrice_GameServer : public QTcpServer {
Q_OBJECT
Q_OBJECT
private:
Servatrice *server;
QList<Servatrice_ConnectionPool *> connectionPools;
Servatrice *server;
QList<Servatrice_ConnectionPool *> connectionPools;
public:
Servatrice_GameServer(Servatrice *_server, int _numberPools, const QSqlDatabase &_sqlDatabase, QObject *parent = 0);
~Servatrice_GameServer();
Servatrice_GameServer(Servatrice *_server, int _numberPools, const QSqlDatabase &_sqlDatabase, QObject *parent = 0);
~Servatrice_GameServer();
protected:
#if QT_VERSION < 0x050000
void incomingConnection(int socketDescriptor);
void incomingConnection(int socketDescriptor);
#else
void incomingConnection(qintptr socketDescriptor);
void incomingConnection(qintptr socketDescriptor);
#endif
};
class Servatrice_IslServer : public QTcpServer {
Q_OBJECT
Q_OBJECT
private:
Servatrice *server;
QSslCertificate cert;
QSslKey privateKey;
Servatrice *server;
QSslCertificate cert;
QSslKey privateKey;
public:
Servatrice_IslServer(Servatrice *_server, const QSslCertificate &_cert, const QSslKey &_privateKey, QObject *parent = 0)
: QTcpServer(parent), server(_server), cert(_cert), privateKey(_privateKey) { }
Servatrice_IslServer(Servatrice *_server, const QSslCertificate &_cert, const QSslKey &_privateKey, QObject *parent = 0)
: QTcpServer(parent), server(_server), cert(_cert), privateKey(_privateKey) { }
protected:
#if QT_VERSION < 0x050000
void incomingConnection(int socketDescriptor);
void incomingConnection(int socketDescriptor);
#else
void incomingConnection(qintptr socketDescriptor);
void incomingConnection(qintptr socketDescriptor);
#endif
};
class ServerProperties {
public:
int id;
QSslCertificate cert;
QString hostname;
QHostAddress address;
int gamePort;
int controlPort;
int id;
QSslCertificate cert;
QString hostname;
QHostAddress address;
int gamePort;
int controlPort;
ServerProperties(int _id, const QSslCertificate &_cert, const QString &_hostname, const QHostAddress &_address, int _gamePort, int _controlPort)
: id(_id), cert(_cert), hostname(_hostname), address(_address), gamePort(_gamePort), controlPort(_controlPort) { }
ServerProperties(int _id, const QSslCertificate &_cert, const QString &_hostname, const QHostAddress &_address, int _gamePort, int _controlPort)
: id(_id), cert(_cert), hostname(_hostname), address(_address), gamePort(_gamePort), controlPort(_controlPort) { }
};
class Servatrice : public Server
{
Q_OBJECT
Q_OBJECT
public:
enum AuthenticationMethod { AuthenticationNone, AuthenticationSql, AuthenticationPassword };
enum AuthenticationMethod { AuthenticationNone, AuthenticationSql, AuthenticationPassword };
private slots:
void statusUpdate();
void shutdownTimeout();
void statusUpdate();
void shutdownTimeout();
protected:
void doSendIslMessage(const IslMessage &msg, int serverId);
void doSendIslMessage(const IslMessage &msg, int serverId);
private:
enum DatabaseType { DatabaseNone, DatabaseMySql };
AuthenticationMethod authenticationMethod;
DatabaseType databaseType;
QTimer *pingClock, *statusUpdateClock;
Servatrice_GameServer *gameServer;
Servatrice_IslServer *islServer;
QString serverName;
mutable QMutex loginMessageMutex;
QString loginMessage;
QString dbPrefix;
Servatrice_DatabaseInterface *servatriceDatabaseInterface;
int serverId;
int uptime;
QMutex txBytesMutex, rxBytesMutex;
quint64 txBytes, rxBytes;
int maxGameInactivityTime, maxPlayerInactivityTime;
int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser, commandCountingInterval, maxCommandCountPerInterval, pingClockInterval;
enum DatabaseType { DatabaseNone, DatabaseMySql };
AuthenticationMethod authenticationMethod;
DatabaseType databaseType;
QTimer *pingClock, *statusUpdateClock;
Servatrice_GameServer *gameServer;
Servatrice_IslServer *islServer;
QString serverName;
mutable QMutex loginMessageMutex;
QString loginMessage;
QString dbPrefix;
Servatrice_DatabaseInterface *servatriceDatabaseInterface;
int serverId;
int uptime;
QMutex txBytesMutex, rxBytesMutex;
quint64 txBytes, rxBytes;
int maxGameInactivityTime, maxPlayerInactivityTime;
int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser, commandCountingInterval, maxCommandCountPerInterval, pingClockInterval;
QString shutdownReason;
int shutdownMinutes;
QTimer *shutdownTimer;
bool isFirstShutdownMessage;
QString shutdownReason;
int shutdownMinutes;
QTimer *shutdownTimer;
bool isFirstShutdownMessage, clientIdRequired;
mutable QMutex serverListMutex;
QList<ServerProperties> serverList;
void updateServerList();
mutable QMutex serverListMutex;
QList<ServerProperties> serverList;
void updateServerList();
QMap<int, IslInterface *> islInterfaces;
QMap<int, IslInterface *> islInterfaces;
public slots:
void scheduleShutdown(const QString &reason, int minutes);
void updateLoginMessage();
void scheduleShutdown(const QString &reason, int minutes);
void updateLoginMessage();
public:
Servatrice(QObject *parent = 0);
~Servatrice();
bool initServer();
QString getServerName() const { return serverName; }
QString getLoginMessage() const { QMutexLocker locker(&loginMessageMutex); return loginMessage; }
bool getGameShouldPing() const { return true; }
int getPingClockInterval() const { return pingClockInterval; }
int getMaxGameInactivityTime() const { return maxGameInactivityTime; }
int getMaxPlayerInactivityTime() const { return maxPlayerInactivityTime; }
int getMaxUsersPerAddress() const { return maxUsersPerAddress; }
int getMessageCountingInterval() const { return messageCountingInterval; }
int getMaxMessageCountPerInterval() const { return maxMessageCountPerInterval; }
int getMaxMessageSizePerInterval() const { return maxMessageSizePerInterval; }
int getMaxGamesPerUser() const { return maxGamesPerUser; }
Servatrice(QObject *parent = 0);
~Servatrice();
bool initServer();
QString getServerName() const { return serverName; }
QString getLoginMessage() const { QMutexLocker locker(&loginMessageMutex); return loginMessage; }
bool getGameShouldPing() const { return true; }
bool getClientIdRequired() const { return clientIdRequired; }
int getPingClockInterval() const { return pingClockInterval; }
int getMaxGameInactivityTime() const { return maxGameInactivityTime; }
int getMaxPlayerInactivityTime() const { return maxPlayerInactivityTime; }
int getMaxUsersPerAddress() const { return maxUsersPerAddress; }
int getMessageCountingInterval() const { return messageCountingInterval; }
int getMaxMessageCountPerInterval() const { return maxMessageCountPerInterval; }
int getMaxMessageSizePerInterval() const { return maxMessageSizePerInterval; }
int getMaxGamesPerUser() const { return maxGamesPerUser; }
int getCommandCountingInterval() const { return commandCountingInterval; }
int getMaxCommandCountPerInterval() const { return maxCommandCountPerInterval; }
AuthenticationMethod getAuthenticationMethod() const { return authenticationMethod; }
QString getDbPrefix() const { return dbPrefix; }
int getServerId() const { return serverId; }
int getUsersWithAddress(const QHostAddress &address) const;
QList<ServerSocketInterface *> getUsersWithAddressAsList(const QHostAddress &address) const;
void incTxBytes(quint64 num);
void incRxBytes(quint64 num);
void addDatabaseInterface(QThread *thread, Servatrice_DatabaseInterface *databaseInterface);
AuthenticationMethod getAuthenticationMethod() const { return authenticationMethod; }
QString getDbPrefix() const { return dbPrefix; }
int getServerId() const { return serverId; }
int getUsersWithAddress(const QHostAddress &address) const;
QList<ServerSocketInterface *> getUsersWithAddressAsList(const QHostAddress &address) const;
void incTxBytes(quint64 num);
void incRxBytes(quint64 num);
void addDatabaseInterface(QThread *thread, Servatrice_DatabaseInterface *databaseInterface);
bool islConnectionExists(int serverId) const;
void addIslInterface(int serverId, IslInterface *interface);
void removeIslInterface(int serverId);
QReadWriteLock islLock;
bool islConnectionExists(int serverId) const;
void addIslInterface(int serverId, IslInterface *interface);
void removeIslInterface(int serverId);
QReadWriteLock islLock;
QList<ServerProperties> getServerList() const;
QList<ServerProperties> getServerList() const;
};
#endif