satori bad
This commit is contained in:
parent
cfcdcc4cd4
commit
6ed3adfb87
13 changed files with 172 additions and 59 deletions
33
PROTOCOL.md
33
PROTOCOL.md
|
@ -181,8 +181,8 @@ Communication between the master server and clients will be done over a WebSocke
|
||||||
</tr>
|
</tr>
|
||||||
<tr style="border-bottom: 2px solid;">
|
<tr style="border-bottom: 2px solid;">
|
||||||
<td class="center">2</td>
|
<td class="center">2</td>
|
||||||
<td>Message</td>
|
<td>Error Code</td>
|
||||||
<td>String</td>
|
<td>Packed Unsigned Short</td>
|
||||||
<td>¬R<sub>1</sub></td>
|
<td>¬R<sub>1</sub></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -213,8 +213,8 @@ Communication between the master server and clients will be done over a WebSocke
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="center">2</td>
|
<td class="center">2</td>
|
||||||
<td>Message</td>
|
<td>Error Code</td>
|
||||||
<td>String</td>
|
<td>Packed Unsigned Short</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -354,12 +354,7 @@ TODO: MAKE THIS SECTION NOT LOOK LIKE SHIT
|
||||||
|
|
||||||
### Master / Slave
|
### Master / Slave
|
||||||
|
|
||||||
#### M -> S (ID 2)
|
#### M -> S (ID 1)
|
||||||
0x100: KEY SIZE WAS INCORRECT
|
|
||||||
|
|
||||||
0x101: COULD NOT PARSE KEY
|
|
||||||
|
|
||||||
#### M -> S (ID 4)
|
|
||||||
0x100: MAX AUTH ATTEMPTS REACHED
|
0x100: MAX AUTH ATTEMPTS REACHED
|
||||||
|
|
||||||
0x101: LICENSE DATA INCORRECT
|
0x101: LICENSE DATA INCORRECT
|
||||||
|
@ -370,4 +365,22 @@ TODO: MAKE THIS SECTION NOT LOOK LIKE SHIT
|
||||||
|
|
||||||
### Master / Client
|
### Master / Client
|
||||||
|
|
||||||
|
#### M -> C (ID 0)
|
||||||
|
|
||||||
|
0x100: MAX AUTH ATTEMPTS REACHED
|
||||||
|
|
||||||
|
0x101: USERNAME DOES NOT EXIST
|
||||||
|
|
||||||
|
0x102: PASSWORD INCORRECT
|
||||||
|
|
||||||
|
#### M -> C (ID 1)
|
||||||
|
|
||||||
|
0x000: OK
|
||||||
|
|
||||||
|
0x100: USERNAME TAKEN
|
||||||
|
|
||||||
|
0x101: EMAIL TAKEN
|
||||||
|
|
||||||
|
0x102: PASSWORD TOO WEAK
|
||||||
|
|
||||||
### Slave / Client
|
### Slave / Client
|
|
@ -148,6 +148,15 @@ bool sosc::Packet::Check(int region_count, ...) const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sosc::Packet::TrimRegions(const std::vector<uint32_t>& ids) {
|
||||||
|
if(ids.size() == 0)
|
||||||
|
for(uint32_t id = 0; id < this->regions.size(); ++id)
|
||||||
|
str::trim(&this->regions[id]);
|
||||||
|
else
|
||||||
|
for(auto id : ids)
|
||||||
|
str::trim(&this->regions[id]);
|
||||||
|
}
|
||||||
|
|
||||||
std::string* sosc::Packet::ToString(std::string* packet) const {
|
std::string* sosc::Packet::ToString(std::string* packet) const {
|
||||||
*packet = std::string(8, 0);
|
*packet = std::string(8, 0);
|
||||||
(*packet)[0] = 0xB0;
|
(*packet)[0] = 0xB0;
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
|
|
||||||
int Parse(const std::string& data, std::string* extra = nullptr);
|
int Parse(const std::string& data, std::string* extra = nullptr);
|
||||||
bool Check(int region_count, ...) const;
|
bool Check(int region_count, ...) const;
|
||||||
|
void TrimRegions(const std::vector<uint32_t>& ids = {});
|
||||||
|
|
||||||
inline void SetId(uint8_t id) {
|
inline void SetId(uint8_t id) {
|
||||||
this->id = id;
|
this->id = id;
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
#include "ini.hpp"
|
#include "ini.hpp"
|
||||||
using namespace sosc::ini;
|
using namespace sosc::ini;
|
||||||
|
|
||||||
bool Field::Test() const {
|
bool Field::Test(const std::string& value) const {
|
||||||
try {
|
try {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case INT32:
|
case INT32:
|
||||||
(int32_t)File::Proxy(name);
|
(int32_t)File::Proxy(value);
|
||||||
break;
|
break;
|
||||||
case UINT32:
|
case UINT32:
|
||||||
(uint32_t)File::Proxy(name);
|
(uint32_t)File::Proxy(value);
|
||||||
break;
|
break;
|
||||||
case DOUBLE:
|
case DOUBLE:
|
||||||
(double)File::Proxy(name);
|
(double)File::Proxy(value);
|
||||||
break;
|
break;
|
||||||
case BOOL:
|
case BOOL:
|
||||||
(bool)File::Proxy(name);
|
(bool)File::Proxy(value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,13 +100,14 @@ File* File::Open
|
||||||
|
|
||||||
for(auto& section : (*ini)[rule.name].sections) {
|
for(auto& section : (*ini)[rule.name].sections) {
|
||||||
for(auto &field : rule.required_fields) {
|
for(auto &field : rule.required_fields) {
|
||||||
if(section.values.count(str::tolower(field.name)) == 0)
|
std::string field_name = str::tolower(field.name);
|
||||||
|
if(section.values.count(field_name) == 0)
|
||||||
throw LoadError(ini, -1, str::join({
|
throw LoadError(ini, -1, str::join({
|
||||||
"Required field '", field.name, "' in section '",
|
"Required field '", field.name, "' in section '",
|
||||||
rule.name, "' not found."
|
rule.name, "' not found."
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if(!field.Test())
|
if(!field.Test(section.values.at(field_name)))
|
||||||
throw LoadError(ini, -1, str::join({
|
throw LoadError(ini, -1, str::join({
|
||||||
"Field '", field.name, "' in section '",rule.name, "' "
|
"Field '", field.name, "' in section '",rule.name, "' "
|
||||||
"cannot be casted to requested type."
|
"cannot be casted to requested type."
|
||||||
|
@ -121,15 +122,16 @@ File* File::Open
|
||||||
std::runtime_error File::LoadError
|
std::runtime_error File::LoadError
|
||||||
(File* file, int line, const std::string &error)
|
(File* file, int line, const std::string &error)
|
||||||
{
|
{
|
||||||
delete file;
|
std::string msg;
|
||||||
if(line > 0)
|
if(line > 0)
|
||||||
return std::runtime_error(str::join(
|
msg = str::join(
|
||||||
{"LOAD ERROR IN '", file->filename, "' L", TOSTR(line), ": ", error}
|
{"LOAD ERROR IN '", file->filename, "' L", TOSTR(line), ": ", error}
|
||||||
));
|
);
|
||||||
else
|
else
|
||||||
return std::runtime_error(str::join(
|
msg = str::join({"LOAD ERROR IN '", file->filename, "': ", error});
|
||||||
{"LOAD ERROR IN '", file->filename, "': ", error}
|
|
||||||
));
|
delete file;
|
||||||
|
throw std::runtime_error(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool File::HasSection(std::string name) const {
|
bool File::HasSection(std::string name) const {
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "string.hpp"
|
#include "string.hpp"
|
||||||
|
|
||||||
namespace sosc {
|
namespace sosc {
|
||||||
|
@ -23,7 +25,7 @@ struct Field {
|
||||||
explicit Field
|
explicit Field
|
||||||
(const std::string& name, kType type = STRING)
|
(const std::string& name, kType type = STRING)
|
||||||
: name(name), type(type) {}
|
: name(name), type(type) {}
|
||||||
bool Test() const;
|
bool Test(const std::string& value) const;
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
kType type;
|
kType type;
|
||||||
|
|
|
@ -23,19 +23,19 @@
|
||||||
#undef NTOHLL
|
#undef NTOHLL
|
||||||
#undef NTOHULL
|
#undef NTOHULL
|
||||||
|
|
||||||
#define HTONS (X) sosc::net::htonv<int16_t>(X)
|
#define HTONS(X) sosc::net::htonv<int16_t>(X)
|
||||||
#define HTONUS(X) sosc::net::htonv<uint16_t>(X)
|
#define HTONUS(X) sosc::net::htonv<uint16_t>(X)
|
||||||
#define NTOHS (X) sosc::net::ntohv<int16_t>(X)
|
#define NTOHS(X) sosc::net::ntohv<int16_t>(X)
|
||||||
#define NTOHUS(X) sosc::net::ntohv<uint16_t>(X)
|
#define NTOHUS(X) sosc::net::ntohv<uint16_t>(X)
|
||||||
|
|
||||||
#define HTONL (X) sosc::net::htonv<int32_t>(X)
|
#define HTONL(X) sosc::net::htonv<int32_t>(X)
|
||||||
#define HTONUL(X) sosc::net::htonv<uint32_t>(X)
|
#define HTONUL(X) sosc::net::htonv<uint32_t>(X)
|
||||||
#define NTOHL (X) sosc::net::ntohv<int32_t>(X, 0)
|
#define NTOHL(X) sosc::net::ntohv<int32_t>(X, 0)
|
||||||
#define NTOHUL(X) sosc::net::ntohv<uint32_t>(X, 0)
|
#define NTOHUL(X) sosc::net::ntohv<uint32_t>(X, 0)
|
||||||
|
|
||||||
#define HTONLL (X) sosc::net::htonv<int64_t>(X)
|
#define HTONLL(X) sosc::net::htonv<int64_t>(X)
|
||||||
#define HTONULL(X) sosc::net::htonv<uint64_t>(X)
|
#define HTONULL(X) sosc::net::htonv<uint64_t>(X)
|
||||||
#define NTOHLL (X) sosc::net::ntohv<int64_t>(X, 0)
|
#define NTOHLL(X) sosc::net::ntohv<int64_t>(X, 0)
|
||||||
#define NTOHULL(X) sosc::net::ntohv<uint64_t>(X, 0)
|
#define NTOHULL(X) sosc::net::ntohv<uint64_t>(X, 0)
|
||||||
|
|
||||||
namespace sosc {
|
namespace sosc {
|
||||||
|
|
|
@ -88,15 +88,15 @@ std::string sosc::str::join(const std::vector<std::string>& parts,
|
||||||
std::string sosc::str::join(const std::vector<std::string>& parts,
|
std::string sosc::str::join(const std::vector<std::string>& parts,
|
||||||
std::string delimiter, int count)
|
std::string delimiter, int count)
|
||||||
{
|
{
|
||||||
std::string assembled;
|
std::stringstream ss;
|
||||||
int bounds = (count == -1)
|
int bounds = (count == -1)
|
||||||
? parts.size()
|
? parts.size()
|
||||||
: std::min<int>(count, parts.size());
|
: std::min<int>(count, parts.size());
|
||||||
|
|
||||||
for(int i = 0; i < bounds; ++i)
|
for(int i = 0; i < bounds; ++i)
|
||||||
assembled += (i == 0 ? "" : delimiter) + parts[i];
|
ss << (i == 0 ? "" : delimiter) + parts[i];
|
||||||
|
|
||||||
return assembled;
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sosc::str::starts
|
bool sosc::str::starts
|
||||||
|
|
|
@ -11,11 +11,12 @@ static struct {
|
||||||
bool sosc::db::init_databases(std::string* error) {
|
bool sosc::db::init_databases(std::string* error) {
|
||||||
if(_ctx.ready)
|
if(_ctx.ready)
|
||||||
return true;
|
return true;
|
||||||
|
_ctx.ready = true;
|
||||||
|
|
||||||
sqlite3_open(":memory:", &_ctx.mem_db);
|
sqlite3_open(":memory:", &_ctx.mem_db);
|
||||||
sqlite3_exec(_ctx.mem_db, _mem_db_sql, nullptr, nullptr, nullptr);
|
sqlite3_exec(_ctx.mem_db, _mem_db_sql, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
sqlite3_open("scape.db", &_ctx.hard_db);
|
sqlite3_open(SOSC_RESC("scape.db").c_str(), &_ctx.hard_db);
|
||||||
|
|
||||||
int32_t migrationsExist = db::Query::ScalarInt32(
|
int32_t migrationsExist = db::Query::ScalarInt32(
|
||||||
"SELECT COUNT(*) FROM SQLITE_MASTER WHERE TBL_NAME = 'MIGRATIONS'"
|
"SELECT COUNT(*) FROM SQLITE_MASTER WHERE TBL_NAME = 'MIGRATIONS'"
|
||||||
|
@ -27,13 +28,14 @@ bool sosc::db::init_databases(std::string* error) {
|
||||||
if(lastMig > _hard_db_sql.size()) {
|
if(lastMig > _hard_db_sql.size()) {
|
||||||
if(error != nullptr)
|
if(error != nullptr)
|
||||||
*error = "HARD DB: RECORDED MIGRATION COUNT TOO HIGH";
|
*error = "HARD DB: RECORDED MIGRATION COUNT TOO HIGH";
|
||||||
|
_ctx.ready = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
Query insertMigration(
|
Query insertMigration(
|
||||||
"INSERT INTO MIGRATIONS (ID, SQL_HASH, DATE_RAN) "
|
"INSERT INTO MIGRATIONS (ID, SQL_HASH, DATE_RAN) "
|
||||||
"VALUES (?, ?, NOW())"
|
"VALUES (?, ?, DATETIME('NOW'))"
|
||||||
);
|
);
|
||||||
Query getMigration("SELECT SQL_HASH FROM MIGRATIONS WHERE ID = ?");
|
Query getMigration("SELECT SQL_HASH FROM MIGRATIONS WHERE ID = ?");
|
||||||
for(id = 0; id < _hard_db_sql.size(); ++id) {
|
for(id = 0; id < _hard_db_sql.size(); ++id) {
|
||||||
|
@ -44,6 +46,7 @@ bool sosc::db::init_databases(std::string* error) {
|
||||||
if(id < lastMig) {
|
if(id < lastMig) {
|
||||||
if(error != nullptr)
|
if(error != nullptr)
|
||||||
*error = "HARD DB: MIGRATION RECORDS NOT CONTINUOUS";
|
*error = "HARD DB: MIGRATION RECORDS NOT CONTINUOUS";
|
||||||
|
_ctx.ready = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +59,7 @@ bool sosc::db::init_databases(std::string* error) {
|
||||||
if(hash != cgc::sha1(_hard_db_sql[id])) {
|
if(hash != cgc::sha1(_hard_db_sql[id])) {
|
||||||
if(error != nullptr)
|
if(error != nullptr)
|
||||||
*error = "HARD DB: MIGRATION SQL HASH MISMATCH";
|
*error = "HARD DB: MIGRATION SQL HASH MISMATCH";
|
||||||
|
_ctx.ready = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +110,7 @@ sosc::db::Query::Query(const std::string& query, int db) : results(this) {
|
||||||
void sosc::db::Query::SetQuery(const std::string &query, int db) {
|
void sosc::db::Query::SetQuery(const std::string &query, int db) {
|
||||||
if(!_ctx.ready)
|
if(!_ctx.ready)
|
||||||
return;
|
return;
|
||||||
if(!this->open)
|
if(this->open)
|
||||||
this->Close();
|
this->Close();
|
||||||
|
|
||||||
this->database = db == DB_USE_MEMORY ? _ctx.mem_db : _ctx.hard_db;
|
this->database = db == DB_USE_MEMORY ? _ctx.mem_db : _ctx.hard_db;
|
||||||
|
@ -120,6 +124,8 @@ void sosc::db::Query::SetQuery(const std::string &query, int db) {
|
||||||
|
|
||||||
if(status == SQLITE_OK)
|
if(status == SQLITE_OK)
|
||||||
this->open = true;
|
this->open = true;
|
||||||
|
else
|
||||||
|
throw std::runtime_error(sqlite3_errmsg(this->database));
|
||||||
}
|
}
|
||||||
|
|
||||||
void sosc::db::Query::BindDouble(double value, int i) {
|
void sosc::db::Query::BindDouble(double value, int i) {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "sqlite/sqlite3.h"
|
#include "sqlite/sqlite3.h"
|
||||||
#include "utils/time.hpp"
|
#include "utils/time.hpp"
|
||||||
#include "crypto/sha1.hpp"
|
#include "crypto/sha1.hpp"
|
||||||
|
#include "common.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -86,7 +87,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
// THE FOLLOWING ARE NOT THREAD SAFE !!
|
// THE FOLLOWING ARE NOT THREAD SAFE !!
|
||||||
// CALL THEM ONLY WHEN MASTER POOL IS INACTIVE
|
// CALL THEM ONLY WHEN MASTER POOLS ARE INACTIVE
|
||||||
bool init_databases(std::string* error);
|
bool init_databases(std::string* error);
|
||||||
void close_databases();
|
void close_databases();
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
#include "sock/scapesock.hpp"
|
#include "sock/scapesock.hpp"
|
||||||
#include "sock/pool.hpp"
|
#include "sock/pool.hpp"
|
||||||
|
|
||||||
|
#include "crypto/bcrypt.hpp"
|
||||||
#include "db/database.hpp"
|
#include "db/database.hpp"
|
||||||
|
|
||||||
#include "ctx/master.hpp"
|
#include "ctx/master.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -27,7 +27,11 @@ public:
|
||||||
~MasterClient() { this->Close(); };
|
~MasterClient() { this->Close(); };
|
||||||
private:
|
private:
|
||||||
bool ProcessLogin(Packet& pck);
|
bool ProcessLogin(Packet& pck);
|
||||||
|
bool LoginError(uint16_t error_code);
|
||||||
|
|
||||||
bool ProcessRegistration(Packet& pck);
|
bool ProcessRegistration(Packet& pck);
|
||||||
|
bool RegistrationError(uint16_t error_code);
|
||||||
|
|
||||||
bool ListServers(Packet& pck);
|
bool ListServers(Packet& pck);
|
||||||
|
|
||||||
enum MasterToClientId {
|
enum MasterToClientId {
|
||||||
|
@ -79,9 +83,9 @@ private:
|
||||||
bool StatusUpdate(Packet& pck);
|
bool StatusUpdate(Packet& pck);
|
||||||
|
|
||||||
bool AuthenticationFailure
|
bool AuthenticationFailure
|
||||||
(const std::string& packetId, uint16_t errorCode);
|
(const std::string& packet_id, uint16_t error_code);
|
||||||
|
|
||||||
bool NotAuthorized(const std::string& packetId);
|
bool NotAuthorized(const std::string& packet_id);
|
||||||
|
|
||||||
enum SlaveToMasterId {
|
enum SlaveToMasterId {
|
||||||
kAuthentication = 0,
|
kAuthentication = 0,
|
||||||
|
|
|
@ -7,44 +7,50 @@ static struct {
|
||||||
/** MASTERCLIENTPOOL CODE **/
|
/** MASTERCLIENTPOOL CODE **/
|
||||||
|
|
||||||
void sosc::MasterClientPool::SetupQueries(db::Queries *queries) {
|
void sosc::MasterClientPool::SetupQueries(db::Queries *queries) {
|
||||||
#define QRY_USER_REG_CHECK 0
|
#define QRY_USER_NAME_REG_CHECK 0
|
||||||
queries->push_back(new db::Query(
|
queries->push_back(new db::Query(
|
||||||
"SELECT COUNT(*) FROM `USERS` "
|
"SELECT COUNT(*) FROM `USERS` "
|
||||||
"WHERE `USERNAME` = ? OR `EMAIL` = ?"
|
"WHERE `USERNAME` = ?"
|
||||||
));
|
));
|
||||||
|
|
||||||
#define QRY_USER_REGISTER 1
|
#define QRY_USER_MAIL_REG_CHECK 1
|
||||||
|
queries->push_back(new db::Query(
|
||||||
|
"SELECT COUNT(*) FROM `USERS` "
|
||||||
|
"WHERE `USERNAME` = ?"
|
||||||
|
));
|
||||||
|
|
||||||
|
#define QRY_USER_REGISTER 2
|
||||||
queries->push_back(new db::Query(
|
queries->push_back(new db::Query(
|
||||||
"INSERT INTO `USERS` "
|
"INSERT INTO `USERS` "
|
||||||
"(`USERNAME`, `PASS_HASH`, `EMAIL`, `ACTIVATED`, `JOINED`) "
|
"(`USERNAME`, `PASS_HASH`, `EMAIL`, `ACTIVATED`, `JOINED`) "
|
||||||
"VALUES (?, ?, ?, 0, CURRENT_TIMESTAMP)"
|
"VALUES (?, ?, ?, 0, CURRENT_TIMESTAMP)"
|
||||||
));
|
));
|
||||||
|
|
||||||
#define QRY_USER_NAME_EXISTS 2
|
#define QRY_USER_NAME_EXISTS 3
|
||||||
queries->push_back(new db::Query(
|
queries->push_back(new db::Query(
|
||||||
"SELECT COUNT(*) FROM `USERS` "
|
"SELECT COUNT(*) FROM `USERS` "
|
||||||
"WHERE LOWER(`USERNAME`) = LOWER(?)"
|
"WHERE LOWER(`USERNAME`) = LOWER(?)"
|
||||||
));
|
));
|
||||||
|
|
||||||
#define QRY_USER_GET_PWD_HASH 3
|
#define QRY_USER_GET_PWD_HASH 4
|
||||||
queries->push_back(new db::Query(
|
queries->push_back(new db::Query(
|
||||||
"SELECT `ID`, `PASS_HASH` FROM `USERS` "
|
"SELECT `ID`, `PASS_HASH` FROM `USERS` "
|
||||||
"WHERE LOWER(`USERNAME`) = LOWER(?)"
|
"WHERE LOWER(`USERNAME`) = LOWER(?)"
|
||||||
));
|
));
|
||||||
|
|
||||||
#define QRY_USER_GENERATE_KEY 4
|
#define QRY_USER_GENERATE_KEY 5
|
||||||
queries->push_back(new db::Query(
|
queries->push_back(new db::Query(
|
||||||
"INSERT OR IGNORE INTO `USER_KEYS` "
|
"INSERT OR IGNORE INTO `USER_KEYS` "
|
||||||
"(`ID`, `SECRET`) VALUES (?, RANDOMBLOB(128))"
|
"(`ID`, `SECRET`) VALUES (?, RANDOMBLOB(128))"
|
||||||
));
|
));
|
||||||
|
|
||||||
#define QRY_USER_GET_KEY 5
|
#define QRY_USER_GET_KEY 6
|
||||||
queries->push_back(new db::Query(
|
queries->push_back(new db::Query(
|
||||||
"SELECT `SECRET` FROM `USER_KEYS` "
|
"SELECT `SECRET` FROM `USER_KEYS` "
|
||||||
"WHERE `ID` = ?"
|
"WHERE `ID` = ?"
|
||||||
));
|
));
|
||||||
|
|
||||||
#define QRY_USER_CHECK_KEY 6
|
#define QRY_USER_CHECK_KEY 7
|
||||||
queries->push_back(new db::Query(
|
queries->push_back(new db::Query(
|
||||||
"SELECT COUNT(*) FROM `USER_KEYS` "
|
"SELECT COUNT(*) FROM `USER_KEYS` "
|
||||||
"WHERE `ID` = ? AND `SECRET` = ?"
|
"WHERE `ID` = ? AND `SECRET` = ?"
|
||||||
|
@ -88,14 +94,85 @@ bool sosc::MasterClient::ProcessLogin(Packet &pck) {
|
||||||
return true;
|
return true;
|
||||||
if(!pck.Check(2, PCK_ANY, PCK_ANY))
|
if(!pck.Check(2, PCK_ANY, PCK_ANY))
|
||||||
return false;
|
return false;
|
||||||
|
pck.TrimRegions();
|
||||||
|
|
||||||
|
db::ResultSet* results = nullptr;
|
||||||
db::Query* query = this->queries->at(QRY_USER_NAME_EXISTS);
|
db::Query* query = this->queries->at(QRY_USER_NAME_EXISTS);
|
||||||
|
query->Reset();
|
||||||
|
query->BindText(pck[0], 0);
|
||||||
|
if(query->ScalarInt32() == 0)
|
||||||
|
return LoginError(0x101);
|
||||||
|
|
||||||
|
query = this->queries->at(QRY_USER_GET_PWD_HASH);
|
||||||
|
query->Reset();
|
||||||
|
query->BindText(pck[0], 0);
|
||||||
|
results = query->GetResults();
|
||||||
|
results->Step();
|
||||||
|
|
||||||
|
int64_t user_id = results->GetInt64(0);
|
||||||
|
if(!cgc::bcrypt_check(pck[1], results->GetText(1)))
|
||||||
|
return LoginError(0x102);
|
||||||
|
|
||||||
|
query = this->queries->at(QRY_USER_GENERATE_KEY);
|
||||||
|
query->Reset();
|
||||||
|
query->BindInt64(user_id, 0);
|
||||||
|
query->NonQuery();
|
||||||
|
|
||||||
|
query = this->queries->at(QRY_USER_GET_KEY);
|
||||||
|
query->Reset();
|
||||||
|
query->BindInt64(user_id, 0);
|
||||||
|
auto secret = query->ScalarBlob();
|
||||||
|
|
||||||
|
this->sock.Send(Packet(kLoginResponse, {"\1", secret}));
|
||||||
|
this->authed = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sosc::MasterClient::ProcessRegistration(Packet &pck) {
|
bool sosc::MasterClient::LoginError(uint16_t error_code) {
|
||||||
|
if(++this->auth_attempts < MAX_AUTH_ATTEMPTS) {
|
||||||
|
this->sock.Send(
|
||||||
|
Packet(kLoginResponse, {"\0", HTONUS(error_code)})
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return this->Close(
|
||||||
|
Packet(kLoginResponse, {"\0", HTONUS(0x100)})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sosc::MasterClient::ProcessRegistration(Packet &pck) {
|
||||||
|
if(!pck.Check(3, PCK_ANY, PCK_ANY, PCK_ANY))
|
||||||
|
return false;
|
||||||
|
pck.TrimRegions();
|
||||||
|
|
||||||
|
db::Query* query = this->queries->at(QRY_USER_NAME_REG_CHECK);
|
||||||
|
query->Reset();
|
||||||
|
query->BindText(pck[0], 0);
|
||||||
|
if(query->ScalarInt32() > 0)
|
||||||
|
return RegistrationError(0x100);
|
||||||
|
|
||||||
|
query = this->queries->at(QRY_USER_MAIL_REG_CHECK);
|
||||||
|
query->Reset();
|
||||||
|
query->BindText(pck[2], 0);
|
||||||
|
if(query->ScalarInt32() > 0)
|
||||||
|
return RegistrationError(0x101);
|
||||||
|
|
||||||
|
query = this->queries->at(QRY_USER_REGISTER);
|
||||||
|
query->Reset();
|
||||||
|
query->BindText(pck[0], 0);
|
||||||
|
query->BindText(cgc::bcrypt_hash(pck[1]), 1);
|
||||||
|
query->BindText(pck[2], 2);
|
||||||
|
query->NonQuery();
|
||||||
|
|
||||||
|
this->sock.Send(Packet(kRegisterResponse, {"\1", 0x000}));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sosc::MasterClient::RegistrationError(uint16_t error_code) {
|
||||||
|
this->sock.Send(
|
||||||
|
Packet(kRegisterResponse, {"\0", HTONUS(error_code)})
|
||||||
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,23 +152,23 @@ bool sosc::MasterIntra::Authentication(sosc::Packet& pck) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sosc::MasterIntra::AuthenticationFailure
|
bool sosc::MasterIntra::AuthenticationFailure
|
||||||
(const std::string& packetId, uint16_t errorCode)
|
(const std::string& packet_id, uint16_t error_code)
|
||||||
{
|
{
|
||||||
if(++this->auth_attempts < MAX_AUTH_ATTEMPTS) {
|
if(++this->auth_attempts < MAX_AUTH_ATTEMPTS) {
|
||||||
this->sock.Send(
|
this->sock.Send(
|
||||||
Packet(kNegativeAck, { packetId , net::htonv(errorCode) })
|
Packet(kNegativeAck, { packet_id , net::htonv(error_code) })
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return this->Close(
|
return this->Close(
|
||||||
Packet(kNegativeAck, { packetId, net::htonv<uint16_t>(0x100) })
|
Packet(kNegativeAck, { packet_id, net::htonv<uint16_t>(0x100) })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sosc::MasterIntra::NotAuthorized(const std::string& packetId) {
|
bool sosc::MasterIntra::NotAuthorized(const std::string& packet_id) {
|
||||||
return this->Close(
|
return this->Close(
|
||||||
Packet(kNegativeAck, { packetId, net::htonv<uint16_t>(0x200) })
|
Packet(kNegativeAck, { packet_id, net::htonv<uint16_t>(0x200) })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,8 +65,6 @@ void configure_poolinfo(sosc::poolinfo_t* info,
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
using namespace sosc;
|
using namespace sosc;
|
||||||
if(argc < 2)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ini::File* config;
|
ini::File* config;
|
||||||
try {
|
try {
|
||||||
|
@ -105,7 +103,7 @@ int main(int argc, char **argv) {
|
||||||
poolinfo_t info;
|
poolinfo_t info;
|
||||||
configure_poolinfo(&_ctx.default_info, (*config)["defaults"][0]);
|
configure_poolinfo(&_ctx.default_info, (*config)["defaults"][0]);
|
||||||
|
|
||||||
if((*config)["master"]["run master"]) {
|
if((*config)["general"]["run master"]) {
|
||||||
if(!config->HasSection("master to client") ||
|
if(!config->HasSection("master to client") ||
|
||||||
!config->HasSection("master to slave"))
|
!config->HasSection("master to slave"))
|
||||||
{
|
{
|
||||||
|
@ -122,13 +120,13 @@ int main(int argc, char **argv) {
|
||||||
configure_poolinfo(&info, (*config)["master to slave"][0]);
|
configure_poolinfo(&info, (*config)["master to slave"][0]);
|
||||||
_ctx.master_intra = new master_intra_ctx;
|
_ctx.master_intra = new master_intra_ctx;
|
||||||
master_intra_start(
|
master_intra_start(
|
||||||
(uint16_t)(*config)["master"]["intra port"], info
|
(uint16_t)(*config)["master to slave"]["port"], info
|
||||||
);
|
);
|
||||||
|
|
||||||
configure_poolinfo(&info, (*config)["master to client"][0]);
|
configure_poolinfo(&info, (*config)["master to client"][0]);
|
||||||
_ctx.master_client = new master_client_ctx;
|
_ctx.master_client = new master_client_ctx;
|
||||||
master_client_start(
|
master_client_start(
|
||||||
(uint16_t)(*config)["master"]["client port"], info
|
(uint16_t)(*config)["master to client"]["port"], info
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue