CashWorld-Server/CashWorldServer.cpp

247 lines
10 KiB
C++
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

// 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;
}