blob: 4b8403ebe0bfe445a0bde9e20b80e70f83510339 [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 =
52 server_->GetProtocolHandler(protocol_handler_id);
53 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
87 return protocol_handler->ProcessRequest(request_handler_id,
88 request_id,
89 std::move(request),
90 error);
91}
92
93Server::Server()
94 : request_handler_{new RequestHandler{this}},
95 dbus_adaptor_{new org::chromium::WebServer::RequestHandlerAdaptor{
96 request_handler_.get()}} {}
Alex Vakulenko039da312015-02-03 08:58:55 -080097
98Server::~Server() {
Alex Vakulenko039da312015-02-03 08:58:55 -080099}
100
Alex Vakulenko31a63792015-02-03 12:44:57 -0800101void Server::Connect(
102 const scoped_refptr<dbus::Bus>& bus,
103 const std::string& service_name,
104 const chromeos::dbus_utils::AsyncEventSequencer::CompletionAction& cb,
105 const base::Closure& on_server_online,
106 const base::Closure& on_server_offline) {
107 service_name_ = service_name;
108 dbus_object_.reset(new chromeos::dbus_utils::DBusObject{
109 nullptr, bus, dbus_adaptor_->GetObjectPath()});
110 dbus_adaptor_->RegisterWithDBusObject(dbus_object_.get());
111 dbus_object_->RegisterAsync(cb);
112 on_server_online_ = on_server_online;
113 on_server_offline_ = on_server_offline;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800114 object_manager_.reset(new org::chromium::WebServer::ObjectManagerProxy{bus});
115 object_manager_->SetServerAddedCallback(
116 base::Bind(&Server::Online, base::Unretained(this)));
117 object_manager_->SetServerRemovedCallback(
118 base::Bind(&Server::Offline, base::Unretained(this)));
119 object_manager_->SetProtocolHandlerAddedCallback(
120 base::Bind(&Server::ProtocolHandlerAdded, base::Unretained(this)));
121 object_manager_->SetProtocolHandlerRemovedCallback(
122 base::Bind(&Server::ProtocolHandlerRemoved, base::Unretained(this)));
Alex Vakulenko039da312015-02-03 08:58:55 -0800123}
124
Alex Vakulenko31a63792015-02-03 12:44:57 -0800125void Server::Disconnect() {
126 object_manager_.reset();
127 on_server_offline_.Reset();
128 on_server_online_.Reset();
129 dbus_object_.reset();
130 protocol_handlers_.clear();
131}
132
133void Server::Online(org::chromium::WebServer::ServerProxy* server) {
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800134 VLOG(1) << "Web server is on-line.";
Alex Vakulenko31a63792015-02-03 12:44:57 -0800135 proxy_ = server;
136 if (!on_server_online_.is_null())
137 on_server_online_.Run();
138}
139
140void Server::Offline(const dbus::ObjectPath& object_path) {
141 if (!on_server_offline_.is_null())
142 on_server_offline_.Run();
143 proxy_ = nullptr;
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800144 VLOG(1) << "Web server is off-line.";
Alex Vakulenko31a63792015-02-03 12:44:57 -0800145}
146
147void Server::ProtocolHandlerAdded(
148 org::chromium::WebServer::ProtocolHandlerProxy* handler) {
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800149 VLOG(1) << "Server-side protocol handler with ID '" << handler->id()
150 << "' is on-line.";
151
Alex Vakulenko31a63792015-02-03 12:44:57 -0800152 protocol_handler_id_map_.emplace(handler->GetObjectPath(), handler->id());
153 ProtocolHandler* registered_handler = GetProtocolHandler(handler->id());
154 if (registered_handler) {
155 registered_handler->Connect(handler);
156 if (!on_protocol_handler_connected_.is_null())
157 on_protocol_handler_connected_.Run(registered_handler);
158 }
159}
160
161void Server::ProtocolHandlerRemoved(const dbus::ObjectPath& object_path) {
162 auto p = protocol_handler_id_map_.find(object_path);
163 if (p == protocol_handler_id_map_.end())
164 return;
165
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800166 VLOG(1) << "Server-side protocol handler with ID '" << p->second
167 << "' is off-line.";
168
Alex Vakulenko31a63792015-02-03 12:44:57 -0800169 ProtocolHandler* registered_handler = GetProtocolHandler(p->second);
170 if (registered_handler) {
171 if (!on_protocol_handler_disconnected_.is_null())
172 on_protocol_handler_disconnected_.Run(registered_handler);
173 registered_handler->Disconnect();
Alex Vakulenko039da312015-02-03 08:58:55 -0800174 }
175
Alex Vakulenko31a63792015-02-03 12:44:57 -0800176 protocol_handler_id_map_.erase(p);
Alex Vakulenko039da312015-02-03 08:58:55 -0800177}
178
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800179ProtocolHandler* Server::GetProtocolHandler(const std::string& id) {
Alex Vakulenko31a63792015-02-03 12:44:57 -0800180 auto p = protocol_handlers_.find(id);
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800181 if (p == protocol_handlers_.end()) {
182 VLOG(1) << "Creating a client-side instance of web server's protocol "
183 << "handler with ID '" << id << "'";
184 p = protocol_handlers_.emplace(
185 id,
186 std::unique_ptr<ProtocolHandler>{new ProtocolHandler{id, this}}).first;
187 }
188 return p->second.get();
Alex Vakulenko039da312015-02-03 08:58:55 -0800189}
190
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800191ProtocolHandler* Server::GetDefaultHttpHandler() {
Alex Vakulenko31a63792015-02-03 12:44:57 -0800192 return GetProtocolHandler(ProtocolHandler::kHttp);
Alex Vakulenko039da312015-02-03 08:58:55 -0800193}
194
Alex Vakulenkoa9352552015-02-17 12:49:59 -0800195ProtocolHandler* Server::GetDefaultHttpsHandler() {
Alex Vakulenko31a63792015-02-03 12:44:57 -0800196 return GetProtocolHandler(ProtocolHandler::kHttps);
Alex Vakulenko039da312015-02-03 08:58:55 -0800197}
198
Alex Vakulenko31a63792015-02-03 12:44:57 -0800199void Server::OnProtocolHandlerConnected(
200 const base::Callback<void(ProtocolHandler*)>& callback) {
201 on_protocol_handler_connected_ = callback;
Alex Vakulenko039da312015-02-03 08:58:55 -0800202}
203
Alex Vakulenko31a63792015-02-03 12:44:57 -0800204void Server::OnProtocolHandlerDisconnected(
205 const base::Callback<void(ProtocolHandler*)>& callback) {
206 on_protocol_handler_disconnected_ = callback;
Alex Vakulenko039da312015-02-03 08:58:55 -0800207}
208
Alex Vakulenko039da312015-02-03 08:58:55 -0800209} // namespace libwebserv