123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- #ifndef __SERVER_HPP__
- #define __SERVER_HPP__
- #include "util.hpp"
- #include "db.hpp"
- #include "online.hpp"
- #include "room.hpp"
- #include "matcher.hpp"
- #include "session.hpp"
- #define WWWROOT "./wwwroot"
- typedef websocketpp::server<websocketpp::config::asio> wsserver_t;
- class gobang_server {
- private:
-
- void file_handler(wsserver_t::connection_ptr conn) {
-
- websocketpp::http::parser::request req = conn->get_request();
- std::string uri = req.get_uri();
-
- std::string pathname = _wwwroot + uri;
- if(pathname.back() == '/') {
- pathname += "login.html";
- }
-
- std::string body;
- if(file_util::read(pathname.c_str(), body) == false) {
- body += "<html><head><meta charset='UTF-8'/></head><body><h1> 404 Not Found </h1></body></html>";
-
- conn->set_status(websocketpp::http::status_code::not_found);
- }
- else conn->set_status(websocketpp::http::status_code::ok);
-
- conn->append_header("Content-Length", std::to_string(body.size()));
-
- conn->set_body(body);
- }
-
- void http_resp(wsserver_t::connection_ptr conn, bool result, websocketpp::http::status_code::value code, const std::string &reason) {
-
- Json::Value resp;
- std::string resp_body;
- resp["result"] = result;
- resp["reason"] = reason;
- json_util::serialize(resp, resp_body);
-
- conn->set_status(code);
- conn->append_header("Content-Type", "application/json");
- conn->set_body(resp_body);
- }
-
- void reg(wsserver_t::connection_ptr conn) {
-
- std::string req_body = conn->get_request_body();
-
- Json::Value user_info;
- if(json_util::deserialize(req_body, user_info) == false) {
- return http_resp(conn, false, websocketpp::http::status_code::bad_request, "请求正文格式错误");
- }
-
- if(user_info["username"].isNull() || user_info["password"].isNull()) {
- return http_resp(conn, false, websocketpp::http::status_code::bad_request, "请输入用户名/密码");
- }
- if(_ut.registers(user_info) == false) {
- return http_resp(conn, false, websocketpp::http::status_code::bad_request, "该用户名已被占用");
- }
- return http_resp(conn, true, websocketpp::http::status_code::ok, "用户注册成功");
- }
-
- void login(wsserver_t::connection_ptr conn) {
-
- std::string req_body = conn->get_request_body();
- Json::Value user_info;
- if(json_util::deserialize(req_body, user_info) == false) {
- return http_resp(conn, false, websocketpp::http::status_code::bad_request, "请求正文格式错误");
- }
- if(user_info["username"].isNull() || user_info["password"].isNull()) {
- return http_resp(conn, false, websocketpp::http::status_code::bad_request, "请输入用户名/密码");
- }
-
- if(_ut.login(user_info) == false) {
- return http_resp(conn, false, websocketpp::http::status_code::bad_request, "用户名/密码错误");
- }
-
- session_ptr ssp = _sm.create_session(user_info["id"].asUInt64());
- if(ssp.get() == nullptr) {
- return http_resp(conn, false, websocketpp::http::status_code::internal_server_error, "用户会话创建失败");
- }
- _sm.set_session_expire_time(ssp->get_ssid(), SESSION_TIMEOUT);
-
- std::string cookie_ssid = "SSID=" + std::to_string(ssp->get_ssid());
- conn->append_header("Set-Cookie", cookie_ssid);
- return http_resp(conn, true, websocketpp::http::status_code::ok, "用户登录成功");
- }
-
- bool get_cookie_val(const std::string &cookie_str, const std::string &key, std::string &val) {
-
-
- std::vector<std::string> cookies;
- string_util::split(cookie_str, ";", cookies);
-
- for(const auto cookie : cookies) {
- std::vector<std::string> kv;
- string_util::split(cookie, "=", kv);
- if(kv.size() != 2) continue;
- if(kv[0] == key) {
- val = kv[1];
- return true;
- }
- }
- return false;
- }
-
- void info(wsserver_t::connection_ptr conn) {
-
- std::string cookie_str = conn->get_request_header("Cookie");
- if(cookie_str.empty()) {
- return http_resp(conn, false, websocketpp::http::status_code::bad_request, "找不到Cookie信息,请重新登录");
- }
- std::string ssid_str;
- if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) {
- return http_resp(conn, false, websocketpp::http::status_code::bad_request, "找不到Session信息,请重新登录");
- }
-
- session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
- if(ssp.get() == nullptr) {
- return http_resp(conn, false, websocketpp::http::status_code::bad_request, "Session已过期,请重新登录");
- }
-
- uint64_t uid = ssp->get_user();
- Json::Value user;
- if(_ut.select_by_id(uid, user) == false) {
- return http_resp(conn, false, websocketpp::http::status_code::bad_request, "用户信息不存在");
- }
-
- std::string body;
- json_util::serialize(user, body);
- std::string resp_cookie = "SSID=" + ssid_str;
- conn->set_status(websocketpp::http::status_code::ok);
- conn->append_header("Content-Type", "application/json");
- conn->append_header("Set-Cookie", resp_cookie);
- conn->set_body(body);
-
- _sm.set_session_expire_time(ssp->get_ssid(), SESSION_TIMEOUT);
- }
- private:
-
- void http_callback(websocketpp::connection_hdl hdl) {
-
- wsserver_t::connection_ptr conn = _wssrv.get_con_from_hdl(hdl);
- websocketpp::http::parser::request req = conn->get_request();
- std::string method = req.get_method();
- std::string uri = req.get_uri();
-
-
- if(method == "POST" && uri == "/reg") reg(conn);
- else if(method == "POST" && uri == "/login") login(conn);
- else if(method == "GET" && uri == "/info") info(conn);
-
- else file_handler(conn);
- }
-
- void game_hall_resp(wsserver_t::connection_ptr conn, bool result, const std::string &reason = "") {
- Json::Value resp;
- resp["optype"] = "hall_ready";
- resp["result"] = result;
-
- if(result == false) resp["reason"] = reason;
- std::string body;
- json_util::serialize(resp, body);
- conn->send(body);
- }
-
- void wsopen_game_hall(wsserver_t::connection_ptr conn) {
-
-
- std::string cookie_str = conn->get_request_header("Cookie");
- if(cookie_str.empty()) {
- return game_hall_resp(conn, false, "找不到Cookie信息,请重新登录");
- }
- std::string ssid_str;
- if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) {
- return game_hall_resp(conn, false, "找不到Session信息,请重新登录");
- }
-
- session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
- if(ssp.get() == nullptr) {
- return game_hall_resp(conn, false, "Session已过期,请重新登录");
- }
-
- uint64_t uid = ssp->get_user();
-
- if(_om.is_in_game_hall(uid) == true) {
- return game_hall_resp(conn, false, "玩家重复登录");
- }
-
- _om.enter_game_hall(uid, conn);
-
- game_hall_resp(conn, true);
-
- _sm.set_session_expire_time(ssp->get_ssid(), SESSION_FOREVER);
- }
-
- void game_room_resp(wsserver_t::connection_ptr conn, bool result, const std::string &reason,
- uint64_t room_id = 0, uint64_t self_id = 0, uint64_t white_id = 0, uint64_t black_id = 0) {
- Json::Value resp;
- resp["optype"] = "room_ready";
- resp["result"] = result;
-
- if(result == true) {
- resp["room_id"] = (Json::UInt64)room_id;
- resp["uid"] = (Json::UInt64)self_id;
- resp["white_id"] = (Json::UInt64)white_id;
- resp["black_id"] = (Json::UInt64)black_id;
- }
- else resp["reason"] = reason;
- std::string body;
- json_util::serialize(resp, body);
- conn->send(body);
- }
-
- void wsopen_game_room(wsserver_t::connection_ptr conn) {
-
- std::string cookie_str = conn->get_request_header("Cookie");
- if(cookie_str.empty()) {
- return game_room_resp(conn, false, "找不到Cookie信息,请重新登录");
- }
- std::string ssid_str;
- if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) {
- return game_room_resp(conn, false, "找不到Session信息,请重新登录");
- }
-
- session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
- if(ssp.get() == nullptr) {
- return game_room_resp(conn, false, "Session已过期,请重新登录");
- }
-
- if(_om.is_in_game_hall(ssp->get_user()) || _om.is_in_game_room(ssp->get_user())) {
- return game_room_resp(conn, false, "玩家重复登录");
- }
-
- room_ptr rp = _rm.get_room_by_uid(ssp->get_user());
- if(rp.get() == nullptr) {
- return game_room_resp(conn, false, "找不到房间信息");
- }
-
- _om.enter_game_room(ssp->get_user(), conn);
-
- game_room_resp(conn, true, "", rp->_room_id, ssp->get_user(), rp->_white_user_id, rp->_black_user_id);
-
- _sm.set_session_expire_time(ssp->get_ssid(), SESSION_FOREVER);
- }
-
- void wsopen_callback(websocketpp::connection_hdl hdl) {
-
- wsserver_t::connection_ptr conn = _wssrv.get_con_from_hdl(hdl);
- websocketpp::http::parser::request req = conn->get_request();
- std::string uri = req.get_uri();
-
- if(uri == "/hall") wsopen_game_hall(conn);
- else if(uri == "/room") wsopen_game_room(conn);
- }
-
- void wsclose_game_hall(wsserver_t::connection_ptr conn) {
-
- std::string cookie_str = conn->get_request_header("Cookie");
- if(cookie_str.empty()) return;
- std::string ssid_str;
- if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) return;
- session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
- if(ssp.get() == nullptr) return;
-
- _om.exit_game_hall(ssp->get_user());
-
- _sm.set_session_expire_time(ssp->get_ssid(), SESSION_TIMEOUT);
- }
-
- void wsclose_game_room(wsserver_t::connection_ptr conn) {
-
- std::string cookie_str = conn->get_request_header("Cookie");
- if(cookie_str.empty()) return;
- std::string ssid_str;
- if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) return;
- session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
- if(ssp.get() == nullptr) return;
-
- _om.exit_game_room(ssp->get_user());
-
- _rm.remove_room_user(ssp->get_user());
-
- _sm.set_session_expire_time(ssp->get_ssid(), SESSION_TIMEOUT);
- }
-
- void wsclose_callback(websocketpp::connection_hdl hdl) {
-
- wsserver_t::connection_ptr conn = _wssrv.get_con_from_hdl(hdl);
- websocketpp::http::parser::request req = conn->get_request();
- std::string uri = req.get_uri();
-
- if(uri == "/hall") wsclose_game_hall(conn);
- else if(uri == "/room") wsclose_game_room(conn);
- }
-
- void wsmsg_game_hall(wsserver_t::connection_ptr conn, wsserver_t::message_ptr msg) {
-
- std::string cookie_str = conn->get_request_header("Cookie");
- if(cookie_str.empty()) {
- return game_hall_resp(conn, false, "找不到Cookie信息,请重新登录");
- }
- std::string ssid_str;
- if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) {
- return game_hall_resp(conn, false, "找不到Session信息,请重新登录");
- }
- session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
- if(ssp.get() == nullptr) {
- return game_hall_resp(conn, false, "Session已过期,请重新登录");
- }
-
- std::string req_msg_body = msg->get_payload();
- Json::Value req_msg;
- if(json_util::deserialize(req_msg_body, req_msg) == false) {
- return game_hall_resp(conn, false, "请求信息解析失败");
- }
-
- Json::Value resp = req_msg;
- std::string resp_body;
-
- if(req_msg["optype"].isNull() == false && req_msg["optype"].asString() == "match_start") {
- _mm.add(ssp->get_user());
- resp["result"] = true;
- json_util::serialize(resp, resp_body);
- conn->send(resp_body);
- } else if(req_msg["optype"].isNull() == false && req_msg["optype"].asString() == "match_stop") {
- _mm.remove(ssp->get_user());
- resp["result"] = true;
- json_util::serialize(resp, resp_body);
- conn->send(resp_body);
- } else {
- resp["optype"] = "unknown";
- resp["result"] = false;
- json_util::serialize(resp, resp_body);
- conn->send(resp_body);
- }
- }
-
- void wsmsg_game_room(wsserver_t::connection_ptr conn, wsserver_t::message_ptr msg) {
-
- std::string cookie_str = conn->get_request_header("Cookie");
- if(cookie_str.empty()) {
- return game_room_resp(conn, false, "找不到Cookie信息,请重新登录");
- }
- std::string ssid_str;
- if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) {
- return game_room_resp(conn, false, "找不到Session信息,请重新登录");
- }
- session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
- if(ssp.get() == nullptr) {
- return game_room_resp(conn, false, "Session已过期,请重新登录");
- }
-
- room_ptr rp = _rm.get_room_by_uid(ssp->get_user());
- if(rp.get() == nullptr) {
- return game_room_resp(conn, false, "找不到房间信息");
- }
-
- std::string req_msg_body = msg->get_payload();
- Json::Value req_msg;
- if(json_util::deserialize(req_msg_body, req_msg) == false) {
- return game_room_resp(conn, false, "请求信息解析失败");
- }
-
- rp->handler(req_msg);
- }
-
- void wsmsg_callback(websocketpp::connection_hdl hdl, wsserver_t::message_ptr msg) {
-
- wsserver_t::connection_ptr conn = _wssrv.get_con_from_hdl(hdl);
- websocketpp::http::parser::request req = conn->get_request();
- std::string uri = req.get_uri();
-
- if(uri == "/hall") wsmsg_game_hall(conn, msg);
- else if(uri == "/room") wsmsg_game_room(conn, msg);
- }
- public:
-
- gobang_server(const std::string &host, const std::string &user, const std::string &passwd, \
- const std::string db = "gobang", uint16_t port = 4106)
- : _wwwroot(WWWROOT), _ut(host, user, passwd, db, port), _sm(&_wssrv), _rm(&_ut, &_om), _mm(&_ut, &_om, &_rm) {
-
- _wssrv.set_access_channels(websocketpp::log::alevel::none);
-
- _wssrv.init_asio();
-
- _wssrv.set_http_handler(std::bind(&gobang_server::http_callback, this, std::placeholders::_1));
- _wssrv.set_open_handler(std::bind(&gobang_server::wsopen_callback, this, std::placeholders::_1));
- _wssrv.set_close_handler(std::bind(&gobang_server::wsclose_callback, this, std::placeholders::_1));
- _wssrv.set_message_handler(std::bind(&gobang_server::wsmsg_callback, this, std::placeholders::_1, std::placeholders::_2));
- }
-
- void start(uint16_t port) {
-
- _wssrv.listen(port);
- _wssrv.set_reuse_addr(true);
-
- _wssrv.start_accept();
-
- _wssrv.run();
- }
- private:
- std::string _wwwroot;
- user_table _ut;
- session_manager _sm;
- online_manager _om;
- room_manager _rm;
- matcher _mm;
- wsserver_t _wssrv;
- };
- #endif
|