summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--CMakeLists.txt3
-rw-r--r--database.cpp91
-rw-r--r--database.h40
-rw-r--r--server_main.cpp94
m---------vendor/stduuid0
6 files changed, 16 insertions, 215 deletions
diff --git a/.gitmodules b/.gitmodules index de49c9f..2f929e3 100644 --- a/.gitmodules +++ b/.gitmodules
@@ -10,6 +10,3 @@
10[submodule "vendor/base64"] 10[submodule "vendor/base64"]
11 path = vendor/base64 11 path = vendor/base64
12 url = https://github.com/tobiaslocker/base64 12 url = https://github.com/tobiaslocker/base64
13[submodule "vendor/stduuid"]
14 path = vendor/stduuid
15 url = https://github.com/mariusbancila/stduuid
diff --git a/CMakeLists.txt b/CMakeLists.txt index b1a7b38..82e9d64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -16,7 +16,6 @@ include_directories(
16 vendor/hkutil 16 vendor/hkutil
17 vendor/asio/asio/include 17 vendor/asio/asio/include
18 vendor/base64/include 18 vendor/base64/include
19 vendor/stduuid
20 ${tesseract_INCLUDE_DIRS} 19 ${tesseract_INCLUDE_DIRS}
21 ${lept_INCLUDE_DIRS} 20 ${lept_INCLUDE_DIRS}
22 ${GraphicsMagick_INCLUDE_DIRS} 21 ${GraphicsMagick_INCLUDE_DIRS}
@@ -52,7 +51,7 @@ target_link_libraries(
52 wizard 51 wizard
53) 52)
54 53
55add_executable(wizard_server database.cpp server_main.cpp) 54add_executable(wizard_server server_main.cpp)
56set_property(TARGET wizard_server PROPERTY CXX_STANDARD 17) 55set_property(TARGET wizard_server PROPERTY CXX_STANDARD 17)
57set_property(TARGET wizard_server PROPERTY CXX_STANDARD_REQUIRED ON) 56set_property(TARGET wizard_server PROPERTY CXX_STANDARD_REQUIRED ON)
58target_link_libraries( 57target_link_libraries(
diff --git a/database.cpp b/database.cpp deleted file mode 100644 index 037579b..0000000 --- a/database.cpp +++ /dev/null
@@ -1,91 +0,0 @@
1#include "database.h"
2
3#include <include/uuid.h>
4
5#include <stdexcept>
6
7std::string database::create(std::mt19937& rng) {
8 std::lock_guard state_guard(mutex_);
9
10 std::string token = uuids::to_string(uuids::uuid_random_generator{rng}());
11 requests_[token] = request{};
12
13 return token;
14}
15
16void database::subscribe(const std::string& token,
17 subscribe_callback_type callback) {
18 std::lock_guard state_guard(mutex_);
19
20 if (!requests_.count(token)) {
21 throw std::invalid_argument("Could not find request.");
22 }
23
24 request& req = requests_[token];
25 size_t nextId = req.subscribers.size();
26 req.subscribers.push_back(callback);
27}
28
29void database::post(const std::string& token, const std::string& msg) {
30 std::lock_guard state_guard(mutex_);
31
32 if (!requests_.count(token)) {
33 throw std::invalid_argument("Could not find request.");
34 }
35
36 request& req = requests_.at(token);
37
38 for (std::optional<subscribe_callback_type>& callback : req.subscribers) {
39 if (callback) {
40 try {
41 (*callback)(msg);
42 } catch (const std::exception& ex) {
43 callback = std::nullopt;
44 }
45 }
46 }
47}
48
49void database::setResult(const std::string& token, const std::string& result) {
50 std::lock_guard state_guard(mutex_);
51
52 if (!requests_.count(token)) {
53 throw std::invalid_argument("Could not find request.");
54 }
55
56 request& req = requests_[token];
57 req.result = result;
58}
59
60const std::string& database::getResult(const std::string& token) {
61 std::lock_guard state_guard(mutex_);
62
63 if (!requests_.count(token)) {
64 throw std::invalid_argument("Could not find request.");
65 }
66
67 const request& req = requests_.at(token);
68 return req.result;
69}
70
71void database::mark_done(const std::string& token) {
72 std::lock_guard state_guard(mutex_);
73
74 if (!requests_.count(token)) {
75 throw std::invalid_argument("Could not find request.");
76 }
77
78 request& req = requests_[token];
79 req.done = true;
80}
81
82bool database::is_done(const std::string& token) {
83 std::lock_guard state_guard(mutex_);
84
85 if (!requests_.count(token)) {
86 throw std::invalid_argument("Could not find request.");
87 }
88
89 const request& req = requests_.at(token);
90 return req.done;
91}
diff --git a/database.h b/database.h deleted file mode 100644 index d8d9b67..0000000 --- a/database.h +++ /dev/null
@@ -1,40 +0,0 @@
1#ifndef DATABASE_H_0A27B356
2#define DATABASE_H_0A27B356
3
4#include <functional>
5#include <map>
6#include <mutex>
7#include <optional>
8#include <random>
9#include <string>
10#include <vector>
11
12class database {
13 public:
14 // Feel free to throw an exception if the subscriber should be killed.
15 using subscribe_callback_type = std::function<void(const std::string&)>;
16
17 std::string create(std::mt19937& rng);
18
19 void subscribe(const std::string& token, subscribe_callback_type callback);
20 void post(const std::string& token, const std::string& msg);
21
22 void setResult(const std::string& token, const std::string& result);
23 const std::string& getResult(const std::string& token);
24
25 void mark_done(const std::string& token);
26 bool is_done(const std::string& token);
27
28 private:
29 struct request {
30 std::vector<std::optional<subscribe_callback_type>> subscribers;
31 std::string result;
32 bool done = false;
33 };
34
35 std::mutex mutex_;
36
37 std::map<std::string, request> requests_;
38};
39
40#endif /* end of include guard: DATABASE_H_0A27B356 */
diff --git a/server_main.cpp b/server_main.cpp index 145f8a2..00a4e7a 100644 --- a/server_main.cpp +++ b/server_main.cpp
@@ -12,7 +12,6 @@
12#include <websocketpp/server.hpp> 12#include <websocketpp/server.hpp>
13 13
14#include "cardset.h" 14#include "cardset.h"
15#include "database.h"
16#include "imagestore.h" 15#include "imagestore.h"
17#include "wizard.h" 16#include "wizard.h"
18 17
@@ -67,8 +66,6 @@ class server {
67 std::string cmd = msgJson["cmd"]; 66 std::string cmd = msgJson["cmd"];
68 if (cmd == "generate") { 67 if (cmd == "generate") {
69 cmd_generate(connection, msgJson["text"]); 68 cmd_generate(connection, msgJson["text"]);
70 } else if (cmd == "check") {
71 cmd_check(connection, msgJson["token"]);
72 } else { 69 } else {
73 std::string response = R"( 70 std::string response = R"(
74 { 71 {
@@ -84,71 +81,11 @@ class server {
84 } 81 }
85 82
86 void cmd_generate(websocketpp::connection_hdl connection, std::string text) { 83 void cmd_generate(websocketpp::connection_hdl connection, std::string text) {
87 std::string token; 84 asio::post(std::bind(&server::generate_thread, this, connection, text));
88
89 {
90 std::lock_guard rng_guard(rng_mutex_);
91 token = database_.create(rng_);
92 }
93
94 nlohmann::json tokenMsg;
95 tokenMsg["type"] = "token";
96 tokenMsg["token"] = token;
97 socket_.send(connection, tokenMsg.dump(),
98 websocketpp::frame::opcode::value::TEXT);
99
100 database_.subscribe(token, [this, connection](const std::string& msg) {
101 socket_.send(connection, msg, websocketpp::frame::opcode::value::TEXT);
102 });
103
104 asio::post(std::bind(&server::generate_thread, this, token, text));
105 } 85 }
106 86
107 void cmd_check(websocketpp::connection_hdl connection, std::string token) { 87 void generate_thread(websocketpp::connection_hdl connection,
108 bool failed = false; 88 std::string text) {
109
110 try {
111 database_.subscribe(token, [this, connection](const std::string& msg) {
112 socket_.send(connection, msg, websocketpp::frame::opcode::value::TEXT);
113 });
114
115 if (!database_.is_done(token)) {
116 return;
117 }
118
119 std::string result = database_.getResult(token);
120 nlohmann::json resultMsg;
121 if (result.empty()) {
122 resultMsg["type"] = "error";
123 resultMsg["msg"] = "Unknown error occurred.";
124 } else {
125 resultMsg["type"] = "result";
126 resultMsg["image"] = database_.getResult(token);
127 resultMsg["msg"] = "Success!";
128 }
129
130 socket_.send(connection, resultMsg.dump(),
131 websocketpp::frame::opcode::value::TEXT);
132 } catch (const std::exception& ex) {
133 failed = true;
134 }
135
136 if (failed) {
137 try {
138 socket_.send(connection, R"(
139 {
140 "type": "error",
141 "msg": "Error retrieving request."
142 })",
143 websocketpp::frame::opcode::value::TEXT);
144 } catch (const std::exception& ex) {
145 // Well, okay
146 std::cout << ex.what() << std::endl;
147 }
148 }
149 }
150
151 void generate_thread(std::string token, std::string text) {
152 std::unique_ptr<wizard> generator; 89 std::unique_ptr<wizard> generator;
153 90
154 { 91 {
@@ -157,13 +94,15 @@ class server {
157 } 94 }
158 95
159 try { 96 try {
160 generator->set_status_callback([this, token](const std::string& status) { 97 generator->set_status_callback(
161 nlohmann::json msg; 98 [this, connection](const std::string& status) {
162 msg["type"] = "status"; 99 nlohmann::json msg;
163 msg["msg"] = status; 100 msg["type"] = "status";
101 msg["msg"] = status;
164 102
165 database_.post(token, msg.dump()); 103 socket_.send(connection, msg.dump(),
166 }); 104 websocketpp::frame::opcode::value::TEXT);
105 });
167 106
168 Magick::Image resultImage = generator->run(); 107 Magick::Image resultImage = generator->run();
169 Magick::Blob resultBlob; 108 Magick::Blob resultBlob;
@@ -173,24 +112,22 @@ class server {
173 resultBlob.length()); 112 resultBlob.length());
174 std::string resultEncoded = base64::to_base64(resultBytes); 113 std::string resultEncoded = base64::to_base64(resultBytes);
175 114
176 database_.setResult(token, resultEncoded);
177
178 nlohmann::json resultMsg; 115 nlohmann::json resultMsg;
179 resultMsg["type"] = "result"; 116 resultMsg["type"] = "result";
180 resultMsg["image"] = resultEncoded; 117 resultMsg["image"] = resultEncoded;
181 resultMsg["msg"] = "Success!"; 118 resultMsg["msg"] = "Success!";
182 119
183 database_.post(token, resultMsg.dump()); 120 socket_.send(connection, resultMsg.dump(),
121 websocketpp::frame::opcode::value::TEXT);
184 } catch (const std::exception& ex) { 122 } catch (const std::exception& ex) {
185 nlohmann::json response; 123 nlohmann::json response;
186 response["type"] = "error"; 124 response["type"] = "error";
187 response["msg"] = 125 response["msg"] =
188 std::string("Error generating card (") + ex.what() + ")"; 126 std::string("Error generating card (") + ex.what() + ")";
189 127
190 database_.post(token, response.dump()); 128 socket_.send(connection, response.dump(),
129 websocketpp::frame::opcode::value::TEXT);
191 } 130 }
192
193 database_.mark_done(token);
194 } 131 }
195 132
196 void cleanup_thread() { 133 void cleanup_thread() {
@@ -207,7 +144,6 @@ class server {
207 std::mt19937& rng_; 144 std::mt19937& rng_;
208 145
209 socket_type socket_; 146 socket_type socket_;
210 database database_;
211}; 147};
212 148
213} // namespace 149} // namespace
diff --git a/vendor/stduuid b/vendor/stduuid deleted file mode 160000
Subproject 3afe7193facd5d674de709fccc44d5055e144d7