Hide Server implementation
Hide the DBus details from the server interface. In the future, we
will guard the DBus specific headers and static factory behind ifdefs and
add support for a binder alternative.
Bug: 25932908
Test: `mmma -j16 system/webservd`
Change-Id: Iceb73eb3470ff5130195802dd1962eb8361d3f0e
diff --git a/libwebserv/Android.mk b/libwebserv/Android.mk
index 17d800d..50235bc 100644
--- a/libwebserv/Android.mk
+++ b/libwebserv/Android.mk
@@ -25,6 +25,7 @@
LOCAL_SHARED_LIBRARIES := libwebservd-client-internal
LOCAL_SRC_FILES := \
dbus_bindings/org.chromium.WebServer.RequestHandler.dbus-xml \
+ dbus_server.cc \
protocol_handler.cc \
request.cc \
request_handler_callback.cc \
diff --git a/libwebserv/dbus_server.cc b/libwebserv/dbus_server.cc
new file mode 100644
index 0000000..091b02f
--- /dev/null
+++ b/libwebserv/dbus_server.cc
@@ -0,0 +1,247 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <libwebserv/dbus_server.h>
+
+#include <tuple>
+#include <vector>
+
+#include <libwebserv/protocol_handler.h>
+#include <libwebserv/request_impl.h>
+
+#include "dbus_bindings/org.chromium.WebServer.RequestHandler.h"
+#include "webservd/dbus-proxies.h"
+
+namespace libwebserv {
+
+class DBusServer::RequestHandler final
+ : public org::chromium::WebServer::RequestHandlerInterface {
+ public:
+ explicit RequestHandler(DBusServer* server) : server_{server} {}
+ bool ProcessRequest(
+ brillo::ErrorPtr* error,
+ const std::tuple<std::string, std::string, std::string, std::string,
+ std::string>& in_request_info,
+ const std::vector<std::tuple<std::string, std::string>>& in_headers,
+ const std::vector<std::tuple<bool, std::string, std::string>>& in_params,
+ const std::vector<std::tuple<int32_t, std::string, std::string,
+ std::string, std::string>>& in_files,
+ const dbus::FileDescriptor& in_body) override;
+
+ private:
+ DBusServer* server_{nullptr};
+ DISALLOW_COPY_AND_ASSIGN(RequestHandler);
+};
+
+bool DBusServer::RequestHandler::ProcessRequest(
+ brillo::ErrorPtr* error,
+ const std::tuple<std::string, std::string, std::string, std::string,
+ std::string>& in_request_info,
+ const std::vector<std::tuple<std::string, std::string>>& in_headers,
+ const std::vector<std::tuple<bool, std::string, std::string>>& in_params,
+ const std::vector<std::tuple<int32_t, std::string, std::string, std::string,
+ std::string>>& in_files,
+ const dbus::FileDescriptor& in_body) {
+ std::string protocol_handler_id = std::get<0>(in_request_info);
+ std::string request_handler_id = std::get<1>(in_request_info);
+ std::string request_id = std::get<2>(in_request_info);
+ std::string url = std::get<3>(in_request_info);
+ std::string method = std::get<4>(in_request_info);
+ ProtocolHandler* protocol_handler =
+ server_->GetProtocolHandlerByID(protocol_handler_id);
+ if (!protocol_handler) {
+ brillo::Error::AddToPrintf(error, FROM_HERE,
+ brillo::errors::dbus::kDomain,
+ DBUS_ERROR_FAILED,
+ "Unknown protocol handler '%s'",
+ protocol_handler_id.c_str());
+ return false;
+ }
+ std::unique_ptr<RequestImpl> request{
+ new RequestImpl{protocol_handler, url, method}};
+ // Convert request data into format required by the Request object.
+ for (const auto& tuple : in_params) {
+ if (std::get<0>(tuple))
+ request->post_data_.emplace(std::get<1>(tuple), std::get<2>(tuple));
+ else
+ request->get_data_.emplace(std::get<1>(tuple), std::get<2>(tuple));
+ }
+
+ for (const auto& tuple : in_headers)
+ request->headers_.emplace(std::get<0>(tuple), std::get<1>(tuple));
+
+ for (const auto& tuple : in_files) {
+ request->file_info_.emplace(
+ std::get<1>(tuple), // field_name
+ std::unique_ptr<FileInfo>{new FileInfo{
+ protocol_handler,
+ std::get<0>(tuple), // file_id
+ request_id,
+ std::get<2>(tuple), // file_name
+ std::get<3>(tuple), // content_type
+ std::get<4>(tuple)}}); // transfer_encoding
+ }
+
+ request->raw_data_fd_ = base::File(dup(in_body.value()));
+ CHECK(request->raw_data_fd_.IsValid());
+
+ return protocol_handler->ProcessRequest(protocol_handler_id,
+ request_handler_id,
+ request_id,
+ std::move(request),
+ error);
+}
+
+DBusServer::DBusServer()
+ : request_handler_{new RequestHandler{this}},
+ dbus_adaptor_{new org::chromium::WebServer::RequestHandlerAdaptor{
+ request_handler_.get()}} {}
+
+void DBusServer::Connect(
+ const scoped_refptr<dbus::Bus>& bus,
+ const std::string& service_name,
+ const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb,
+ const base::Closure& on_server_online,
+ const base::Closure& on_server_offline) {
+ service_name_ = service_name;
+ dbus_object_.reset(new brillo::dbus_utils::DBusObject{
+ nullptr, bus, dbus_adaptor_->GetObjectPath()});
+ dbus_adaptor_->RegisterWithDBusObject(dbus_object_.get());
+ dbus_object_->RegisterAsync(cb);
+ on_server_online_ = on_server_online;
+ on_server_offline_ = on_server_offline;
+ object_manager_.reset(new org::chromium::WebServer::ObjectManagerProxy{bus});
+ object_manager_->SetServerAddedCallback(
+ base::Bind(&DBusServer::Online, base::Unretained(this)));
+ object_manager_->SetServerRemovedCallback(
+ base::Bind(&DBusServer::Offline, base::Unretained(this)));
+ object_manager_->SetProtocolHandlerAddedCallback(
+ base::Bind(&DBusServer::ProtocolHandlerAdded, base::Unretained(this)));
+ object_manager_->SetProtocolHandlerRemovedCallback(
+ base::Bind(&DBusServer::ProtocolHandlerRemoved, base::Unretained(this)));
+}
+
+void DBusServer::Disconnect() {
+ on_server_offline_.Reset();
+ on_server_online_.Reset();
+ protocol_handlers_ids_.clear();
+ protocol_handlers_names_.clear();
+ // Release D-Bus object manager proxy after all the dependent maps are freed
+ // (e.g. |protocol_handlers_names_| contains pointers to ProtocolHandlerProxy,
+ // instances of which are owned by the D-Bus object manager).
+ object_manager_.reset();
+ dbus_object_.reset();
+}
+
+void DBusServer::Online(
+ org::chromium::WebServer::ServerProxyInterface* server) {
+ VLOG(1) << "Web server is on-line.";
+ proxy_ = server;
+ if (!on_server_online_.is_null())
+ on_server_online_.Run();
+}
+
+bool DBusServer::IsConnected() const {
+ return proxy_ != nullptr;
+}
+
+void DBusServer::Offline(const dbus::ObjectPath& object_path) {
+ if (!on_server_offline_.is_null())
+ on_server_offline_.Run();
+ proxy_ = nullptr;
+ VLOG(1) << "Web server is off-line.";
+}
+
+void DBusServer::ProtocolHandlerAdded(
+ org::chromium::WebServer::ProtocolHandlerProxyInterface* handler) {
+ VLOG(1) << "Server-side protocol handler with ID '" << handler->id()
+ << "' is on-line (" << handler->name() << ")";
+
+ protocol_handler_id_map_.emplace(handler->GetObjectPath(), 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);
+ }
+}
+
+void DBusServer::ProtocolHandlerRemoved(const dbus::ObjectPath& object_path) {
+ auto p = protocol_handler_id_map_.find(object_path);
+ if (p == protocol_handler_id_map_.end())
+ return;
+
+ VLOG(1) << "Server-side protocol handler with ID '" << p->second
+ << "' is off-line.";
+
+ 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(object_path);
+ protocol_handlers_ids_.erase(p->second);
+ }
+
+ protocol_handler_id_map_.erase(p);
+}
+
+ProtocolHandler* DBusServer::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 name '" << name << "'";
+ p = protocol_handlers_names_.emplace(
+ name,
+ std::unique_ptr<ProtocolHandler>{new ProtocolHandler{name, this}})
+ .first;
+ }
+ return p->second.get();
+}
+
+ProtocolHandler* DBusServer::GetDefaultHttpHandler() {
+ return GetProtocolHandler(ProtocolHandler::kHttp);
+}
+
+ProtocolHandler* DBusServer::GetDefaultHttpsHandler() {
+ return GetProtocolHandler(ProtocolHandler::kHttps);
+}
+
+ProtocolHandler* DBusServer::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 DBusServer::OnProtocolHandlerConnected(
+ const base::Callback<void(ProtocolHandler*)>& callback) {
+ on_protocol_handler_connected_ = callback;
+}
+
+void DBusServer::OnProtocolHandlerDisconnected(
+ const base::Callback<void(ProtocolHandler*)>& callback) {
+ on_protocol_handler_disconnected_ = callback;
+}
+
+base::TimeDelta DBusServer::GetDefaultRequestTimeout() const {
+ int timeout_seconds = proxy_ ? proxy_->default_request_timeout() : -1;
+ if (timeout_seconds <= 0)
+ return base::TimeDelta::Max();
+ return base::TimeDelta::FromSeconds(timeout_seconds);
+}
+
+} // namespace libwebserv
diff --git a/libwebserv/dbus_server.h b/libwebserv/dbus_server.h
new file mode 100644
index 0000000..36bcdcb
--- /dev/null
+++ b/libwebserv/dbus_server.h
@@ -0,0 +1,145 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef WEBSERVER_LIBWEBSERV_DBUS_SERVER_H_
+#define WEBSERVER_LIBWEBSERV_DBUS_SERVER_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include <base/macros.h>
+#include <dbus/bus.h>
+#include <brillo/dbus/async_event_sequencer.h>
+#include <brillo/dbus/dbus_object.h>
+
+#include "libwebserv/export.h"
+#include "libwebserv/request_handler_interface.h"
+#include "libwebserv/server.h"
+
+namespace org {
+namespace chromium {
+namespace WebServer {
+
+class ObjectManagerProxy;
+class ProtocolHandlerProxyInterface;
+class RequestHandlerAdaptor;
+class ServerProxyInterface;
+
+} // namespace WebServer
+} // namespace chromium
+} // namespace org
+
+namespace libwebserv {
+
+class LIBWEBSERV_PRIVATE DBusServer : public Server {
+ public:
+ DBusServer();
+ ~DBusServer() override = default;
+
+ // Establish a connection to the system webserver.
+ // |service_name| is the well known D-Bus name of the client's process, used
+ // to expose a callback D-Bus object the web server calls back with incoming
+ // requests.
+ // |on_server_online| and |on_server_offline| will notify the caller when the
+ // server comes up and down.
+ // Note that we can Connect() even before the webserver attaches to D-Bus,
+ // and appropriate state will be built up when the webserver appears on D-Bus.
+ void Connect(
+ const scoped_refptr<dbus::Bus>& bus,
+ const std::string& service_name,
+ const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb,
+ const base::Closure& on_server_online,
+ const base::Closure& on_server_offline);
+
+ ProtocolHandler* GetDefaultHttpHandler() override;
+
+ ProtocolHandler* GetDefaultHttpsHandler() override;
+ ProtocolHandler* GetProtocolHandler(const std::string& name) override;
+
+ bool IsConnected() const override;
+
+ void OnProtocolHandlerConnected(
+ const base::Callback<void(ProtocolHandler*)>& callback) override;
+
+ void OnProtocolHandlerDisconnected(
+ const base::Callback<void(ProtocolHandler*)>& callback) override;
+
+ base::TimeDelta GetDefaultRequestTimeout() const override;
+
+ private:
+ friend class ProtocolHandler;
+ class RequestHandler;
+
+ void Disconnect();
+
+ // Handler invoked when a connection is established to web server daemon.
+ void Online(org::chromium::WebServer::ServerProxyInterface* server);
+
+ // Handler invoked when the web server daemon connection is dropped.
+ void Offline(const dbus::ObjectPath& object_path);
+
+ // Handler invoked when a new protocol handler D-Bus proxy object becomes
+ // available.
+ void ProtocolHandlerAdded(
+ org::chromium::WebServer::ProtocolHandlerProxyInterface* handler);
+
+ // Handler invoked when a protocol handler D-Bus proxy object disappears.
+ void ProtocolHandlerRemoved(
+ const dbus::ObjectPath& object_path);
+
+ // Looks up a protocol handler by ID. If not found, returns nullptr.
+ ProtocolHandler* GetProtocolHandlerByID(
+ const std::string& id) const;
+
+ // Private implementation of D-Bus RequestHandlerInterface called by the web
+ // server daemon whenever a new request is available to be processed.
+ std::unique_ptr<RequestHandler> request_handler_;
+ // D-Bus object adaptor for RequestHandlerInterface.
+ std::unique_ptr<org::chromium::WebServer::RequestHandlerAdaptor>
+ dbus_adaptor_;
+ // D-Bus object to handler registration of RequestHandlerInterface.
+ std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object_;
+
+ // A mapping of protocol handler name to the associated object.
+ std::map<std::string, std::unique_ptr<ProtocolHandler>>
+ protocol_handlers_names_;
+ // A mapping of protocol handler IDs to the associated object.
+ std::map<std::string, ProtocolHandler*> protocol_handlers_ids_;
+ // A map between D-Bus object path of protocol handler and remote protocol
+ // handler ID.
+ std::map<dbus::ObjectPath, std::string> protocol_handler_id_map_;
+
+ // User-specified callbacks for server and protocol handler life-time events.
+ base::Closure on_server_online_;
+ base::Closure on_server_offline_;
+ base::Callback<void(ProtocolHandler*)> on_protocol_handler_connected_;
+ base::Callback<void(ProtocolHandler*)> on_protocol_handler_disconnected_;
+
+ // D-Bus object manager proxy that receives notification of web server
+ // daemon's D-Bus object creation and destruction.
+ std::unique_ptr<org::chromium::WebServer::ObjectManagerProxy> object_manager_;
+
+ // D-Bus proxy for the web server main object.
+ org::chromium::WebServer::ServerProxyInterface* proxy_{nullptr};
+
+ // D-Bus service name used by the daemon hosting this object.
+ std::string service_name_;
+
+ DISALLOW_COPY_AND_ASSIGN(DBusServer);
+};
+
+} // namespace libwebserv
+
+#endif // WEBSERVER_LIBWEBSERV_DBUS_SERVER_H_
diff --git a/libwebserv/protocol_handler.cc b/libwebserv/protocol_handler.cc
index 76d1606..8c50d47 100644
--- a/libwebserv/protocol_handler.cc
+++ b/libwebserv/protocol_handler.cc
@@ -22,10 +22,10 @@
#include <brillo/streams/stream_utils.h>
#include "dbus_bindings/org.chromium.WebServer.RequestHandler.h"
+#include "libwebserv/dbus_server.h"
#include "libwebserv/request.h"
#include "libwebserv/request_handler_callback.h"
#include "libwebserv/response_impl.h"
-#include "libwebserv/server.h"
#include "webservd/dbus-proxies.h"
namespace libwebserv {
@@ -58,7 +58,7 @@
const char ProtocolHandler::kHttp[] = "http";
const char ProtocolHandler::kHttps[] = "https";
-ProtocolHandler::ProtocolHandler(const std::string& name, Server* server)
+ProtocolHandler::ProtocolHandler(const std::string& name, DBusServer* server)
: name_{name}, server_{server} {
}
diff --git a/libwebserv/protocol_handler.h b/libwebserv/protocol_handler.h
index 2e1c748..2c2dee5 100644
--- a/libwebserv/protocol_handler.h
+++ b/libwebserv/protocol_handler.h
@@ -44,7 +44,7 @@
namespace libwebserv {
-class Server;
+class DBusServer;
class Request;
// Wrapper around a protocol handler (e.g. HTTP or HTTPs).
@@ -53,7 +53,7 @@
// information.
class LIBWEBSERV_EXPORT ProtocolHandler final {
public:
- ProtocolHandler(const std::string& name, Server* server);
+ ProtocolHandler(const std::string& name, DBusServer* server);
~ProtocolHandler();
// Returns true if the protocol handler object is connected to the web server
@@ -126,7 +126,7 @@
private:
friend class FileInfo;
- friend class Server;
+ friend class DBusServer;
friend class ResponseImpl;
using ProtocolHandlerProxyInterface =
@@ -139,12 +139,12 @@
std::unique_ptr<RequestHandlerInterface> handler;
};
- // Called by the Server class when the D-Bus proxy object gets connected
+ // Called by the DBusServer class when the D-Bus proxy object gets connected
// to the web server daemon.
-
LIBWEBSERV_PRIVATE void Connect(ProtocolHandlerProxyInterface* proxy);
- // Called by the Server class when the D-Bus proxy object gets disconnected
- // from the web server daemon.
+
+ // Called by the DBusServer class when the D-Bus proxy object gets
+ // disconnected from the web server daemon.
LIBWEBSERV_PRIVATE void Disconnect(const dbus::ObjectPath& object_path);
// Asynchronous callbacks to handle successful or failed request handler
@@ -156,7 +156,7 @@
LIBWEBSERV_PRIVATE void AddHandlerError(int handler_id,
brillo::Error* error);
- // Called by Server when an incoming request is dispatched.
+ // Called by DBusServer when an incoming request is dispatched.
LIBWEBSERV_PRIVATE bool ProcessRequest(const std::string& protocol_handler_id,
const std::string& remote_handler_id,
const std::string& request_id,
@@ -187,7 +187,7 @@
// Protocol Handler name.
std::string name_;
// Back reference to the server object.
- Server* server_{nullptr};
+ DBusServer* server_{nullptr};
// Handler data map. The key is the client-facing request handler ID returned
// by AddHandler() when registering the handler.
std::map<int, HandlerMapEntry> request_handlers_;
diff --git a/libwebserv/request.h b/libwebserv/request.h
index f1f7043..ce8d82b 100644
--- a/libwebserv/request.h
+++ b/libwebserv/request.h
@@ -49,7 +49,7 @@
const base::Callback<void(brillo::Error*)>& error_callback) const;
private:
- friend class Server;
+ friend class DBusServer;
LIBWEBSERV_PRIVATE FileInfo(ProtocolHandler* handler,
int file_id,
diff --git a/libwebserv/request_impl.h b/libwebserv/request_impl.h
index 4d99873..2c172ec 100644
--- a/libwebserv/request_impl.h
+++ b/libwebserv/request_impl.h
@@ -31,7 +31,7 @@
brillo::StreamPtr GetDataStream() override;
private:
- friend class Server;
+ friend class DBusServer;
LIBWEBSERV_PRIVATE RequestImpl(ProtocolHandler* handler,
const std::string& url,
diff --git a/libwebserv/server.cc b/libwebserv/server.cc
index d806eaa..9f567b3 100644
--- a/libwebserv/server.cc
+++ b/libwebserv/server.cc
@@ -14,232 +14,22 @@
#include <libwebserv/server.h>
-#include <tuple>
-#include <vector>
+#include <libwebserv/dbus_server.h>
-#include <libwebserv/protocol_handler.h>
-#include <libwebserv/request_impl.h>
-
-#include "dbus_bindings/org.chromium.WebServer.RequestHandler.h"
-#include "webservd/dbus-proxies.h"
+using std::unique_ptr;
namespace libwebserv {
-class Server::RequestHandler final
- : public org::chromium::WebServer::RequestHandlerInterface {
- public:
- explicit RequestHandler(Server* server) : server_{server} {}
- bool ProcessRequest(
- brillo::ErrorPtr* error,
- const std::tuple<std::string, std::string, std::string, std::string,
- std::string>& in_request_info,
- const std::vector<std::tuple<std::string, std::string>>& in_headers,
- const std::vector<std::tuple<bool, std::string, std::string>>& in_params,
- const std::vector<std::tuple<int32_t, std::string, std::string,
- std::string, std::string>>& in_files,
- const dbus::FileDescriptor& in_body) override;
-
- private:
- Server* server_{nullptr};
- DISALLOW_COPY_AND_ASSIGN(RequestHandler);
-};
-
-bool Server::RequestHandler::ProcessRequest(
- brillo::ErrorPtr* error,
- const std::tuple<std::string, std::string, std::string, std::string,
- std::string>& in_request_info,
- const std::vector<std::tuple<std::string, std::string>>& in_headers,
- const std::vector<std::tuple<bool, std::string, std::string>>& in_params,
- const std::vector<std::tuple<int32_t, std::string, std::string, std::string,
- std::string>>& in_files,
- const dbus::FileDescriptor& in_body) {
- std::string protocol_handler_id = std::get<0>(in_request_info);
- std::string request_handler_id = std::get<1>(in_request_info);
- std::string request_id = std::get<2>(in_request_info);
- std::string url = std::get<3>(in_request_info);
- std::string method = std::get<4>(in_request_info);
- ProtocolHandler* protocol_handler =
- server_->GetProtocolHandlerByID(protocol_handler_id);
- if (!protocol_handler) {
- brillo::Error::AddToPrintf(error, FROM_HERE,
- brillo::errors::dbus::kDomain,
- DBUS_ERROR_FAILED,
- "Unknown protocol handler '%s'",
- protocol_handler_id.c_str());
- return false;
- }
- std::unique_ptr<RequestImpl> request{
- new RequestImpl{protocol_handler, url, method}};
- // Convert request data into format required by the Request object.
- for (const auto& tuple : in_params) {
- if (std::get<0>(tuple))
- request->post_data_.emplace(std::get<1>(tuple), std::get<2>(tuple));
- else
- request->get_data_.emplace(std::get<1>(tuple), std::get<2>(tuple));
- }
-
- for (const auto& tuple : in_headers)
- request->headers_.emplace(std::get<0>(tuple), std::get<1>(tuple));
-
- for (const auto& tuple : in_files) {
- request->file_info_.emplace(
- std::get<1>(tuple), // field_name
- std::unique_ptr<FileInfo>{new FileInfo{
- protocol_handler,
- std::get<0>(tuple), // file_id
- request_id,
- std::get<2>(tuple), // file_name
- std::get<3>(tuple), // content_type
- std::get<4>(tuple)}}); // transfer_encoding
- }
-
- request->raw_data_fd_ = base::File(dup(in_body.value()));
- CHECK(request->raw_data_fd_.IsValid());
-
- return protocol_handler->ProcessRequest(protocol_handler_id,
- request_handler_id,
- request_id,
- std::move(request),
- error);
-}
-
-Server::Server()
- : request_handler_{new RequestHandler{this}},
- dbus_adaptor_{new org::chromium::WebServer::RequestHandlerAdaptor{
- request_handler_.get()}} {}
-
-Server::~Server() {
-}
-
-void Server::Connect(
+unique_ptr<Server> Server::ConnectToServerViaDBus(
const scoped_refptr<dbus::Bus>& bus,
const std::string& service_name,
const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb,
const base::Closure& on_server_online,
const base::Closure& on_server_offline) {
- service_name_ = service_name;
- dbus_object_.reset(new brillo::dbus_utils::DBusObject{
- nullptr, bus, dbus_adaptor_->GetObjectPath()});
- dbus_adaptor_->RegisterWithDBusObject(dbus_object_.get());
- dbus_object_->RegisterAsync(cb);
- on_server_online_ = on_server_online;
- on_server_offline_ = on_server_offline;
- object_manager_.reset(new org::chromium::WebServer::ObjectManagerProxy{bus});
- object_manager_->SetServerAddedCallback(
- base::Bind(&Server::Online, base::Unretained(this)));
- object_manager_->SetServerRemovedCallback(
- base::Bind(&Server::Offline, base::Unretained(this)));
- object_manager_->SetProtocolHandlerAddedCallback(
- base::Bind(&Server::ProtocolHandlerAdded, base::Unretained(this)));
- object_manager_->SetProtocolHandlerRemovedCallback(
- base::Bind(&Server::ProtocolHandlerRemoved, base::Unretained(this)));
-}
-
-void Server::Disconnect() {
- on_server_offline_.Reset();
- on_server_online_.Reset();
- protocol_handlers_ids_.clear();
- protocol_handlers_names_.clear();
- // Release D-Bus object manager proxy after all the dependent maps are freed
- // (e.g. |protocol_handlers_names_| contains pointers to ProtocolHandlerProxy,
- // instances of which are owned by the D-Bus object manager).
- object_manager_.reset();
- dbus_object_.reset();
-}
-
-void Server::Online(org::chromium::WebServer::ServerProxyInterface* server) {
- VLOG(1) << "Web server is on-line.";
- proxy_ = server;
- if (!on_server_online_.is_null())
- on_server_online_.Run();
-}
-
-void Server::Offline(const dbus::ObjectPath& object_path) {
- if (!on_server_offline_.is_null())
- on_server_offline_.Run();
- proxy_ = nullptr;
- VLOG(1) << "Web server is off-line.";
-}
-
-void Server::ProtocolHandlerAdded(
- org::chromium::WebServer::ProtocolHandlerProxyInterface* handler) {
- VLOG(1) << "Server-side protocol handler with ID '" << handler->id()
- << "' is on-line (" << handler->name() << ")";
-
- protocol_handler_id_map_.emplace(handler->GetObjectPath(), 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);
- }
-}
-
-void Server::ProtocolHandlerRemoved(const dbus::ObjectPath& object_path) {
- auto p = protocol_handler_id_map_.find(object_path);
- if (p == protocol_handler_id_map_.end())
- return;
-
- VLOG(1) << "Server-side protocol handler with ID '" << p->second
- << "' is off-line.";
-
- 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(object_path);
- protocol_handlers_ids_.erase(p->second);
- }
-
- protocol_handler_id_map_.erase(p);
-}
-
-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 name '" << name << "'";
- p = protocol_handlers_names_.emplace(
- name,
- std::unique_ptr<ProtocolHandler>{new ProtocolHandler{name, this}})
- .first;
- }
- return p->second.get();
-}
-
-ProtocolHandler* Server::GetDefaultHttpHandler() {
- return GetProtocolHandler(ProtocolHandler::kHttp);
-}
-
-ProtocolHandler* Server::GetDefaultHttpsHandler() {
- 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;
-}
-
-void Server::OnProtocolHandlerDisconnected(
- const base::Callback<void(ProtocolHandler*)>& callback) {
- on_protocol_handler_disconnected_ = callback;
-}
-
-base::TimeDelta Server::GetDefaultRequestTimeout() const {
- int timeout_seconds = proxy_ ? proxy_->default_request_timeout() : -1;
- if (timeout_seconds <= 0)
- return base::TimeDelta::Max();
- return base::TimeDelta::FromSeconds(timeout_seconds);
+ DBusServer* server = new DBusServer;
+ unique_ptr<Server> ret(server);
+ server->Connect(bus, service_name, cb, on_server_online, on_server_offline);
+ return ret;
}
} // namespace libwebserv
diff --git a/libwebserv/server.h b/libwebserv/server.h
index ca8a6f1..77bf484 100644
--- a/libwebserv/server.h
+++ b/libwebserv/server.h
@@ -15,38 +15,26 @@
#ifndef WEBSERVER_LIBWEBSERV_SERVER_H_
#define WEBSERVER_LIBWEBSERV_SERVER_H_
-#include <map>
#include <memory>
#include <string>
+#include <base/callback.h>
#include <base/macros.h>
-#include <dbus/bus.h>
+#include <base/memory/ref_counted.h>
#include <brillo/dbus/async_event_sequencer.h>
-#include <brillo/dbus/dbus_object.h>
+#include <dbus/bus.h>
#include <libwebserv/export.h>
-#include <libwebserv/request_handler_interface.h>
-
-namespace org {
-namespace chromium {
-namespace WebServer {
-
-class ObjectManagerProxy;
-class ProtocolHandlerProxyInterface;
-class RequestHandlerAdaptor;
-class ServerProxyInterface;
-
-} // namespace WebServer
-} // namespace chromium
-} // namespace org
namespace libwebserv {
+class ProtocolHandler;
+
// Top-level wrapper class around HTTP server and provides an interface to
// the web server.
-class LIBWEBSERV_EXPORT Server final {
+class LIBWEBSERV_EXPORT Server {
public:
- Server();
- ~Server();
+ Server() = default;
+ virtual ~Server() = default;
// Establish a connection to the system webserver.
// |service_name| is the well known D-Bus name of the client's process, used
@@ -56,22 +44,18 @@
// server comes up and down.
// Note that we can Connect() even before the webserver attaches to D-Bus,
// and appropriate state will be built up when the webserver appears on D-Bus.
- void Connect(
+ static std::unique_ptr<Server> ConnectToServerViaDBus(
const scoped_refptr<dbus::Bus>& bus,
const std::string& service_name,
const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb,
const base::Closure& on_server_online,
const base::Closure& on_server_offline);
- // Disconnects from the web server and removes the library interface from
- // D-Bus.
- void Disconnect();
-
// A helper method that returns the default handler for "http".
- ProtocolHandler* GetDefaultHttpHandler();
+ virtual ProtocolHandler* GetDefaultHttpHandler() = 0;
// A helper method that returns the default handler for "https".
- ProtocolHandler* GetDefaultHttpsHandler();
+ virtual ProtocolHandler* GetDefaultHttpsHandler() = 0;
// Returns an existing protocol handler by name. If the handler with the
// requested |name| does not exist, a new one will be created.
@@ -80,88 +64,30 @@
// being configured to open a corresponding handler with the given name.
// Because clients and the server come up asynchronously, we allow clients
// to register anticipated handlers before server starts up.
- ProtocolHandler* GetProtocolHandler(const std::string& name);
+ virtual ProtocolHandler* GetProtocolHandler(const std::string& name) = 0;
- // Returns true if the web server daemon is connected to DBus and our
- // connection to it has been established.
- bool IsConnected() const { return proxy_ != nullptr; }
+ // Returns true if |this| is connected to the web server daemon via IPC.
+ virtual bool IsConnected() const = 0;
// Set a user-callback to be invoked when a protocol handler is connect to the
// server daemon. Multiple calls to this method will overwrite previously set
// callbacks.
- void OnProtocolHandlerConnected(
- const base::Callback<void(ProtocolHandler*)>& callback);
+ virtual void OnProtocolHandlerConnected(
+ const base::Callback<void(ProtocolHandler*)>& callback) = 0;
// Set a user-callback to be invoked when a protocol handler is disconnected
// from the server daemon (e.g. on shutdown). Multiple calls to this method
// will overwrite previously set callbacks.
- void OnProtocolHandlerDisconnected(
- const base::Callback<void(ProtocolHandler*)>& callback);
+ virtual void OnProtocolHandlerDisconnected(
+ const base::Callback<void(ProtocolHandler*)>& callback) = 0;
// Returns the default request timeout used to process incoming requests.
// The reply to an incoming request should be sent within this timeout or
// else the web server will automatically abort the connection. If the timeout
// is not set, the returned value will be base::TimeDelta::Max().
- base::TimeDelta GetDefaultRequestTimeout() const;
+ virtual base::TimeDelta GetDefaultRequestTimeout() const = 0;
private:
- friend class ProtocolHandler;
- class RequestHandler;
-
- // Handler invoked when a connection is established to web server daemon.
- LIBWEBSERV_PRIVATE void Online(
- org::chromium::WebServer::ServerProxyInterface* server);
-
- // Handler invoked when the web server daemon connection is dropped.
- LIBWEBSERV_PRIVATE void Offline(const dbus::ObjectPath& object_path);
-
- // Handler invoked when a new protocol handler D-Bus proxy object becomes
- // available.
- LIBWEBSERV_PRIVATE void ProtocolHandlerAdded(
- org::chromium::WebServer::ProtocolHandlerProxyInterface* handler);
-
- // Handler invoked when a protocol handler D-Bus proxy object disappears.
- LIBWEBSERV_PRIVATE void ProtocolHandlerRemoved(
- const dbus::ObjectPath& object_path);
-
- // Looks up a protocol handler by ID. If not found, returns nullptr.
- LIBWEBSERV_PRIVATE ProtocolHandler* GetProtocolHandlerByID(
- const std::string& id) const;
-
- // Private implementation of D-Bus RequestHandlerInterface called by the web
- // server daemon whenever a new request is available to be processed.
- std::unique_ptr<RequestHandler> request_handler_;
- // D-Bus object adaptor for RequestHandlerInterface.
- std::unique_ptr<org::chromium::WebServer::RequestHandlerAdaptor>
- dbus_adaptor_;
- // D-Bus object to handler registration of RequestHandlerInterface.
- std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object_;
-
- // A mapping of protocol handler name to the associated object.
- std::map<std::string, std::unique_ptr<ProtocolHandler>>
- protocol_handlers_names_;
- // A mapping of protocol handler IDs to the associated object.
- std::map<std::string, ProtocolHandler*> protocol_handlers_ids_;
- // A map between D-Bus object path of protocol handler and remote protocol
- // handler ID.
- std::map<dbus::ObjectPath, std::string> protocol_handler_id_map_;
-
- // User-specified callbacks for server and protocol handler life-time events.
- base::Closure on_server_online_;
- base::Closure on_server_offline_;
- base::Callback<void(ProtocolHandler*)> on_protocol_handler_connected_;
- base::Callback<void(ProtocolHandler*)> on_protocol_handler_disconnected_;
-
- // D-Bus object manager proxy that receives notification of web server
- // daemon's D-Bus object creation and destruction.
- std::unique_ptr<org::chromium::WebServer::ObjectManagerProxy> object_manager_;
-
- // D-Bus proxy for the web server main object.
- org::chromium::WebServer::ServerProxyInterface* proxy_{nullptr};
-
- // D-Bus service name used by the daemon hosting this object.
- std::string service_name_;
-
DISALLOW_COPY_AND_ASSIGN(Server);
};