blob: 3ec66a8bf72bc7ebd0a609b1bf1e8ffc11d51303 [file] [log] [blame]
Daniel Erat35f65872015-08-17 20:59:29 -06001// Copyright 2015 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
Alex Vakulenko039da312015-02-03 08:58:55 -080014
15#include <libwebserv/server.h>
16
Alex Vakulenko31a63792015-02-03 12:44:57 -080017#include <tuple>
Alex Vakulenko039da312015-02-03 08:58:55 -080018#include <vector>
19
Alex Vakulenko31a63792015-02-03 12:44:57 -080020#include <libwebserv/protocol_handler.h>
Alex Vakulenko039da312015-02-03 08:58:55 -080021#include <libwebserv/request.h>
Alex Vakulenko31a63792015-02-03 12:44:57 -080022
Christopher Wiley34bc9df2015-08-19 15:03:47 -070023#include "dbus_bindings/org.chromium.WebServer.RequestHandler.h"
Alex Vakulenko31a63792015-02-03 12:44:57 -080024#include "webservd/dbus-proxies.h"
Alex Vakulenko039da312015-02-03 08:58:55 -080025
26namespace libwebserv {
27
Alex Vakulenko31a63792015-02-03 12:44:57 -080028class Server::RequestHandler final
29 : public org::chromium::WebServer::RequestHandlerInterface {
Alex Vakulenko039da312015-02-03 08:58:55 -080030 public:
Alex Vakulenko31a63792015-02-03 12:44:57 -080031 explicit RequestHandler(Server* server) : server_{server} {}
32 bool ProcessRequest(
33 chromeos::ErrorPtr* error,
34 const std::tuple<std::string, std::string, std::string, std::string,
35 std::string>& in_request_info,
36 const std::vector<std::tuple<std::string, std::string>>& in_headers,
37 const std::vector<std::tuple<bool, std::string, std::string>>& in_params,
38 const std::vector<std::tuple<int32_t, std::string, std::string,
39 std::string, std::string>>& in_files,
40 const std::vector<uint8_t>& in_body) override;
41
42 private:
43 Server* server_{nullptr};
44 DISALLOW_COPY_AND_ASSIGN(RequestHandler);
Alex Vakulenko039da312015-02-03 08:58:55 -080045};
46
Alex Vakulenko31a63792015-02-03 12:44:57 -080047bool Server::RequestHandler::ProcessRequest(
48 chromeos::ErrorPtr* error,
49 const std::tuple<std::string, std::string, std::string, std::string,
50 std::string>& in_request_info,
51 const std::vector<std::tuple<std::string, std::string>>& in_headers,
52 const std::vector<std::tuple<bool, std::string, std::string>>& in_params,
53 const std::vector<std::tuple<int32_t, std::string, std::string,
54 std::string, std::string>>& in_files,
55 const std::vector<uint8_t>& in_body) {
56 std::string protocol_handler_id = std::get<0>(in_request_info);
57 std::string request_handler_id = std::get<1>(in_request_info);
58 std::string request_id = std::get<2>(in_request_info);
59 std::string url = std::get<3>(in_request_info);
60 std::string method = std::get<4>(in_request_info);
61 ProtocolHandler* protocol_handler =
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080062 server_->GetProtocolHandlerByID(protocol_handler_id);
Alex Vakulenko31a63792015-02-03 12:44:57 -080063 if (!protocol_handler) {
64 chromeos::Error::AddToPrintf(error, FROM_HERE,
65 chromeos::errors::dbus::kDomain,
66 DBUS_ERROR_FAILED,
67 "Unknown protocol handler '%s'",
68 protocol_handler_id.c_str());
69 return false;
70 }
71 std::unique_ptr<Request> request{new Request{protocol_handler, url, method}};
72 // Convert request data into format required by the Request object.
73 for (const auto& tuple : in_params) {
74 if (std::get<0>(tuple))
75 request->post_data_.emplace(std::get<1>(tuple), std::get<2>(tuple));
76 else
77 request->get_data_.emplace(std::get<1>(tuple), std::get<2>(tuple));
Alex Vakulenko039da312015-02-03 08:58:55 -080078 }
79
Alex Vakulenko31a63792015-02-03 12:44:57 -080080 for (const auto& tuple : in_headers)
81 request->headers_.emplace(std::get<0>(tuple), std::get<1>(tuple));
Alex Vakulenko039da312015-02-03 08:58:55 -080082
Alex Vakulenko31a63792015-02-03 12:44:57 -080083 for (const auto& tuple : in_files) {
84 request->file_info_.emplace(
85 std::get<1>(tuple), // field_name
86 std::unique_ptr<FileInfo>{new FileInfo{
87 protocol_handler,
88 std::get<0>(tuple), // file_id
89 request_id,
90 std::get<2>(tuple), // file_name
91 std::get<3>(tuple), // content_type
92 std::get<4>(tuple)}}); // transfer_encoding
93 }
94
95 request->raw_data_ = in_body;
96
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080097 return protocol_handler->ProcessRequest(protocol_handler_id,
98 request_handler_id,
Alex Vakulenko31a63792015-02-03 12:44:57 -080099 request_id,
100 std::move(request),
101 error);
102}
103
104Server::Server()
105 : request_handler_{new RequestHandler{this}},
106 dbus_adaptor_{new org::chromium::WebServer::RequestHandlerAdaptor{
107 request_handler_.get()}} {}
Alex Vakulenko039da312015-02-03 08:58:55 -0800108
109Server::~Server() {
Alex Vakulenko039da312015-02-03 08:58:55 -0800110}
111
Alex Vakulenko31a63792015-02-03 12:44:57 -0800112void Server::Connect(
113 const scoped_refptr<dbus::Bus>& bus,
114 const std::string& service_name,
115 const chromeos::dbus_utils::AsyncEventSequencer::CompletionAction& cb,
116 const base::Closure& on_server_online,
117 const base::Closure& on_server_offline) {
118 service_name_ = service_name;
119 dbus_object_.reset(new chromeos::dbus_utils::DBusObject{
120 nullptr, bus, dbus_adaptor_->GetObjectPath()});
121 dbus_adaptor_->RegisterWithDBusObject(dbus_object_.get());
122 dbus_object_->RegisterAsync(cb);
123 on_server_online_ = on_server_online;
124 on_server_offline_ = on_server_offline;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800125 object_manager_.reset(new org::chromium::WebServer::ObjectManagerProxy{bus});
126 object_manager_->SetServerAddedCallback(
127 base::Bind(&Server::Online, base::Unretained(this)));
128 object_manager_->SetServerRemovedCallback(
129 base::Bind(&Server::Offline, base::Unretained(this)));
130 object_manager_->SetProtocolHandlerAddedCallback(
131 base::Bind(&Server::ProtocolHandlerAdded, base::Unretained(this)));
132 object_manager_->SetProtocolHandlerRemovedCallback(
133 base::Bind(&Server::ProtocolHandlerRemoved, base::Unretained(this)));
Alex Vakulenko039da312015-02-03 08:58:55 -0800134}
135
Alex Vakulenko31a63792015-02-03 12:44:57 -0800136void Server::Disconnect() {
Alex Vakulenko31a63792015-02-03 12:44:57 -0800137 on_server_offline_.Reset();
138 on_server_online_.Reset();
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800139 protocol_handlers_ids_.clear();
140 protocol_handlers_names_.clear();
Alex Vakulenko77b4c2b2015-05-22 15:38:42 -0700141 // Release D-Bus object manager proxy after all the dependent maps are freed
142 // (e.g. |protocol_handlers_names_| contains pointers to ProtocolHandlerProxy,
143 // instances of which are owned by the D-Bus object manager).
144 object_manager_.reset();
145 dbus_object_.reset();
Alex Vakulenko31a63792015-02-03 12:44:57 -0800146}
147
148void Server::Online(org::chromium::WebServer::ServerProxy* server) {
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800149 VLOG(1) << "Web server is on-line.";
Alex Vakulenko31a63792015-02-03 12:44:57 -0800150 proxy_ = server;
151 if (!on_server_online_.is_null())
152 on_server_online_.Run();
153}
154
155void Server::Offline(const dbus::ObjectPath& object_path) {
156 if (!on_server_offline_.is_null())
157 on_server_offline_.Run();
158 proxy_ = nullptr;
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800159 VLOG(1) << "Web server is off-line.";
Alex Vakulenko31a63792015-02-03 12:44:57 -0800160}
161
162void Server::ProtocolHandlerAdded(
163 org::chromium::WebServer::ProtocolHandlerProxy* handler) {
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800164 VLOG(1) << "Server-side protocol handler with ID '" << handler->id()
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800165 << "' is on-line (" << handler->name() << ")";
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800166
Alex Vakulenko31a63792015-02-03 12:44:57 -0800167 protocol_handler_id_map_.emplace(handler->GetObjectPath(), handler->id());
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800168 ProtocolHandler* registered_handler = GetProtocolHandler(handler->name());
Alex Vakulenko31a63792015-02-03 12:44:57 -0800169 if (registered_handler) {
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800170 protocol_handlers_ids_.emplace(handler->id(), registered_handler);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800171 registered_handler->Connect(handler);
172 if (!on_protocol_handler_connected_.is_null())
173 on_protocol_handler_connected_.Run(registered_handler);
174 }
175}
176
177void Server::ProtocolHandlerRemoved(const dbus::ObjectPath& object_path) {
178 auto p = protocol_handler_id_map_.find(object_path);
179 if (p == protocol_handler_id_map_.end())
180 return;
181
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800182 VLOG(1) << "Server-side protocol handler with ID '" << p->second
183 << "' is off-line.";
184
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800185 ProtocolHandler* registered_handler = GetProtocolHandlerByID(p->second);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800186 if (registered_handler) {
187 if (!on_protocol_handler_disconnected_.is_null())
188 on_protocol_handler_disconnected_.Run(registered_handler);
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800189 registered_handler->Disconnect(object_path);
190 protocol_handlers_ids_.erase(p->second);
Alex Vakulenko039da312015-02-03 08:58:55 -0800191 }
192
Alex Vakulenko31a63792015-02-03 12:44:57 -0800193 protocol_handler_id_map_.erase(p);
Alex Vakulenko039da312015-02-03 08:58:55 -0800194}
195
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800196ProtocolHandler* Server::GetProtocolHandler(const std::string& name) {
197 auto p = protocol_handlers_names_.find(name);
198 if (p == protocol_handlers_names_.end()) {
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800199 VLOG(1) << "Creating a client-side instance of web server's protocol "
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800200 << "handler with name '" << name << "'";
201 p = protocol_handlers_names_.emplace(
202 name,
203 std::unique_ptr<ProtocolHandler>{new ProtocolHandler{name, this}})
204 .first;
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800205 }
206 return p->second.get();
Alex Vakulenko039da312015-02-03 08:58:55 -0800207}
208
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800209ProtocolHandler* Server::GetDefaultHttpHandler() {
Alex Vakulenko31a63792015-02-03 12:44:57 -0800210 return GetProtocolHandler(ProtocolHandler::kHttp);
Alex Vakulenko039da312015-02-03 08:58:55 -0800211}
212
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800213ProtocolHandler* Server::GetDefaultHttpsHandler() {
Alex Vakulenko31a63792015-02-03 12:44:57 -0800214 return GetProtocolHandler(ProtocolHandler::kHttps);
Alex Vakulenko039da312015-02-03 08:58:55 -0800215}
216
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800217ProtocolHandler* Server::GetProtocolHandlerByID(const std::string& id) const {
218 auto p = protocol_handlers_ids_.find(id);
219 if (p == protocol_handlers_ids_.end()) {
220 LOG(ERROR) << "Unable to locate protocol handler with ID '" << id << "'";
221 return nullptr;
222 }
223 return p->second;
224}
225
Alex Vakulenko31a63792015-02-03 12:44:57 -0800226void Server::OnProtocolHandlerConnected(
227 const base::Callback<void(ProtocolHandler*)>& callback) {
228 on_protocol_handler_connected_ = callback;
Alex Vakulenko039da312015-02-03 08:58:55 -0800229}
230
Alex Vakulenko31a63792015-02-03 12:44:57 -0800231void Server::OnProtocolHandlerDisconnected(
232 const base::Callback<void(ProtocolHandler*)>& callback) {
233 on_protocol_handler_disconnected_ = callback;
Alex Vakulenko039da312015-02-03 08:58:55 -0800234}
235
Alex Vakulenko039da312015-02-03 08:58:55 -0800236} // namespace libwebserv