247 lines
10 KiB
C++
247 lines
10 KiB
C++
// CashWorld Server
|
||
#include <cstdio>
|
||
#include <cstdlib>
|
||
#include <cstring>
|
||
#include <memory>
|
||
#include <map>
|
||
#include <vector>
|
||
#include <ctime>
|
||
#include <mutex>
|
||
#include "GSock/gsock.h"
|
||
#include "GSock/gsock_helper.h"
|
||
#include "NaiveThreadPool/ThreadPool.h"
|
||
using namespace std;
|
||
|
||
const int PORT_CHECK = 59401;
|
||
const int PORT_LOGIN = 59402;
|
||
const int PORT_GAME = 59402;
|
||
|
||
struct UserData
|
||
{
|
||
string name;
|
||
string pass;
|
||
|
||
int cash;
|
||
};
|
||
|
||
vector<shared_ptr<UserData>> user_vec;
|
||
mutex user_vec_lock;
|
||
|
||
map<string, shared_ptr<UserData>> uuid_map;
|
||
mutex uuid_map_lock;
|
||
|
||
string GenerateUUID()
|
||
{
|
||
const char* x = "ABCDEFGHIJKLMOPQRSTUVWXYZ0123456789";
|
||
int len = strlen(x);
|
||
string s;
|
||
for (int i = 0; i < 16; i++)
|
||
{
|
||
s.push_back(x[rand() % len]);
|
||
}
|
||
return s;
|
||
}
|
||
|
||
void server_user_login(sock& s)
|
||
{
|
||
sock_helper sh(s);
|
||
string uname, upass;
|
||
if (sh.recvline(uname) < 0 || sh.recvline(upass) < 0)
|
||
{
|
||
return;
|
||
}
|
||
unique_lock<mutex> ulk(user_vec_lock);
|
||
int sz = user_vec.size();
|
||
for (int i = 0; i < sz; i++)
|
||
{
|
||
if (user_vec[i]->name == uname)
|
||
{
|
||
if (user_vec[i]->pass == upass)
|
||
{
|
||
// Login OK
|
||
shared_ptr<UserData> tmp = user_vec[i];
|
||
ulk.unlock();
|
||
|
||
string uuid;
|
||
while (true)
|
||
{
|
||
uuid = GenerateUUID();
|
||
unique_lock<mutex> ulkx(uuid_map_lock);
|
||
if (uuid_map.find(uuid) != uuid_map.end()) continue;
|
||
uuid_map.insert(make_pair(uuid, tmp));
|
||
break;
|
||
}
|
||
sh.sendline("login_ok");
|
||
sh.sendline(uuid);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
sh.sendline("login_failed");
|
||
}
|
||
|
||
void server_get_self_profile(sock& s)
|
||
{
|
||
sock_helper sh(s);
|
||
string ucode;
|
||
if (sh.recvline(ucode) < 0)
|
||
{
|
||
return;
|
||
}
|
||
unique_lock<mutex> ulk(uuid_map_lock);
|
||
auto iter = uuid_map.find(ucode);
|
||
if (iter != uuid_map.end())
|
||
{
|
||
string name=iter->second->name;
|
||
int cash = iter->second->cash;
|
||
ulk.unlock();
|
||
|
||
char xbuff[64] = { 0 };
|
||
sprintf(xbuff, "%d", cash);
|
||
|
||
sh.sendline("my_profile_ok");
|
||
sh.sendline(name);
|
||
sh.sendline(xbuff);
|
||
}
|
||
else
|
||
{
|
||
ulk.unlock();
|
||
sh.sendline("invalid_cert");
|
||
}
|
||
}
|
||
|
||
void server_game_guess_number(sock& s)
|
||
{
|
||
sock_helper sh(s);
|
||
string ucode;
|
||
if (sh.recvline(ucode) < 0)
|
||
{
|
||
return;
|
||
}
|
||
unique_lock<mutex> ulk(uuid_map_lock);
|
||
auto iter = uuid_map.find(ucode);
|
||
if (iter != uuid_map.end())
|
||
{
|
||
int cash = iter->second->cash;
|
||
ulk.unlock();
|
||
|
||
string data;
|
||
if (sh.recvline(data) < 0)
|
||
{
|
||
return;
|
||
}
|
||
int val, low, high, guess;
|
||
if (sscanf(data.c_str(), "%d %d %d %d", &val, &low, &high, &guess) != 4)
|
||
{
|
||
sh.sendline("guess_number_error");
|
||
sh.sendline("invalid parameters");
|
||
return;
|
||
}
|
||
|
||
if (val > cash)
|
||
{
|
||
sh.sendline("guess_number_error");
|
||
sh.sendline("Wrong parameter: val");
|
||
return;
|
||
}
|
||
|
||
sh.sendline("guess_number_ok");
|
||
int target = rand() % (high - low) + low;
|
||
double guess_rate = 1.0 / (high - low + 1);
|
||
double guess_reward_rate = 0.01 / guess_rate;
|
||
int reward = val * guess_reward_rate;
|
||
|
||
if (target == guess)
|
||
{
|
||
sh.sendline("guessed");
|
||
|
||
iter->second->cash += reward;
|
||
}
|
||
else
|
||
{
|
||
sh.sendline("failed");
|
||
|
||
iter->second->cash -= val;
|
||
}
|
||
}
|
||
}
|
||
|
||
void server_main(sock& s)
|
||
{
|
||
sock_helper sh(s);
|
||
string cmd;
|
||
if (sh.recvline(cmd) <= 0)
|
||
{
|
||
return;
|
||
}
|
||
if (cmd == "user_login")
|
||
{
|
||
server_user_login(s);
|
||
}
|
||
else if (cmd == "get_my_profile")
|
||
{
|
||
server_get_self_profile(s);
|
||
}
|
||
else if (cmd == "game_guess_number")
|
||
{
|
||
server_game_guess_number(s);
|
||
}
|
||
}
|
||
|
||
void InitUserData()
|
||
{
|
||
shared_ptr<UserData> a(new UserData);
|
||
a->name = "testA";
|
||
a->pass = "testApwd";
|
||
a->cash = 1000;
|
||
|
||
shared_ptr<UserData> b(new UserData);
|
||
b->name = "testB";
|
||
b->pass = "testBpwd";
|
||
b->cash = 2000;
|
||
|
||
user_vec.push_back(a);
|
||
user_vec.push_back(b);
|
||
}
|
||
|
||
int main()
|
||
{
|
||
srand(time(NULL));
|
||
InitUserData();
|
||
|
||
ThreadPool tp(10);
|
||
|
||
serversock t;
|
||
if (t.bind(PORT_LOGIN) < 0 || t.listen(10) < 0)
|
||
{
|
||
printf("Failed to start server.\n");
|
||
return 0;
|
||
}
|
||
|
||
while (true)
|
||
{
|
||
sock* ps = new sock;
|
||
|
||
if (t.accept(*ps) < 0)
|
||
{
|
||
printf("Failed to accept.\n");
|
||
break;
|
||
}
|
||
|
||
if (tp.start([ps](){
|
||
server_main(*ps);
|
||
delete ps;
|
||
}) < 0)
|
||
{
|
||
printf("Failed to start job.\n");
|
||
}
|
||
else
|
||
{
|
||
printf("Job started.\n");
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|