Added server/client feature set communication

This commit is contained in:
woogerboy21 2015-08-27 00:10:41 -04:00
parent baa61d0571
commit 044c2356ff
26 changed files with 225 additions and 22 deletions

View file

@ -7,6 +7,7 @@ add_subdirectory(pb)
SET(common_SOURCES
decklist.cpp
featureset.cpp
get_pb_extension.cpp
rng_abstract.cpp
rng_sfmt.cpp

55
common/featureset.cpp Normal file
View file

@ -0,0 +1,55 @@
#include "featureset.h"
#include <QMap>
#include <QDebug>
FeatureSet::FeatureSet()
{
}
QMap<QString, bool> FeatureSet::getDefaultFeatureList() {
initalizeFeatureList(featureList);
return featureList;
}
void FeatureSet::initalizeFeatureList(QMap<QString, bool> &featureList){
featureList.insert("client_id", false);
featureList.insert("client_ver", false);
featureList.insert("feature_set", false);
}
void FeatureSet::enableRequiredFeature(QMap<QString, bool> &featureList, QString featureName){
if (featureList.contains(featureName))
featureList.insert(featureName,true);
}
void FeatureSet::disableRequiredFeature(QMap<QString, bool> &featureList, QString featureName){
if (featureList.contains(featureName))
featureList.insert(featureName,false);
}
QMap<QString, bool> FeatureSet::addFeature(QMap<QString, bool> &featureList, QString featureName, bool isFeatureRequired){
featureList.insert(featureName,isFeatureRequired);
return featureList;
}
QMap<QString, bool> FeatureSet::identifyMissingFeatures(QMap<QString, bool> suppliedFeatures, QMap<QString, bool> requiredFeatures){
QMap<QString, bool> missingList;
QMap<QString, bool>::iterator i;
for (i = requiredFeatures.begin(); i != requiredFeatures.end(); ++i) {
if (!suppliedFeatures.contains(i.key())) {
missingList.insert(i.key(), i.value());
}
}
return missingList;
}
bool FeatureSet::isRequiredFeaturesMissing(QMap<QString, bool> suppliedFeatures, QMap<QString, bool> requiredFeatures) {
QMap<QString, bool>::iterator i;
for (i = requiredFeatures.begin(); i != requiredFeatures.end(); ++i) {
if (i.value() && suppliedFeatures.contains(i.key())) {
return true;
}
}
return false;
}

24
common/featureset.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef FEATURESET_H
#define FEATURESET_H
#include <QMap>
#include <QSet>
#include <QString>
class FeatureSet
{
public:
FeatureSet();
QMap<QString, bool> getDefaultFeatureList();
void initalizeFeatureList(QMap<QString, bool> &featureList);
void enableRequiredFeature(QMap<QString, bool> &featureList, QString featureName);
void disableRequiredFeature(QMap<QString, bool> &featureList, QString featureName);
QMap<QString, bool> addFeature(QMap<QString, bool> &featureList, QString featureName, bool isFeatureRequired);
QMap<QString, bool> identifyMissingFeatures(QMap<QString, bool> featureListToCheck, QMap<QString, bool> featureListToCompareTo);
bool isRequiredFeaturesMissing(QMap<QString, bool> featureListToCheck, QMap<QString, bool> featureListToCompareTo);
private:
QMap<QString, bool> featureList;
};
#endif // FEEATURESET_H

View file

@ -37,6 +37,7 @@ message Response {
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 requires client to generate and send its client id before allowing access
RespClientUpdateRequired = 35; // Client is missing features that the server is requiring
}
enum ResponseType {
JOIN_ROOM = 1000;

View file

@ -11,4 +11,5 @@ message Response_Login {
repeated ServerInfo_User ignore_list = 3;
optional string denied_reason_str = 4;
optional uint64 denied_end_time = 5;
repeated string missing_features = 6;
}

View file

@ -46,6 +46,7 @@ message Command_Login {
optional string password = 2;
optional string clientid = 3;
optional string clientver = 4;
repeated string clientfeatures = 5;
}
message Command_Message {

View file

@ -32,6 +32,7 @@
#include "pb/session_event.pb.h"
#include "pb/event_connection_closed.pb.h"
#include "pb/isl_message.pb.h"
#include "featureset.h"
#include <QCoreApplication>
#include <QThread>
#include <QDebug>

View file

@ -51,10 +51,10 @@ public:
Server_AbstractUserInterface *findUser(const QString &userName) const;
const QMap<QString, Server_ProtocolHandler *> &getUsers() const { return users; }
const QMap<qint64, Server_ProtocolHandler *> &getUsersBySessionId() const { return usersBySessionId; }
virtual QMap<QString, bool> getServerRequiredFeatureList() const { return QMap<QString, bool>(); }
void addClient(Server_ProtocolHandler *player);
void removeClient(Server_ProtocolHandler *player);
virtual QString getLoginMessage() const { return QString(); }
virtual bool permitUnregisteredUsers() const { return true; }
virtual bool getGameShouldPing() const { return false; }
virtual bool getClientIdRequired() const { return false; }
@ -94,6 +94,7 @@ private:
mutable QReadWriteLock persistentPlayersLock;
int nextLocalGameId;
QMutex nextLocalGameIdMutex;
protected slots:
void externalUserJoined(const ServerInfo_User &userInfo);
void externalUserLeft(const QString &userName);

View file

@ -19,6 +19,8 @@
#include "pb/event_game_joined.pb.h"
#include "pb/event_room_say.pb.h"
#include <google/protobuf/descriptor.h>
#include "featureset.h"
Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, Server_DatabaseInterface *_databaseInterface, QObject *parent)
: QObject(parent),
@ -382,10 +384,32 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
{
QString userName = QString::fromStdString(cmd.user_name()).simplified();
QString clientId = QString::fromStdString(cmd.clientid()).simplified();
if (userName.isEmpty() || (userInfo != 0))
return Response::RespContextError;
// check client feature set against server feature set
FeatureSet features;
QMap<QString, bool> receivedClientFeatures;
QMap<QString, bool> missingClientFeatures;
for (int i = 0; i < cmd.clientfeatures().size(); ++i)
receivedClientFeatures.insert(QString::fromStdString(cmd.clientfeatures(i)).simplified(), false);
missingClientFeatures = features.identifyMissingFeatures(receivedClientFeatures, server->getServerRequiredFeatureList());
if (!missingClientFeatures.isEmpty()) {
if (features.isRequiredFeaturesMissing(missingClientFeatures, server->getServerRequiredFeatureList())) {
Response_Login *re = new Response_Login;
re->set_denied_reason_str("Client upgrade required");
QMap<QString, bool>::iterator i;
for (i = missingClientFeatures.begin(); i != missingClientFeatures.end(); ++i)
re->add_missing_features(i.key().toStdString().c_str());
rc.setResponseExtension(re);
return Response::RespClientUpdateRequired;
}
}
QString reasonStr;
int banSecondsLeft = 0;
AuthenticationResult res = server->loginUser(this, userName, QString::fromStdString(cmd.password()), reasonStr, banSecondsLeft, clientId);
@ -430,6 +454,13 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
re->add_ignore_list()->CopyFrom(ignoreIterator.next().value());
}
// return to client any missing features the server has that the client does not
if (!missingClientFeatures.isEmpty()) {
QMap<QString, bool>::iterator i;
for (i = missingClientFeatures.begin(); i != missingClientFeatures.end(); ++i)
re->add_missing_features(i.key().toStdString().c_str());
}
joinPersistentGames(rc);
rc.setResponseExtension(re);

View file

@ -8,11 +8,13 @@
#include "pb/response.pb.h"
#include "pb/server_message.pb.h"
class Features;
class Server_DatabaseInterface;
class Server_Player;
class ServerInfo_User;
class Server_Room;
class QTimer;
class FeatureSet;
class ServerMessage;
class Response;