the boob will swarm your flat lands
This commit is contained in:
parent
4d1894066c
commit
8310d31ae2
6 changed files with 127 additions and 19 deletions
20
protocol.md
20
protocol.md
|
@ -185,8 +185,18 @@ Communication between the master server and clients will be done over a WebSocke
|
||||||
</thead>
|
</thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="center">1</td>
|
<td class="center">1</td>
|
||||||
<td>Client Key</td>
|
<td>Server Name</td>
|
||||||
<td>Big Int</td>
|
<td>Text</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="center">2</td>
|
||||||
|
<td>License</td>
|
||||||
|
<td>Text</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="center">3</td>
|
||||||
|
<td>Secret</td>
|
||||||
|
<td>Blob (512b)</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -472,9 +482,11 @@ TODO: MAKE THIS SECTION NOT LOOK LIKE SHIT
|
||||||
0x02: COULD NOT PARSE KEY
|
0x02: COULD NOT PARSE KEY
|
||||||
|
|
||||||
#### M -> S (ID 4)
|
#### M -> S (ID 4)
|
||||||
0x01: LICENSE DATA INCORRECT
|
0x01: MAX AUTH ATTEMPTS REACHED
|
||||||
|
|
||||||
0x02: LICENSE LIMIT REACHED
|
0x02: LICENSE DATA INCORRECT
|
||||||
|
|
||||||
|
0x03: LICENSE LIMIT REACHED
|
||||||
|
|
||||||
### Master / Client
|
### Master / Client
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace sosc {
|
||||||
namespace db {
|
namespace db {
|
||||||
|
|
||||||
class Query;
|
class Query;
|
||||||
|
typedef std::vector<Query*> QueryList;
|
||||||
|
|
||||||
class ResultSet {
|
class ResultSet {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
#include "../db/database.hpp"
|
#include "../db/database.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace sosc {
|
namespace sosc {
|
||||||
/** MASTER -> CLIENT **/
|
/** MASTER -> CLIENT **/
|
||||||
|
|
||||||
|
@ -36,7 +38,7 @@ protected:
|
||||||
class MasterIntra {
|
class MasterIntra {
|
||||||
public:
|
public:
|
||||||
explicit MasterIntra(const IntraClient& client);
|
explicit MasterIntra(const IntraClient& client);
|
||||||
bool Process();
|
bool Process(const db::QueryList* queries);
|
||||||
|
|
||||||
bool Close();
|
bool Close();
|
||||||
bool Close(const Packet& message);
|
bool Close(const Packet& message);
|
||||||
|
@ -45,6 +47,9 @@ private:
|
||||||
bool Authentication(Packet& pck);
|
bool Authentication(Packet& pck);
|
||||||
bool StatusUpdate(Packet& pck);
|
bool StatusUpdate(Packet& pck);
|
||||||
|
|
||||||
|
bool AuthenticationFailure
|
||||||
|
(const std::string& packetId, uint16_t errorCode);
|
||||||
|
|
||||||
enum SlaveToMasterId {
|
enum SlaveToMasterId {
|
||||||
kInitAttempt = 1,
|
kInitAttempt = 1,
|
||||||
kAuthentication,
|
kAuthentication,
|
||||||
|
@ -66,13 +71,21 @@ private:
|
||||||
int auth_attempts;
|
int auth_attempts;
|
||||||
const int MAX_AUTH_ATTEMPTS = 3;
|
const int MAX_AUTH_ATTEMPTS = 3;
|
||||||
std::string license;
|
std::string license;
|
||||||
|
|
||||||
|
const db::QueryList* queries;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MasterIntraPool : public Pool<MasterIntra> {
|
class MasterIntraPool : public Pool<MasterIntra> {
|
||||||
|
public:
|
||||||
|
MasterIntraPool();
|
||||||
protected:
|
protected:
|
||||||
bool ProcessClient(MasterIntra& client) override {
|
bool ProcessClient(MasterIntra& client) override {
|
||||||
return client.Process();
|
return client.Process(&this->queries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Stop() override;
|
||||||
|
private:
|
||||||
|
db::QueryList queries;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,43 @@
|
||||||
#include "master.hpp"
|
#include "master.hpp"
|
||||||
#include "../db/database.hpp"
|
#include "../db/database.hpp"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
std::mutex license_check_mtx;
|
||||||
|
} _ctx;
|
||||||
|
|
||||||
|
/** MASTERINTRAPOOL CODE **/
|
||||||
|
|
||||||
|
sosc::MasterIntraPool::MasterIntraPool() {
|
||||||
|
#define QRY_LICENSE_CHECK 0
|
||||||
|
this->queries.push_back(new db::Query(
|
||||||
|
"SELECT COUNT(*) FROM SERVER_LICENSES "
|
||||||
|
"WHERE KEY_ID = ? AND SECRET = ?"
|
||||||
|
));
|
||||||
|
|
||||||
|
#define QRY_LICENSE_LIMIT 1
|
||||||
|
this->queries.push_back(new db::Query(
|
||||||
|
"SELECT ALLOWANCE FROM SERVER_LICENSES WHERE KEY_ID = ?"
|
||||||
|
));
|
||||||
|
|
||||||
|
#define QRY_LICENSE_ACTIVE_COUNT 2
|
||||||
|
this->queries.push_back(new db::Query(
|
||||||
|
"SELECT COUNT(*) FROM SERVER_LIST WHERE LICENSE = ?"
|
||||||
|
, DB_USE_MEMORY));
|
||||||
|
|
||||||
|
#define QRY_LICENSE_
|
||||||
|
}
|
||||||
|
|
||||||
|
void sosc::MasterIntraPool::Stop() {
|
||||||
|
Pool<MasterIntra>::Stop();
|
||||||
|
|
||||||
|
for(auto& query : this->queries) {
|
||||||
|
query->Close();
|
||||||
|
delete query;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** MASTERINTRA CODE **/
|
||||||
|
|
||||||
sosc::MasterIntra::MasterIntra(const IntraClient& client) {
|
sosc::MasterIntra::MasterIntra(const IntraClient& client) {
|
||||||
this->sock = client;
|
this->sock = client;
|
||||||
|
@ -7,7 +45,7 @@ sosc::MasterIntra::MasterIntra(const IntraClient& client) {
|
||||||
this->auth_attempts = 0;
|
this->auth_attempts = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sosc::MasterIntra::Process() {
|
bool sosc::MasterIntra::Process(const db::QueryList* queries) {
|
||||||
Packet pck;
|
Packet pck;
|
||||||
int status = this->sock.Receive(&pck);
|
int status = this->sock.Receive(&pck);
|
||||||
if(status == PCK_ERR)
|
if(status == PCK_ERR)
|
||||||
|
@ -15,6 +53,7 @@ bool sosc::MasterIntra::Process() {
|
||||||
else if(status == PCK_MORE)
|
else if(status == PCK_MORE)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
this->queries = queries;
|
||||||
switch(pck.GetId()) {
|
switch(pck.GetId()) {
|
||||||
case kInitAttempt:
|
case kInitAttempt:
|
||||||
return this->InitAttempt(pck);
|
return this->InitAttempt(pck);
|
||||||
|
@ -27,7 +66,8 @@ bool sosc::MasterIntra::Process() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sosc::MasterIntra::InitAttempt(sosc::Packet &pck) {
|
bool sosc::MasterIntra::InitAttempt(sosc::Packet &pck)
|
||||||
|
{
|
||||||
if(!pck.Check(1, key.key_size_bytes))
|
if(!pck.Check(1, key.key_size_bytes))
|
||||||
return this->Close(Packet(kEncryptionError, { "\x01" }));
|
return this->Close(Packet(kEncryptionError, { "\x01" }));
|
||||||
|
|
||||||
|
@ -38,24 +78,62 @@ bool sosc::MasterIntra::InitAttempt(sosc::Packet &pck) {
|
||||||
this->sock.Send(response);
|
this->sock.Send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sosc::MasterIntra::Authentication(sosc::Packet &pck) {
|
bool sosc::MasterIntra::Authentication(sosc::Packet &pck)
|
||||||
|
{
|
||||||
if(this->authed)
|
if(this->authed)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if(!pck.Check(2, PCK_ANY, 512))
|
std::string packetId = BYTESTR(kAuthentication);
|
||||||
return this->Close(Packet(kNegativeAck, { "\x01" }));
|
if(!pck.Check(3, PCK_ANY, PCK_ANY, 512))
|
||||||
|
return this->Close();
|
||||||
|
|
||||||
db::Query = db::Query::ScalarInt32(
|
db::Query* query = this->queries->at(QRY_LICENSE_CHECK);
|
||||||
"SELECT COUNT(*) FROM SERVER_LICENSES "
|
query->Reset();
|
||||||
"WHERE KEY_ID = ? AND SECRET = ?"
|
query->BindText(pck[1], 0);
|
||||||
);
|
query->BindBlob(pck[2], 1);
|
||||||
|
if(query->ScalarInt32() == 0)
|
||||||
|
return AuthenticationFailure(packetId, 2);
|
||||||
|
|
||||||
if(isValid > 0) {
|
_ctx.license_check_mtx.lock();
|
||||||
|
|
||||||
|
int limit;
|
||||||
|
query = this->queries->at(QRY_LICENSE_LIMIT);
|
||||||
|
query->Reset();
|
||||||
|
query->BindText(pck[1], 0);
|
||||||
|
if((limit = query->ScalarInt32()) != 0) {
|
||||||
|
query = this->queries->at(QRY_LICENSE_ACTIVE_COUNT);
|
||||||
|
query->Reset();
|
||||||
|
query->BindText(pck[1], 0);
|
||||||
|
if(query->ScalarInt32() < limit) {
|
||||||
|
_ctx.license_check_mtx.unlock();
|
||||||
|
return AuthenticationFailure(packetId, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_ctx.license_check_mtx.unlock();
|
||||||
|
|
||||||
|
this->authed = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sosc::MasterIntra::AuthenticationFailure
|
||||||
|
(const std::string& packetId, uint16_t errorCode)
|
||||||
|
{
|
||||||
|
if(++this->auth_attempts < MAX_AUTH_ATTEMPTS) {
|
||||||
|
this->sock.Send(
|
||||||
|
Packet(kNegativeAck, { packetId , net::htonv(errorCode) })
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return this->Close(
|
||||||
|
Packet(kNegativeAck, { packetId, net::htonv<uint16_t>(1) })
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sosc::MasterIntra::StatusUpdate(sosc::Packet &pck) {
|
bool sosc::MasterIntra::StatusUpdate(sosc::Packet &pck)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,4 +145,4 @@ bool sosc::MasterIntra::Close() {
|
||||||
bool sosc::MasterIntra::Close(const Packet &message) {
|
bool sosc::MasterIntra::Close(const Packet &message) {
|
||||||
this->sock.Send(message);
|
this->sock.Send(message);
|
||||||
this->Close();
|
this->Close();
|
||||||
}
|
}
|
|
@ -40,7 +40,7 @@ public:
|
||||||
return this->is_open;
|
return this->is_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stop();
|
virtual void Stop();
|
||||||
protected:
|
protected:
|
||||||
virtual bool ProcessClient(T& client) = 0;
|
virtual bool ProcessClient(T& client) = 0;
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -10,6 +10,10 @@
|
||||||
#undef TOSTR
|
#undef TOSTR
|
||||||
#define TOSTR(X) std::to_string(X)
|
#define TOSTR(X) std::to_string(X)
|
||||||
|
|
||||||
|
#undef bytestr
|
||||||
|
#undef BYTESTR
|
||||||
|
#define BYTESTR(X) std::string(1, X)
|
||||||
|
|
||||||
namespace sosc {
|
namespace sosc {
|
||||||
namespace str {
|
namespace str {
|
||||||
std::string trim (std::string str);
|
std::string trim (std::string str);
|
||||||
|
|
Loading…
Reference in a new issue