webserver: Add support for multiple protocol handlers with the same name
Previously protocol handlers were designed with their ID to be unique.
If the device needed to server requests on multiple ports, the clients
were forced to register separate request handlers for each of the
unique protocol handler instance.
This change makes it possible to have multiple protocol handlers share
a common "name" (like "http" or "https") and all the request handlers
registered for a particular protocol handler with a given name will be
added to each protocol handler that has this name.
So, the implementation has changed a bit. Each protocol handler still
has a unique ID (GUID) that allows to identify each instance (for example
in order to send back the reply from the client to the exact instance
of the object that initiated the request), while leaving the rest of
client-side library (libwebserv) working with non-unique names when
registering request handlers.
This also changed the web server configuration file a bit, since it
used to use a JSON dictionary for each protocol handler config, now
its an array of objects, which allows to specify the same name for
more than one protocol handler.
BUG=brillo:412
TEST=`FEATURES=test emerge-link webserver privetd`
Change-Id: Ib67fb586dd249c834d2464bfa0ef0eaabb7d780f
Reviewed-on: https://chromium-review.googlesource.com/255262
Trybot-Ready: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Reviewed-by: Aaron Kemp <kemp@google.com>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/libwebserv/server.cc b/libwebserv/server.cc
index 4b8403e..ed38988 100644
--- a/libwebserv/server.cc
+++ b/libwebserv/server.cc
@@ -49,7 +49,7 @@
std::string url = std::get<3>(in_request_info);
std::string method = std::get<4>(in_request_info);
ProtocolHandler* protocol_handler =
- server_->GetProtocolHandler(protocol_handler_id);
+ server_->GetProtocolHandlerByID(protocol_handler_id);
if (!protocol_handler) {
chromeos::Error::AddToPrintf(error, FROM_HERE,
chromeos::errors::dbus::kDomain,
@@ -84,7 +84,8 @@
request->raw_data_ = in_body;
- return protocol_handler->ProcessRequest(request_handler_id,
+ return protocol_handler->ProcessRequest(protocol_handler_id,
+ request_handler_id,
request_id,
std::move(request),
error);
@@ -127,7 +128,8 @@
on_server_offline_.Reset();
on_server_online_.Reset();
dbus_object_.reset();
- protocol_handlers_.clear();
+ protocol_handlers_ids_.clear();
+ protocol_handlers_names_.clear();
}
void Server::Online(org::chromium::WebServer::ServerProxy* server) {
@@ -147,11 +149,12 @@
void Server::ProtocolHandlerAdded(
org::chromium::WebServer::ProtocolHandlerProxy* handler) {
VLOG(1) << "Server-side protocol handler with ID '" << handler->id()
- << "' is on-line.";
+ << "' is on-line (" << handler->name() << ")";
protocol_handler_id_map_.emplace(handler->GetObjectPath(), handler->id());
- ProtocolHandler* registered_handler = GetProtocolHandler(handler->id());
+ ProtocolHandler* registered_handler = GetProtocolHandler(handler->name());
if (registered_handler) {
+ protocol_handlers_ids_.emplace(handler->id(), registered_handler);
registered_handler->Connect(handler);
if (!on_protocol_handler_connected_.is_null())
on_protocol_handler_connected_.Run(registered_handler);
@@ -166,24 +169,26 @@
VLOG(1) << "Server-side protocol handler with ID '" << p->second
<< "' is off-line.";
- ProtocolHandler* registered_handler = GetProtocolHandler(p->second);
+ ProtocolHandler* registered_handler = GetProtocolHandlerByID(p->second);
if (registered_handler) {
if (!on_protocol_handler_disconnected_.is_null())
on_protocol_handler_disconnected_.Run(registered_handler);
- registered_handler->Disconnect();
+ registered_handler->Disconnect(object_path);
+ protocol_handlers_ids_.erase(p->second);
}
protocol_handler_id_map_.erase(p);
}
-ProtocolHandler* Server::GetProtocolHandler(const std::string& id) {
- auto p = protocol_handlers_.find(id);
- if (p == protocol_handlers_.end()) {
+ProtocolHandler* Server::GetProtocolHandler(const std::string& name) {
+ auto p = protocol_handlers_names_.find(name);
+ if (p == protocol_handlers_names_.end()) {
VLOG(1) << "Creating a client-side instance of web server's protocol "
- << "handler with ID '" << id << "'";
- p = protocol_handlers_.emplace(
- id,
- std::unique_ptr<ProtocolHandler>{new ProtocolHandler{id, this}}).first;
+ << "handler with name '" << name << "'";
+ p = protocol_handlers_names_.emplace(
+ name,
+ std::unique_ptr<ProtocolHandler>{new ProtocolHandler{name, this}})
+ .first;
}
return p->second.get();
}
@@ -196,6 +201,15 @@
return GetProtocolHandler(ProtocolHandler::kHttps);
}
+ProtocolHandler* Server::GetProtocolHandlerByID(const std::string& id) const {
+ auto p = protocol_handlers_ids_.find(id);
+ if (p == protocol_handlers_ids_.end()) {
+ LOG(ERROR) << "Unable to locate protocol handler with ID '" << id << "'";
+ return nullptr;
+ }
+ return p->second;
+}
+
void Server::OnProtocolHandlerConnected(
const base::Callback<void(ProtocolHandler*)>& callback) {
on_protocol_handler_connected_ = callback;