blob: 2bf7c7db0b0b0439678731a97ba18120ef24fbbf [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;
114 AddProtocolHandler(std::unique_ptr<ProtocolHandler>{
115 new ProtocolHandler{ProtocolHandler::kHttp, this}});
116 AddProtocolHandler(std::unique_ptr<ProtocolHandler>{
117 new ProtocolHandler{ProtocolHandler::kHttps, this}});
118 object_manager_.reset(new org::chromium::WebServer::ObjectManagerProxy{bus});
119 object_manager_->SetServerAddedCallback(
120 base::Bind(&Server::Online, base::Unretained(this)));
121 object_manager_->SetServerRemovedCallback(
122 base::Bind(&Server::Offline, base::Unretained(this)));
123 object_manager_->SetProtocolHandlerAddedCallback(
124 base::Bind(&Server::ProtocolHandlerAdded, base::Unretained(this)));
125 object_manager_->SetProtocolHandlerRemovedCallback(
126 base::Bind(&Server::ProtocolHandlerRemoved, base::Unretained(this)));
Alex Vakulenko039da312015-02-03 08:58:55 -0800127}
128
Alex Vakulenko31a63792015-02-03 12:44:57 -0800129void Server::Disconnect() {
130 object_manager_.reset();
131 on_server_offline_.Reset();
132 on_server_online_.Reset();
133 dbus_object_.reset();
134 protocol_handlers_.clear();
135}
136
137void Server::Online(org::chromium::WebServer::ServerProxy* server) {
138 proxy_ = server;
139 if (!on_server_online_.is_null())
140 on_server_online_.Run();
141}
142
143void Server::Offline(const dbus::ObjectPath& object_path) {
144 if (!on_server_offline_.is_null())
145 on_server_offline_.Run();
146 proxy_ = nullptr;
147}
148
149void Server::ProtocolHandlerAdded(
150 org::chromium::WebServer::ProtocolHandlerProxy* handler) {
151 protocol_handler_id_map_.emplace(handler->GetObjectPath(), handler->id());
152 ProtocolHandler* registered_handler = GetProtocolHandler(handler->id());
153 if (registered_handler) {
154 registered_handler->Connect(handler);
155 if (!on_protocol_handler_connected_.is_null())
156 on_protocol_handler_connected_.Run(registered_handler);
157 }
158}
159
160void Server::ProtocolHandlerRemoved(const dbus::ObjectPath& object_path) {
161 auto p = protocol_handler_id_map_.find(object_path);
162 if (p == protocol_handler_id_map_.end())
163 return;
164
165 ProtocolHandler* registered_handler = GetProtocolHandler(p->second);
166 if (registered_handler) {
167 if (!on_protocol_handler_disconnected_.is_null())
168 on_protocol_handler_disconnected_.Run(registered_handler);
169 registered_handler->Disconnect();
Alex Vakulenko039da312015-02-03 08:58:55 -0800170 }
171
Alex Vakulenko31a63792015-02-03 12:44:57 -0800172 protocol_handler_id_map_.erase(p);
Alex Vakulenko039da312015-02-03 08:58:55 -0800173}
174
Alex Vakulenko31a63792015-02-03 12:44:57 -0800175ProtocolHandler* Server::GetProtocolHandler(const std::string& id) const {
176 auto p = protocol_handlers_.find(id);
177 return (p != protocol_handlers_.end()) ? p->second.get() : nullptr;
Alex Vakulenko039da312015-02-03 08:58:55 -0800178}
179
Alex Vakulenko31a63792015-02-03 12:44:57 -0800180ProtocolHandler* Server::GetDefaultHttpHandler() const {
181 return GetProtocolHandler(ProtocolHandler::kHttp);
Alex Vakulenko039da312015-02-03 08:58:55 -0800182}
183
Alex Vakulenko31a63792015-02-03 12:44:57 -0800184ProtocolHandler* Server::GetDefaultHttpsHandler() const {
185 return GetProtocolHandler(ProtocolHandler::kHttps);
Alex Vakulenko039da312015-02-03 08:58:55 -0800186}
187
Alex Vakulenko31a63792015-02-03 12:44:57 -0800188void Server::OnProtocolHandlerConnected(
189 const base::Callback<void(ProtocolHandler*)>& callback) {
190 on_protocol_handler_connected_ = callback;
Alex Vakulenko039da312015-02-03 08:58:55 -0800191}
192
Alex Vakulenko31a63792015-02-03 12:44:57 -0800193void Server::OnProtocolHandlerDisconnected(
194 const base::Callback<void(ProtocolHandler*)>& callback) {
195 on_protocol_handler_disconnected_ = callback;
Alex Vakulenko039da312015-02-03 08:58:55 -0800196}
197
Alex Vakulenko31a63792015-02-03 12:44:57 -0800198void Server::AddProtocolHandler(std::unique_ptr<ProtocolHandler> handler) {
199 // Make sure a handler with this ID isn't already registered.
200 CHECK(protocol_handlers_.find(handler->GetID()) == protocol_handlers_.end());
201 protocol_handlers_.emplace(handler->GetID(), std::move(handler));
Alex Vakulenko039da312015-02-03 08:58:55 -0800202}
203
204} // namespace libwebserv