diff options
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | database.cpp | 91 | ||||
-rw-r--r-- | database.h | 40 | ||||
-rw-r--r-- | server_main.cpp | 94 | ||||
m--------- | vendor/stduuid | 0 |
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 | ||
55 | add_executable(wizard_server database.cpp server_main.cpp) | 54 | add_executable(wizard_server server_main.cpp) |
56 | set_property(TARGET wizard_server PROPERTY CXX_STANDARD 17) | 55 | set_property(TARGET wizard_server PROPERTY CXX_STANDARD 17) |
57 | set_property(TARGET wizard_server PROPERTY CXX_STANDARD_REQUIRED ON) | 56 | set_property(TARGET wizard_server PROPERTY CXX_STANDARD_REQUIRED ON) |
58 | target_link_libraries( | 57 | target_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 | |||
7 | std::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 | |||
16 | void 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 | |||
29 | void 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 | |||
49 | void 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 | |||
60 | const 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 | |||
71 | void 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 | |||
82 | bool 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 | |||
12 | class 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 | |||