Skip to content

Commit e754550

Browse files
committed
Update the context per minute
1 parent 400d2a6 commit e754550

File tree

8 files changed

+94
-45
lines changed

8 files changed

+94
-45
lines changed

include/dbus2http/Dbus2Http.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ class Dbus2Http {
2020
std::thread service_thread_;
2121
std::unique_ptr<sdbus::IConnection> conn_;
2222

23+
std::thread update_thread_;
24+
bool stop_ = false;
25+
2326
public:
2427
Dbus2Http(const std::vector<std::string>& service_prefixes, bool system_bus);
2528

@@ -31,6 +34,8 @@ class Dbus2Http {
3134

3235
private:
3336
bool match_prefix(const std::string& service_name);
37+
38+
void update();
3439
};
3540

3641
} // namespace dbus2http

include/dbus2http/DbusEnumerator.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
#pragma once
66

7-
#include <plog/Log.h>
87
#include <sdbus-c++/IConnection.h>
98

109
#include <string>
@@ -37,7 +36,6 @@ class DbusEnumerator {
3736
std::vector<ObjectPath> result;
3837
result.emplace_back(object);
3938
context_.add(service_name, object);
40-
PLOGI << service_name << " " << object.path;
4139
for (const auto& child : object.children_paths) {
4240
std::string child_path = path + (path == "/" ? "" : "/") + child;
4341
std::vector<ObjectPath> child_ops =

include/dbus2http/entity/DbusSerialization.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,10 @@ class Dbus2Html {
9090

9191
public:
9292
static void set_ws_port(const std::string& port) { ws_port = port; }
93+
9394
static std::string to_html(
94-
const std::map<std::string, std::map<std::string, ObjectPath>>&
95-
object_paths);
95+
const InterfaceContext & context);
96+
9697
static std::string to_html(const ObjectPath& op,
9798
const std::string& service_name = "");
9899

include/dbus2http/entity/InterfaceContext.h

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,70 @@
66

77
#include <map>
88
#include <string>
9+
#include <mutex>
910

1011
#include "interface.h"
1112
#include "object_path.h"
1213

1314
namespace dbus2http {
1415

15-
struct InterfaceContext {
16+
class InterfaceContext {
1617
std::map<std::string, std::map<std::string, ObjectPath>> object_paths;
1718
std::map<std::string, Interface> interfaces;
19+
mutable std::recursive_mutex mutex;
1820

21+
public:
1922
void add(const Interface& interface) {
23+
std::unique_lock lock(mutex);
2024
interfaces[interface.name] = interface;
2125
};
2226

2327
void add(const std::string& service_name,
2428
const ObjectPath& object_path) {
29+
std::unique_lock lock(mutex);
2530
object_paths[service_name][object_path.path] = object_path;
2631
}
2732

33+
Interface get_interfaces(const std::string& interface_name) const {
34+
std::unique_lock lock(mutex);
35+
return interfaces.at(interface_name);
36+
}
37+
38+
ObjectPath get_object_path(const std::string& service_name, const std::string& path_string) const {
39+
std::unique_lock lock(mutex);
40+
return object_paths.at(service_name).at(path_string);
41+
}
42+
43+
std::vector<std::string> get_service_names() const {
44+
std::unique_lock lock(mutex);
45+
std::vector<std::string> service_names;
46+
for (const auto& [service_name, _] : object_paths)
47+
service_names.push_back(service_name);
48+
return service_names;
49+
}
2850

51+
std::vector<std::string> get_object_path_string(const std::string& service_name) const {
52+
std::unique_lock lock(mutex);
53+
std::vector<std::string> object_path_strings;
54+
if (not contains_service(service_name)) return object_path_strings;
55+
for (const auto& [path, object_path] : object_paths.at(service_name))
56+
object_path_strings.push_back(path);
57+
return object_path_strings;
58+
}
2959

3060
bool contains_service(const std::string& service_name) const {
61+
std::unique_lock lock(mutex);
3162
return object_paths.contains(service_name);
3263
}
3364

65+
bool contains_interface(const std::string& interface_name) const {
66+
std::unique_lock lock(mutex);
67+
return interfaces.contains(interface_name);
68+
}
69+
3470
const std::map<std::string, ObjectPath>& object_paths_of_service(
3571
const std::string& service_name) const {
72+
std::unique_lock lock(mutex);
3673
if (object_paths.contains(service_name))
3774
return object_paths.at(service_name);
3875
throw std::invalid_argument("service not found: " + service_name);
@@ -41,6 +78,7 @@ struct InterfaceContext {
4178
template <typename T>
4279
[[nodiscard]] const T& get(const std::string& interface_name,
4380
const std::string& member_name) const {
81+
std::unique_lock lock(mutex);
4482
if (interfaces.contains(interface_name))
4583
return interfaces.at(interface_name).get<T>(member_name);
4684
throw std::invalid_argument("interface not found: " + interface_name);

src/Dbus2Http.cpp

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,45 +6,49 @@
66
namespace dbus2http {
77

88
Dbus2Http::Dbus2Http(const std::vector<std::string>& service_prefixes,
9-
bool system)
9+
bool system)
1010
: system_bus_(system) {
1111
service_prefixes_.insert(service_prefixes.begin(), service_prefixes.end());
1212
conn_ = DbusUtils::createConnection(system_bus_);
1313
}
1414

1515
void Dbus2Http::start(int port, int ws_port) {
16-
DbusEnumerator dbusEnumerator(context_);
17-
auto service_names = DbusEnumerator::list_services(system_bus_);
18-
for (const auto& service_name : service_names) {
19-
if (not match_prefix(service_name)) continue;
20-
PLOGI << "servcie name: " << service_name;
21-
PLOGI << "object paths: ";
22-
std::vector<ObjectPath> object_paths =
23-
dbusEnumerator.parse_object_paths_recursively(*conn_.get(), service_name, "/");
24-
object_paths.erase(std::remove_if(object_paths.begin(), object_paths.end(),
25-
[](const ObjectPath& op) {
26-
return op.interfaces.empty();
27-
}),
28-
object_paths.end());
29-
}
30-
3116
dbus_caller_ = std::make_unique<DbusCaller>(context_, system_bus_);
3217
service_ = std::make_unique<WebService>(*dbus_caller_);
3318
service_thread_ = std::thread([&] { service_->run(port, ws_port); });
34-
// nlohmann::json j;
35-
// j["object_paths"] = context_.object_paths;
36-
// j["interfaces"] = context_.interfaces;
37-
// PLOGI << j.dump();
19+
update_thread_ = std::thread([&] {
20+
while (not stop_) {
21+
update();
22+
for (int i = 0; i < 60 and not stop_; ++i)
23+
std::this_thread::sleep_for(std::chrono::seconds(1));
24+
}
25+
});
3826
PLOGI << "dbus2http started on port " << port << "...";
3927
}
4028

4129
void Dbus2Http::stop() {
30+
stop_ = true;
31+
PLOGI << "stopping httplib service update thread...";
32+
if (update_thread_.joinable()) update_thread_.join();
33+
PLOGI << "httplib service update thread stopped.";
4234
PLOGI << "stopping httplib service...";
4335
service_->stop();
4436
if (service_thread_.joinable()) service_thread_.join();
4537
PLOGI << "httplib service stopped.";
4638
}
4739

40+
void Dbus2Http::update() {
41+
DbusEnumerator dbusEnumerator(context_);
42+
auto service_names = DbusEnumerator::list_services(system_bus_);
43+
for (const auto& service_name : service_names) {
44+
if (not match_prefix(service_name)) continue;
45+
if (context_.contains_service(service_name)) continue;
46+
PLOGI << "Found new service: " << service_name;
47+
dbusEnumerator.parse_object_paths_recursively(*conn_.get(), service_name,
48+
"/");
49+
}
50+
}
51+
4852
bool Dbus2Http::match_prefix(const std::string& service_name) {
4953
if (service_prefixes_.empty()) return true;
5054
for (const auto& prefix : service_prefixes_) {
@@ -53,4 +57,4 @@ bool Dbus2Http::match_prefix(const std::string& service_name) {
5357
return false;
5458
}
5559

56-
}
60+
} // namespace dbus2http

src/DbusSerialization.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,19 +190,20 @@ Flags DbusSerialization::parse_flags(const tinyxml2::XMLElement* parent_node) {
190190
}
191191

192192
std::string Dbus2Html::ws_port;
193-
194193
std::string Dbus2Html::to_html(
195-
const std::map<std::string, std::map<std::string, ObjectPath>>&
196-
object_paths) {
194+
const InterfaceContext & context) {
197195
std::ostringstream oss;
198-
for (const auto& [service_name, paths] : object_paths) {
196+
for (const auto& service_name : context.get_service_names()) {
199197
oss << "<details>";
200198
oss << "<summary>" << service_name << "</summary>";
201-
for (const auto& [path, op] : paths) oss << to_html(op, service_name);
199+
for (const auto& path : context.get_object_path_string(service_name)) {
200+
oss << to_html(context.get_object_path(service_name, path), service_name);
201+
}
202202
oss << "</details>";
203203
}
204204
return oss.str();
205205
}
206+
206207
std::string Dbus2Html::to_html(const ObjectPath& op,
207208
const std::string& service_name) {
208209
std::ostringstream oss;

src/WebService.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
#include <dbus2http/WebService.h>
55
#include <dbus2http/entity/DbusSerialization.h>
66

7-
#include <utility>
87
#include <ranges>
8+
#include <utility>
99

1010
// #embed "../dbus2http_openapi.yaml" as dbus2http_openapi_yaml
1111

@@ -18,7 +18,6 @@ bool WebService::parse_dbus_request_path(const std::string& path,
1818
std::string& object_path,
1919
std::string& interface_name,
2020
std::string& method) {
21-
2221
std::string rem = path;
2322
const auto first_slash = rem.find('/');
2423
if (first_slash == std::string::npos) {
@@ -100,22 +99,20 @@ WebService::WebService(DbusCaller& caller) : caller_(caller) {
10099
)";
101100

102101
bool ret = server_.set_mount_point("/", "/opt/cosmos/var/www/dbus2http");
103-
if (not ret)
104-
PLOGW << "set mount point failed";
102+
if (not ret) PLOGW << "set mount point failed";
105103

106104
// List DBus services
107105
server_.Get("/dbus/service", [this](const auto& req, auto& res) {
108106
nlohmann::json j;
109107
j["services"] = nlohmann::json::array();
110-
for (const auto& service_name :
111-
caller_.context().object_paths | std::views::keys) {
108+
for (const auto& service_name : caller_.context().get_service_names()) {
112109
j["services"].push_back(service_name);
113110
}
114111
res.set_content(j.dump(), "application/json");
115112
});
116113
server_.Get("/dbus/html", [&, header, footer](const auto& req, auto& res) {
117114
res.set_content(
118-
header + Dbus2Html::to_html(caller_.context().object_paths) + footer,
115+
header + Dbus2Html::to_html(caller_.context()) + footer,
119116
"text/html");
120117
});
121118
server_.Get(R"(/dbus/interface/html/(.*))", [&, header, footer](
@@ -124,9 +121,9 @@ WebService::WebService(DbusCaller& caller) : caller_(caller) {
124121
Dbus2Html::set_ws_port(std::to_string(ws_port_));
125122
if (suffix.find('/') == std::string::npos) {
126123
const std::string& interface_name = suffix;
127-
if (caller_.context().interfaces.contains(interface_name)) {
124+
if (caller_.context().contains_interface(interface_name)) {
128125
const Interface& interface =
129-
caller_.context().interfaces.at(interface_name);
126+
caller_.context().get_interfaces(interface_name);
130127
res.set_content(header + Dbus2Html::to_html(interface) + footer,
131128
"text/html");
132129
} else {
@@ -139,8 +136,8 @@ WebService::WebService(DbusCaller& caller) : caller_(caller) {
139136
std::string suffix = req.matches[1];
140137
if (suffix.find('/') == std::string::npos) {
141138
const std::string& interface_name = suffix;
142-
if (caller_.context().interfaces.contains(interface_name)) {
143-
nlohmann::json j = caller_.context().interfaces.at(interface_name);
139+
if (caller_.context().contains_interface(interface_name)) {
140+
nlohmann::json j = caller_.context().get_interfaces(interface_name);
144141
res.set_content(j.dump(2), "application/json");
145142
} else {
146143
res.status = 404;
@@ -197,7 +194,8 @@ WebService::WebService(DbusCaller& caller) : caller_(caller) {
197194
res.set_content(R"({"message": ")" + what + "\"}", "application/json");
198195
}
199196
});
200-
server_.Get(R"(/dbus/try/(.*))", [this, try_html](const auto& req, auto& res) {
197+
server_.Get(R"(/dbus/try/(.*))", [this, try_html](const auto& req,
198+
auto& res) {
201199
std::string service_name, object_path, interface_name, method;
202200
if (!parse_dbus_request_path(req.matches[1], service_name, object_path,
203201
interface_name, method)) {
@@ -224,8 +222,10 @@ WebService::WebService(DbusCaller& caller) : caller_(caller) {
224222
filled_html = replaceAll(filled_html, "$method_name$", method);
225223
const auto& method_type =
226224
caller_.context().get<Method>(interface_name, method);
227-
filled_html = replaceAll(filled_html, "$request_signature$", method_type.in_signature());
228-
filled_html = replaceAll(filled_html, "$response_signature$", method_type.out_signature());
225+
filled_html = replaceAll(filled_html, "$request_signature$",
226+
method_type.in_signature());
227+
filled_html = replaceAll(filled_html, "$response_signature$",
228+
method_type.out_signature());
229229
res.set_content(filled_html, "text/html");
230230
} catch (const std::exception& e) {
231231
res.status = 500;

src/main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ int main(int argc, char* argv[]) {
109109
// std::thread dbus_thread([&conn] { RunExample(conn); });
110110
// std::this_thread::sleep_for(std::chrono::milliseconds(10));
111111

112+
std::this_thread::sleep_for(std::chrono::seconds(5));
113+
112114
// launch dbus2http proxy
113115
PLOGI << "Starting dbus2http...";
114116
dbus2http::Dbus2Http dbus2http(service_prefix, program.get<bool>("--system"));

0 commit comments

Comments
 (0)