Cavoke  1.1.0
A Platform for creating and hosting multiplayer turn-based board games
Loading...
Searching...
No Matches
main.cpp
1#include <drogon/HttpAppFramework.h>
2#include <boost/algorithm/string/join.hpp>
3#include <boost/program_options.hpp>
4#include <boost/range/adaptor/transformed.hpp>
5#include "controllers/games_controller.h"
6#include "controllers/rooms_controller.h"
7#include "controllers/sessions_controller.h"
8#include "controllers/state_controller.h"
9#include "controllers/statistics_controller.h"
10#include "model/games/games_storage.h"
11#include "model/logic/game_logic_manager.h"
12#include "model/rooms/rooms_storage.h"
13#include "model/sessions/sessions_storage.h"
14#include "model/statistics/statistics_manager.h"
15
16namespace cavoke::server {
17void run(const model::GamesStorageConfig &games_storage_config) {
18 // TODO: logging
19
20 // init models
21 std::cout << "Initialize models..." << std::endl;
22 auto games_storage =
23 std::make_shared<model::GamesStorage>(games_storage_config);
24 auto game_logic_manager =
25 std::make_shared<model::GameLogicManager>(games_storage);
26 auto game_state_storage = std::make_shared<model::GameStateStorage>();
27 auto sessions_storage = std::make_shared<model::SessionsStorage>(
28 game_logic_manager, games_storage, game_state_storage);
29 auto statistics_manager = std::make_shared<model::StatisticsManager>(
30 sessions_storage, games_storage);
31 auto rooms_storage =
32 std::make_shared<model::RoomsStorage>(sessions_storage);
33
34 // init controllers
35 std::cout << "Initialize controllers..." << std::endl;
36 auto games_controller =
37 std::make_shared<controllers::GamesController>(games_storage);
38 auto state_controller = std::make_shared<controllers::StateController>(
39 games_storage, game_logic_manager, game_state_storage,
40 sessions_storage);
41 auto sessions_controller =
42 std::make_shared<controllers::SessionsController>(
43 games_storage, game_logic_manager, game_state_storage,
44 sessions_storage);
45 auto statistics_controller =
46 std::make_shared<controllers::StatisticsController>(games_storage,
47 statistics_manager);
48 auto rooms_controller = std::make_shared<controllers::RoomsController>(
49 rooms_storage, games_storage, sessions_storage);
50
51 auto &app = drogon::app();
52
53 // register controllers
54 app.registerController(games_controller);
55 app.registerController(state_controller);
56 app.registerController(sessions_controller);
57 app.registerController(statistics_controller);
58 app.registerController(rooms_controller);
59
60 // print db and listeners on start
61 app.registerBeginningAdvice([]() {
62 auto dbclient = drogon::app().getDbClient();
63 dbclient->connectionInfo();
64 std::cout << "Database connection: "
65 << (dbclient == nullptr
66 ? "FAILED"
67 : hide_password(dbclient->connectionInfo()))
68 << std::endl;
69
70 auto listeners = drogon::app().getListeners();
71 std::string ips =
72 listeners.empty()
73 ? "<NO LISTENERS>"
74 : boost::join(
75 listeners | boost::adaptors::transformed(
76 [](const trantor::InetAddress &e) {
77 return e.toIpPort();
78 }),
79 ", ");
80 std::cout << "Listening at " << ips << "... " << std::endl;
81 });
82
83 // Add CORS handler
84 auto corsValue = nlohmann::to_nlohmann(drogon::app().getCustomConfig())
85 .value("cors", "*");
86 app.registerPostHandlingAdvice(
87 [corsValue](const drogon::HttpRequestPtr &req,
88 const drogon::HttpResponsePtr &resp) {
89 // cors header for every response
90 resp->addHeader("Access-Control-Allow-Origin", corsValue);
91 });
92
93 // start server
94 app.run();
95}
96} // namespace cavoke::server
97
98namespace po = boost::program_options;
99
100int main(int argc, char *argv[]) {
101 po::options_description desc("Allowed options");
102 auto add_desc_options = desc.add_options();
103 add_desc_options("help,h", "Print help");
104 add_desc_options("config-file,c", po::value<std::string>(),
105 "File with game storage configuration");
106 add_desc_options("port,p", po::value<uint16_t>()->default_value(8080),
107 "TCP/IP port number for connection");
108
109 po::variables_map vm;
110 po::store(po::parse_command_line(argc, argv, desc), vm);
111 po::notify(vm);
112
113 if (vm.count("help")) {
114 std::cout << desc << "\n";
115 return 0;
116 }
117
119 if (vm.count("config-file")) {
120 // load from file
121 try {
122 std::string file = vm["config-file"].as<std::string>();
123 drogon::app().loadConfigFile(file);
124 games_storage_config =
125 nlohmann::to_nlohmann(drogon::app().getCustomConfig())
126 .at("storage")
128 std::cout << "Server configuration loaded from: '" << file << "'\n";
129 } catch (const std::exception &err) {
130 std::cerr
131 << "Failed to load games storage configuration from file: "
132 << err.what() << '\n';
133 return 1;
134 }
135 } else {
136 // use default one
137 std::cerr
138 << "No server configuration file specified. Using a default "
139 "one.\nWARNING: No database requests will succeed.\nPlease use "
140 "`-c` option to specify config file.\n";
141 // default configuration
142 games_storage_config = {"../../local_server/games", "logic",
143 "client.zip", "config.json"};
144 }
145
146 if (vm.count("port")) {
147 uint16_t port = vm.at("port").as<uint16_t>();
148 drogon::app().addListener("0.0.0.0", port);
149 }
150
151 cavoke::server::run(games_storage_config);
152 return 0;
153}