summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2023-01-22 12:02:16 +0100
committerRoland Reichwein <mail@reichwein.it>2023-01-22 12:02:16 +0100
commit004db5e7e4e9ab6ac5b4730873c6b8f58da92930 (patch)
tree9b76e938558e24ad3a6778b2d725874a3dbe878b
parent6889067f0e4104eaced27bd2e1c303e70e23ca85 (diff)
Storage bugfix, whiteboard xml implementation
-rw-r--r--storage.cpp2
-rw-r--r--tests/test-storage.cpp17
-rw-r--r--tests/test-whiteboard.cpp8
-rw-r--r--whiteboard.cpp39
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