diff options
-rw-r--r-- | storage.cpp | 2 | ||||
-rw-r--r-- | tests/test-storage.cpp | 17 | ||||
-rw-r--r-- | tests/test-whiteboard.cpp | 8 | ||||
-rw-r--r-- | whiteboard.cpp | 39 |
4 files changed, 46 insertions, 20 deletions
diff --git a/storage.cpp b/storage.cpp index e7e9248..a7d5a36 100644 --- a/storage.cpp +++ b/storage.cpp @@ -186,7 +186,7 @@ std::string Storage::generate_id() for (int i = 0; i < 6; i++) { char c{static_cast<char>('0' + uniform_dist(e1))}; if (c > '9') - c = c - '9' + 'a'; + c = c - '9' - 1 + 'a'; result.push_back(c); } diff --git a/tests/test-storage.cpp b/tests/test-storage.cpp index ce19c3e..d8259e1 100644 --- a/tests/test-storage.cpp +++ b/tests/test-storage.cpp @@ -210,15 +210,20 @@ TEST_F(StorageTest, revision_increment) TEST_F(StorageTest, generate_id) { Storage storage(*m_config); - std::string a{storage.generate_id()}; - std::string b{storage.generate_id()}; + for (int i = 0; i < 100; i++) { + std::string a{storage.generate_id()}; + std::string b{storage.generate_id()}; - EXPECT_NE(a, b); - EXPECT_NE(a, ""); - EXPECT_NE(b, ""); + EXPECT_NE(a, b); + EXPECT_NE(a, ""); + EXPECT_NE(b, ""); - EXPECT_GE(a.size(), 6); + EXPECT_GE(a.size(), 6); + for (char c: a + b) { + EXPECT_TRUE((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')); + } + } } TEST_F(StorageTest, checksum32) diff --git a/tests/test-whiteboard.cpp b/tests/test-whiteboard.cpp index 4ed10ae..a472d64 100644 --- a/tests/test-whiteboard.cpp +++ b/tests/test-whiteboard.cpp @@ -234,11 +234,15 @@ TEST_F(WhiteboardTest, generate_id) wc.write("<request><command>newid</command></request>"); std::string result0 {wc.read()}; - ASSERT_EQ(result0.size(), 6); + ASSERT_TRUE(boost::algorithm::starts_with(result0, "<serverinfo><type>newid</type><id>")); + ASSERT_TRUE(boost::algorithm::ends_with(result0, "</id></serverinfo>")); + ASSERT_EQ(result0.size(), 58); wc.write("<request><command>newid</command></request>"); std::string result1 {wc.read()}; - ASSERT_EQ(result1.size(), 6); + ASSERT_TRUE(boost::algorithm::starts_with(result1, "<serverinfo><type>newid</type><id>")); + ASSERT_TRUE(boost::algorithm::ends_with(result1, "</id></serverinfo>")); + ASSERT_EQ(result1.size(), 58); ASSERT_NE(result0, result1); } diff --git a/whiteboard.cpp b/whiteboard.cpp index be8bcb0..6782385 100644 --- a/whiteboard.cpp +++ b/whiteboard.cpp @@ -8,11 +8,13 @@ #include <sys/types.h> #include <chrono> +#include <initializer_list> #include <iostream> #include <functional> #include <filesystem> #include <mutex> #include <regex> +#include <sstream> #include <string> #include <thread> #include <unordered_map> @@ -30,6 +32,8 @@ #include <boost/asio/connect.hpp> #include <boost/asio/ip/tcp.hpp> +#include <fmt/core.h> + #include "libreichwein/file.h" #include "config.h" @@ -76,6 +80,19 @@ void Whiteboard::storage_cleanup() } } +std::string make_xml(const std::initializer_list<std::pair<std::string, std::string>>& key_values) +{ + pt::ptree xml; + for (const auto& i: key_values) { + xml.put(fmt::format("serverinfo.{}", i.first), i.second); + } + + std::ostringstream oss; + // write_xml_element instead of write_xml to omit <!xml...> header + pt::xml_parser::write_xml_element(oss, {}, xml, -1, boost::property_tree::xml_writer_settings<pt::ptree::key_type>{}); + return oss.str(); +} + std::string Whiteboard::handle_request(const std::string& request) { try { @@ -93,7 +110,7 @@ std::string Whiteboard::handle_request(const std::string& request) std::string id {xml.get<std::string>("request.id")}; std::string data {xml.get<std::string>("request.data")}; m_storage->setDocument(id, data); - return {}; + return make_xml({{"type", "modify"}, {"revision", std::to_string(m_storage->getRevision(id)) }}); } else if (command == "getfile") { std::string id {xml.get<std::string>("request.id")}; @@ -102,20 +119,19 @@ std::string Whiteboard::handle_request(const std::string& request) if (filedata.size() > 30000000) throw std::runtime_error("File too big"); - return filedata; + return make_xml({{"type", "getfile"}, {"data", filedata}, {"revision", std::to_string(m_storage->getRevision(id)) }}); } else if (command == "checkupdate") { std::string id {xml.get<std::string>("request.id")}; - std::string checksum_s {xml.get<std::string>("request.checksum")}; - uint32_t checksum{static_cast<uint32_t>(stoul(checksum_s))}; + int request_revision {xml.get<int>("request.revision")}; - std::string filedata {m_storage->getDocument(id)}; - if (checksum != m_storage->checksum32(filedata)) { - return filedata; + int revision {m_storage->getRevision(id)}; + if (revision != request_revision) { + return make_xml({{"type", "update"}, {"data", m_storage->getDocument(id)}, {"revision", std::to_string(revision) }}); } else { - return {}; + return {}; // no reply } } else if (command == "newid") { - return m_storage->generate_id(); + return make_xml({{"type", "newid"}, {"id", m_storage->generate_id()}}); } else if (command == "qrcode") { std::string url{xml.get<std::string>("request.url")}; @@ -124,7 +140,7 @@ std::string Whiteboard::handle_request(const std::string& request) std::string pngdata {QRCode::getQRCode(url)}; - return pngdata; + return make_xml({{"type", "qrcode"}, {"png", pngdata}}); } else { throw std::runtime_error("Bad command: "s + command); } @@ -167,7 +183,8 @@ void Whiteboard::do_session(boost::asio::ip::tcp::socket socket) data = handle_request(data); buffer.consume(buffer.size()); boost::beast::ostream(buffer) << data; - ws.write(buffer.data()); + if (buffer.data().size() > 0) + ws.write(buffer.data()); } } catch (boost::beast::system_error const& se) { // This indicates that the session was closed |