webserver: Fix handler unregistration when client quits
When there are multiple protocol handlers sharing the same name,
the implementation in libwebserv library had a bug that would
attempt to unregister request handler on a wrong protocol handler.
We need to track the exact protocol handler D-Bus object proxy that
we registered a request handler, so when the client exits, we remove
the request handler from the correct protocol handler object on the
server side.
BUG=brillo:539
TEST=`FEATURES=test emerge-link webserver`
Manually tested under debugger on both webservd and privetd
sides starting/existing processes in various orders and made
sure that D-Bus communications happen on the correct objects.
Change-Id: I8499052b48cb38a70b96fc3d6214490b412050c9
Reviewed-on: https://chromium-review.googlesource.com/260027
Trybot-Ready: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Reviewed-by: Christopher Wiley <wiley@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/libwebserv/protocol_handler.cc b/libwebserv/protocol_handler.cc
index fe4d567..fe0c9b0 100644
--- a/libwebserv/protocol_handler.cc
+++ b/libwebserv/protocol_handler.cc
@@ -76,9 +76,13 @@
const std::string& url,
const std::string& method,
std::unique_ptr<RequestHandlerInterface> handler) {
- request_handlers_.emplace(++last_handler_id_,
- HandlerMapEntry{url, method, std::string{},
- std::move(handler)});
+ request_handlers_.emplace(
+ ++last_handler_id_,
+ HandlerMapEntry{url, method,
+ std::map<ProtocolHandlerProxy*, std::string>{},
+ std::move(handler)});
+ // For each instance of remote protocol handler object sharing the same name,
+ // add the request handler.
for (const auto& pair : proxies_) {
pair.second->AddRequestHandlerAsync(
url,
@@ -86,7 +90,8 @@
server_->service_name_,
base::Bind(&ProtocolHandler::AddHandlerSuccess,
weak_ptr_factory_.GetWeakPtr(),
- last_handler_id_),
+ last_handler_id_,
+ pair.second),
base::Bind(&ProtocolHandler::AddHandlerError,
weak_ptr_factory_.GetWeakPtr(),
last_handler_id_));
@@ -109,9 +114,9 @@
if (p == request_handlers_.end())
return false;
- for (const auto& pair : proxies_) {
- pair.second->RemoveRequestHandlerAsync(
- p->second.remote_handler_id,
+ for (const auto& pair : p->second.remote_handler_ids) {
+ pair.first->RemoveRequestHandlerAsync(
+ pair.second,
base::Bind(&base::DoNothing),
base::Bind(&IgnoreError));
}
@@ -129,7 +134,8 @@
server_->service_name_,
base::Bind(&ProtocolHandler::AddHandlerSuccess,
weak_ptr_factory_.GetWeakPtr(),
- pair.first),
+ pair.first,
+ proxy),
base::Bind(&ProtocolHandler::AddHandlerError,
weak_ptr_factory_.GetWeakPtr(),
pair.first));
@@ -140,13 +146,16 @@
proxies_.erase(object_path);
if (proxies_.empty())
remote_handler_id_map_.clear();
+ for (auto& pair : request_handlers_)
+ pair.second.remote_handler_ids.clear();
}
void ProtocolHandler::AddHandlerSuccess(int handler_id,
+ ProtocolHandlerProxy* proxy,
const std::string& remote_handler_id) {
auto p = request_handlers_.find(handler_id);
CHECK(p != request_handlers_.end());
- p->second.remote_handler_id = remote_handler_id;
+ p->second.remote_handler_ids.emplace(proxy, remote_handler_id);
remote_handler_id_map_.emplace(remote_handler_id, handler_id);
}
diff --git a/libwebserv/protocol_handler.h b/libwebserv/protocol_handler.h
index bd8afb2..f6543cc 100644
--- a/libwebserv/protocol_handler.h
+++ b/libwebserv/protocol_handler.h
@@ -42,7 +42,7 @@
// information.
class LIBWEBSERV_EXPORT ProtocolHandler final {
public:
- explicit ProtocolHandler(const std::string& name, Server* server);
+ ProtocolHandler(const std::string& name, Server* server);
~ProtocolHandler();
// Returns true if the protocol handler object is connected to the web server
@@ -123,7 +123,7 @@
struct LIBWEBSERV_PRIVATE HandlerMapEntry {
std::string url;
std::string method;
- std::string remote_handler_id;
+ std::map<ProtocolHandlerProxy*, std::string> remote_handler_ids;
std::unique_ptr<RequestHandlerInterface> handler;
};
@@ -138,7 +138,9 @@
// Asynchronous callbacks to handle successful or failed request handler
// registration over D-Bus.
LIBWEBSERV_PRIVATE void AddHandlerSuccess(
- int handler_id, const std::string& remote_handler_id);
+ int handler_id,
+ ProtocolHandlerProxy* proxy,
+ const std::string& remote_handler_id);
LIBWEBSERV_PRIVATE void AddHandlerError(int handler_id,
chromeos::Error* error);