blob: ed38988e2f9b5a9cd5f8bc1f11579468edca7033 [file] [log] [blame]
Alex Vakulenko039da312015-02-03 08:58:55 -08001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <libwebserv/server.h>
6
Alex Vakulenko31a63792015-02-03 12:44:57 -08007#include <tuple>
Alex Vakulenko039da312015-02-03 08:58:55 -08008#include <vector>
9
Alex Vakulenko31a63792015-02-03 12:44:57 -080010#include <libwebserv/protocol_handler.h>
Alex Vakulenko039da312015-02-03 08:58:55 -080011#include <libwebserv/request.h>
Alex Vakulenko31a63792015-02-03 12:44:57 -080012
13#include "libwebserv/org.chromium.WebServer.RequestHandler.h"
14#include "webservd/dbus-proxies.h"
Alex Vakulenko039da312015-02-03 08:58:55 -080015
16namespace libwebserv {
17
Alex Vakulenko31a63792015-02-03 12:44:57 -080018class Server::RequestHandler final
19 : public org::chromium::WebServer::RequestHandlerInterface {
Alex Vakulenko039da312015-02-03 08:58:55 -080020 public:
Alex Vakulenko31a63792015-02-03 12:44:57 -080021 explicit RequestHandler(Server* server) : server_{server} {}
22 bool ProcessRequest(
23 chromeos::ErrorPtr* error,
24 const std::tuple<std::string, std::string, std::string, std::string,
25 std::string>& in_request_info,
26 const std::vector<std::tuple<std::string, std::string>>& in_headers,
27 const std::vector<std::tuple<bool, std::string, std::string>>& in_params,
28 const std::vector<std::tuple<int32_t, std::string, std::string,
29 std::string, std::string>>& in_files,
30 const std::vector<uint8_t>& in_body) override;
31
32 private:
33 Server* server_{nullptr};
34 DISALLOW_COPY_AND_ASSIGN(RequestHandler);
Alex Vakulenko039da312015-02-03 08:58:55 -080035};
36
Alex Vakulenko31a63792015-02-03 12:44:57 -080037bool Server::RequestHandler::ProcessRequest(
38 chromeos::ErrorPtr* error,
39 const std::tuple<std::string, std::string, std::string, std::string,
40 std::string>& in_request_info,
41 const std::vector<std::tuple<std::string, std::string>>& in_headers,
42 const std::vector<std::tuple<bool, std::string, std::string>>& in_params,
43 const std::vector<std::tuple<int32_t, std::string, std::string,
44 std::string, std::string>>& in_files,
45 const std::vector<uint8_t>& in_body) {
46 std::string protocol_handler_id = std::get<0>(in_request_info);
47 std::string request_handler_id = std::get<1>(in_request_info);
48 std::string request_id = std::get<2>(in_request_info);
49 std::string url = std::get<3>(in_request_info);
50 std::string method = std::get<4>(in_request_info);
51 ProtocolHandler* protocol_handler =
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080052 server_->GetProtocolHandlerByID(protocol_handler_id);
Alex Vakulenko31a63792015-02-03 12:44:57 -080053 if (!protocol_handler) {
54 chromeos::Error::AddToPrintf(error, FROM_HERE,
55 chromeos::errors::dbus::kDomain,
56 DBUS_ERROR_FAILED,
57 "Unknown protocol handler '%s'",
58 protocol_handler_id.c_str());
59 return false;
60 }
61 std::unique_ptr<Request> request{new Request{protocol_handler, url, method}};
62 // Convert request data into format required by the Request object.
63 for (const auto& tuple : in_params) {
64 if (std::get<0>(tuple))
65 request->post_data_.emplace(std::get<1>(tuple), std::get<2>(tuple));
66 else
67 request->get_data_.emplace(std::get<1>(tuple), std::get<2>(tuple));
Alex Vakulenko039da312015-02-03 08:58:55 -080068 }
69
Alex Vakulenko31a63792015-02-03 12:44:57 -080070 for (const auto& tuple : in_headers)
71 request->headers_.emplace(std::get<0>(tuple), std::get<1>(tuple));
Alex Vakulenko039da312015-02-03 08:58:55 -080072
Alex Vakulenko31a63792015-02-03 12:44:57 -080073 for (const auto& tuple : in_files) {
74 request->file_info_.emplace(
75 std::get<1>(tuple), // field_name
76 std::unique_ptr<FileInfo>{new FileInfo{
77 protocol_handler,
78 std::get<0>(tuple), // file_id
79 request_id,
80 std::get<2>(tuple), // file_name
81 std::get<3>(tuple), // content_type
82 std::get<4>(tuple)}}); // transfer_encoding
83 }
84
85 request->raw_data_ = in_body;
86
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080087 return protocol_handler->ProcessRequest(protocol_handler_id,
88 request_handler_id,
Alex Vakulenko31a63792015-02-03 12:44:57 -080089 request_id,
90 std::move(request),
91 error);
92}
93
94Server::Server()
95 : request_handler_{new RequestHandler{this}},
96 dbus_adaptor_{new org::chromium::WebServer::RequestHandlerAdaptor{
97 request_handler_.get()}} {}
Alex Vakulenko039da312015-02-03 08:58:55 -080098
99Server::~Server() {
Alex Vakulenko039da312015-02-03 08:58:55 -0800100}
101
Alex Vakulenko31a63792015-02-03 12:44:57 -0800102void Server::Connect(
103 const scoped_refptr<dbus::Bus>& bus,
104 const std::string& service_name,
105 const chromeos::dbus_utils::AsyncEventSequencer::CompletionAction& cb,
106 const base::Closure& on_server_online,
107 const base::Closure& on_server_offline) {
108 service_name_ = service_name;
109 dbus_object_.reset(new chromeos::dbus_utils::DBusObject{
110 nullptr, bus, dbus_adaptor_->GetObjectPath()});
111 dbus_adaptor_->RegisterWithDBusObject(dbus_object_.get());
112 dbus_object_->RegisterAsync(cb);
113 on_server_online_ = on_server_online;
114 on_server_offline_ = on_server_offline;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800115 object_manager_.reset(new org::chromium::WebServer::ObjectManagerProxy{bus});
116 object_manager_->SetServerAddedCallback(
117 base::Bind(&Server::Online, base::Unretained(this)));
118 object_manager_->SetServerRemovedCallback(
119 base::Bind(&Server::Offline, base::Unretained(this)));
120 object_manager_->SetProtocolHandlerAddedCallback(
121 base::Bind(&Server::ProtocolHandlerAdded, base::Unretained(this)));
122 object_manager_->SetProtocolHandlerRemovedCallback(
123 base::Bind(&Server::ProtocolHandlerRemoved, base::Unretained(this)));
Alex Vakulenko039da312015-02-03 08:58:55 -0800124}
125
Alex Vakulenko31a63792015-02-03 12:44:57 -0800126void Server::Disconnect() {
127 object_manager_.reset();
128 on_server_offline_.Reset();
129 on_server_online_.Reset();
130 dbus_object_.reset();
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800131 protocol_handlers_ids_.clear();
132 protocol_handlers_names_.clear();
Alex Vakulenko31a63792015-02-03 12:44:57 -0800133}
134
135void Server::Online(org::chromium::WebServer::ServerProxy* server) {
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800136 VLOG(1) << "Web server is on-line.";
Alex Vakulenko31a63792015-02-03 12:44:57 -0800137 proxy_ = server;
138 if (!on_server_online_.is_null())
139 on_server_online_.Run();
140}
141
142void Server::Offline(const dbus::ObjectPath& object_path) {
143 if (!on_server_offline_.is_null())
144 on_server_offline_.Run();
145 proxy_ = nullptr;
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800146 VLOG(1) << "Web server is off-line.";
Alex Vakulenko31a63792015-02-03 12:44:57 -0800147}
148
149void Server::ProtocolHandlerAdded(
150 org::chromium::WebServer::ProtocolHandlerProxy* handler) {
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800151 VLOG(1) << "Server-side protocol handler with ID '" << handler->id()
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800152 << "' is on-line (" << handler->name() << ")";
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800153
Alex Vakulenko31a63792015-02-03 12:44:57 -0800154 protocol_handler_id_map_.emplace(handler->GetObjectPath(), handler->id());
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800155 ProtocolHandler* registered_handler = GetProtocolHandler(handler->name());
Alex Vakulenko31a63792015-02-03 12:44:57 -0800156 if (registered_handler) {
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800157 protocol_handlers_ids_.emplace(handler->id(), registered_handler);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800158 registered_handler->Connect(handler);
159 if (!on_protocol_handler_connected_.is_null())
160 on_protocol_handler_connected_.Run(registered_handler);
161 }
162}
163
164void Server::ProtocolHandlerRemoved(const dbus::ObjectPath& object_path) {
165 auto p = protocol_handler_id_map_.find(object_path);
166 if (p == protocol_handler_id_map_.end())
167 return;
168
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800169 VLOG(1) << "Server-side protocol handler with ID '" << p->second
170 << "' is off-line.";
171
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800172 ProtocolHandler* registered_handler = GetProtocolHandlerByID(p->second);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800173 if (registered_handler) {
174 if (!on_protocol_handler_disconnected_.is_null())
175 on_protocol_handler_disconnected_.Run(registered_handler);
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800176 registered_handler->Disconnect(object_path);
177 protocol_handlers_ids_.erase(p->second);
Alex Vakulenko039da312015-02-03 08:58:55 -0800178 }
179
Alex Vakulenko31a63792015-02-03 12:44:57 -0800180 protocol_handler_id_map_.erase(p);
Alex Vakulenko039da312015-02-03 08:58:55 -0800181}
182
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800183ProtocolHandler* Server::GetProtocolHandler(const std::string& name) {
184 auto p = protocol_handlers_names_.find(name);
185 if (p == protocol_handlers_names_.end()) {
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800186 VLOG(1) << "Creating a client-side instance of web server's protocol "
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800187 << "handler with name '" << name << "'";
188 p = protocol_handlers_names_.emplace(
189 name,
190 std::unique_ptr<ProtocolHandler>{new ProtocolHandler{name, this}})
191 .first;
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800192 }
193 return p->second.get();
Alex Vakulenko039da312015-02-03 08:58:55 -0800194}
195
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800196ProtocolHandler* Server::GetDefaultHttpHandler() {
Alex Vakulenko31a63792015-02-03 12:44:57 -0800197 return GetProtocolHandler(ProtocolHandler::kHttp);
Alex Vakulenko039da312015-02-03 08:58:55 -0800198}
199
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800200ProtocolHandler* Server::GetDefaultHttpsHandler() {
Alex Vakulenko31a63792015-02-03 12:44:57 -0800201 return GetProtocolHandler(ProtocolHandler::kHttps);
Alex Vakulenko039da312015-02-03 08:58:55 -0800202}
203
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800204ProtocolHandler* Server::GetProtocolHandlerByID(const std::string& id) const {
205 auto p = protocol_handlers_ids_.find(id);
206 if (p == protocol_handlers_ids_.end()) {
207 LOG(ERROR) << "Unable to locate protocol handler with ID '" << id << "'";
208 return nullptr;
209 }
210 return p->second;
211}
212
Alex Vakulenko31a63792015-02-03 12:44:57 -0800213void Server::OnProtocolHandlerConnected(
214 const base::Callback<void(ProtocolHandler*)>& callback) {
215 on_protocol_handler_connected_ = callback;
Alex Vakulenko039da312015-02-03 08:58:55 -0800216}
217
Alex Vakulenko31a63792015-02-03 12:44:57 -0800218void Server::OnProtocolHandlerDisconnected(
219 const base::Callback<void(ProtocolHandler*)>& callback) {
220 on_protocol_handler_disconnected_ = callback;
Alex Vakulenko039da312015-02-03 08:58:55 -0800221}
222
Alex Vakulenko039da312015-02-03 08:58:55 -0800223} // namespace libwebserv