blob: 3cce096cde38469ec336113370cf492d353de633 [file] [log] [blame]
Christopher Wileyd6197ec2016-01-11 17:05:13 -08001// Copyright 2016 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.
14
Casey Dahlin24d0e752016-02-05 15:48:01 -080015#include "webserv_common/binder_constants.h"
Christopher Wileyd6197ec2016-01-11 17:05:13 -080016
Casey Dahlin242fa232016-02-17 17:01:55 -080017#include "libwebserv/binder_request_handler.h"
Casey Dahlin730b0d52016-02-16 18:22:46 -080018#include "libwebserv/binder_server.h"
19#include "libwebserv/protocol_handler.h"
20#include "libwebserv/request_handler_callback.h"
21
Casey Dahlin730b0d52016-02-16 18:22:46 -080022#include <map>
23#include <set>
Christopher Wileyd6197ec2016-01-11 17:05:13 -080024#include <string>
25#include <vector>
26
Christopher Wileyd6197ec2016-01-11 17:05:13 -080027using android::sp;
28using android::IBinder;
Casey Dahlin2f69b812016-02-16 14:10:48 -080029using android::binder::Status;
Casey Dahlin730b0d52016-02-16 18:22:46 -080030using android::webservd::IProtocolHandler;
31using android::webservd::IRequestHandler;
32using std::map;
33using std::pair;
34using std::set;
Christopher Wileyd6197ec2016-01-11 17:05:13 -080035using std::string;
Casey Dahlin730b0d52016-02-16 18:22:46 -080036using std::unique_ptr;
Christopher Wileyd6197ec2016-01-11 17:05:13 -080037using std::vector;
38
39namespace libwebserv {
40
Casey Dahlinf42e5592016-03-02 14:09:10 -080041class RequestHandlerRegistration {
42 public:
43 RequestHandlerRegistration(const string& url,
44 const string& method,
45 unique_ptr<RequestHandlerInterface> handler)
46 : url_(url),
47 method_(method),
48 handler_(std::move(handler)),
49 binder_handler_(new BinderRequestHandler(handler_.get())) {}
50
51 ~RequestHandlerRegistration() { DropRemotes(); }
52
53 void AddRemote(sp<IProtocolHandler> handler) {
54 string guid;
55
56 if (!handler->AddRequestHandler(url_,
57 method_,
58 binder_handler_,
59 &guid).isOk()) {
60 LOG(WARNING) << "Remote protocol handler failed to "
61 << "register new request handler.";
62 }
63
64 protos_.emplace_back(handler, guid);
65 }
66
67 void DropRemotes() {
68 for (auto& proto : protos_) {
69 if (!proto.first->RemoveRequestHandler(proto.second).isOk()) {
70 LOG(WARNING) << "Could not remove request handler from remote.";
71 }
72 }
73 }
74
75 private:
76 string url_;
77 string method_;
78 unique_ptr<RequestHandlerInterface> handler_;
79 sp<IRequestHandler> binder_handler_;
80 vector<pair<sp<IProtocolHandler>, string>> protos_;
81
82 DISALLOW_COPY_AND_ASSIGN(RequestHandlerRegistration);
83};
84
85// This is libwebserv's binder based process local protocol
86// handler. It wraps around a group of remote protocol handlers
87// that share a common name. It exists independently of the
88// lifetime of the remote protocol handlers and is created on
89// either of:
90// 1) The local process requests a protocol handler by name
91// 2) We connect to the remote webservd process and it has a protocol
92// handler with the given name.
Casey Dahlin730b0d52016-02-16 18:22:46 -080093class BinderProtocolHandler : public ProtocolHandler {
94 public:
95 explicit BinderProtocolHandler(const string& name)
96 : name_(name) {}
97
98 virtual ~BinderProtocolHandler() {
99 ResetRemoteProtocolHandlers();
100 }
101
102 bool AddRemote(sp<IProtocolHandler> handler) {
103 string name;
104 int32_t port;
105 string protocol;
106
107 if (!handler->GetName(&name).isOk()) {
108 LOG(INFO) << "Could not get name of remote protocol handler.";
109 return false;
110 }
111
112 CHECK(name == name_);
113
114 if (!handler->GetPort(&port).isOk()) {
115 LOG(INFO) << "Could not get port for remote protocol handler.";
116 return false;
117 }
118
119 if (!handler->GetProtocol(&protocol).isOk()) {
120 LOG(INFO) << "Could not get protocol for remote protocol handler.";
121 return false;
122 }
123
124 ports_.insert(uint16_t(port));
125 protocols_.insert(protocol);
126 remote_handlers_.push_back(handler);
127
Casey Dahlinf42e5592016-03-02 14:09:10 -0800128 for (auto& request_handler : request_handler_ids_) {
129 request_handler.second->AddRemote(handler);
130 }
131
Casey Dahlin730b0d52016-02-16 18:22:46 -0800132 return true;
133 }
134
135 int AddHandler(const string& url,
136 const string& method,
137 unique_ptr<RequestHandlerInterface> handler) override {
Casey Dahlinf42e5592016-03-02 14:09:10 -0800138 unique_ptr<RequestHandlerRegistration> registration(
139 new RequestHandlerRegistration(url, method, std::move(handler)));
Casey Dahlin730b0d52016-02-16 18:22:46 -0800140
Casey Dahlinf42e5592016-03-02 14:09:10 -0800141 for (sp<IProtocolHandler> remote : remote_handlers_) {
142 registration->AddRemote(remote);
Casey Dahlin730b0d52016-02-16 18:22:46 -0800143 }
144
145 int id = last_handler_id_++;
Casey Dahlinf42e5592016-03-02 14:09:10 -0800146
147 request_handler_ids_.emplace(id, std::move(registration));
148
Casey Dahlin730b0d52016-02-16 18:22:46 -0800149 return id;
150 }
151
152 int AddHandlerCallback(
153 const string& url,
154 const string& method,
155 const base::Callback<RequestHandlerInterface::HandlerSignature>&
156 handler_callback) override {
157 std::unique_ptr<RequestHandlerInterface> handler{
158 new RequestHandlerCallback{handler_callback}};
159 return AddHandler(url, method, std::move(handler));
160 }
161
162 bool RemoveHandler(int handler_id) override {
Casey Dahlinf42e5592016-03-02 14:09:10 -0800163 return request_handler_ids_.erase(handler_id) > 0;
Casey Dahlin730b0d52016-02-16 18:22:46 -0800164 }
165
166 void ResetRemoteProtocolHandlers() {
Casey Dahlinf42e5592016-03-02 14:09:10 -0800167 for (auto& it : request_handler_ids_) {
168 it.second->DropRemotes();
Casey Dahlin730b0d52016-02-16 18:22:46 -0800169 }
170
Casey Dahlin730b0d52016-02-16 18:22:46 -0800171 remote_handlers_.clear();
172 }
173
174 bool IsConnected() const override { return !remote_handlers_.empty(); }
175 string GetName() const override { return name_; }
176 set<uint16_t> GetPorts() const override { return ports_; }
177 set<string> GetProtocols() const override { return protocols_; }
178
179 brillo::Blob GetCertificateFingerprint() const override {
180 brillo::Blob result;
181
182 for (auto& handler : remote_handlers_) {
183 Status status = handler->GetCertificateFingerprint(&result);
184 if (!status.isOk()) {
185 LOG(WARNING) << "Could not get certificate fingerprint "
Ralph Nathan9419e662016-04-13 13:42:07 -0700186 << "from protocol handler: " << status.toString8();
Casey Dahlin730b0d52016-02-16 18:22:46 -0800187 } else if (!result.empty()) {
188 break;
189 }
190 }
191
192 return result;
193 }
194
195 private:
196 int last_handler_id_ = 0;
197 set<uint16_t> ports_;
198 set<string> protocols_;
199 string name_;
200 vector<sp<IProtocolHandler>> remote_handlers_;
201
Casey Dahlinf42e5592016-03-02 14:09:10 -0800202 // Map of local handler IDs to objects containing the various bits of IPC
203 // state we need to maintain those handlers on the remote end.
204 map<int,unique_ptr<RequestHandlerRegistration>> request_handler_ids_;
Casey Dahlin730b0d52016-02-16 18:22:46 -0800205
206 DISALLOW_COPY_AND_ASSIGN(BinderProtocolHandler);
207};
208
Christopher Wileyd6197ec2016-01-11 17:05:13 -0800209BinderServer::BinderServer(brillo::MessageLoop* message_loop,
210 const base::Closure& on_server_online,
211 const base::Closure& on_server_offline,
212 android::BinderWrapper* binder_wrapper)
213 : message_loop_{message_loop},
214 on_server_online_{on_server_online},
215 on_server_offline_{on_server_offline},
216 binder_wrapper_{binder_wrapper} {
217 message_loop_->PostTask(FROM_HERE,
218 base::Bind(&BinderServer::TryConnecting,
219 weak_ptr_factory_.GetWeakPtr()));
220}
221
222void BinderServer::TryConnecting() {
223 ClearLocalState();
Casey Dahlin242fa232016-02-17 17:01:55 -0800224 sp<IBinder> binder = binder_wrapper_->GetService(
Casey Dahlin24d0e752016-02-05 15:48:01 -0800225 webservd::kWebserverBinderServiceName);
Christopher Wileyd6197ec2016-01-11 17:05:13 -0800226 if (!binder.get()) {
227 LOG(INFO) << "Webservd has not registered with service manager.";
228 } else if (!BuildLocalState(binder)) {
229 ClearLocalState();
230 } else {
Casey Dahlincb641832016-03-11 15:12:31 -0800231 if (!on_server_online_.is_null()) {
232 message_loop_->PostTask(FROM_HERE, on_server_online_);
233 }
234
Christopher Wileyd6197ec2016-01-11 17:05:13 -0800235 // Got a binder, built up appropriate local state, our job is done.
236 return;
237 }
238 message_loop_->PostDelayedTask(FROM_HERE,
239 base::Bind(&BinderServer::TryConnecting,
240 weak_ptr_factory_.GetWeakPtr()),
241 base::TimeDelta::FromSeconds(1));
242}
243
Christopher Wileyd6197ec2016-01-11 17:05:13 -0800244void BinderServer::ClearLocalState() {
Casey Dahlin730b0d52016-02-16 18:22:46 -0800245 for (auto& local_handler: local_protocol_handlers_) {
246 local_handler.second->ResetRemoteProtocolHandlers();
Casey Dahlinef1354a2016-03-04 14:12:56 -0800247 if (!on_protocol_handler_disconnected_.is_null()) {
248 message_loop_->PostTask(
249 FROM_HERE, base::Bind(on_protocol_handler_disconnected_,
250 base::Unretained(local_handler.second.get())));
251 }
Casey Dahlin730b0d52016-02-16 18:22:46 -0800252 }
Christopher Wileyd6197ec2016-01-11 17:05:13 -0800253
Casey Dahlincb641832016-03-11 15:12:31 -0800254 if (remote_server_.get() && !on_server_offline_.is_null()) {
255 message_loop_->PostTask(FROM_HERE, on_server_offline_);
256 }
Christopher Wileyd6197ec2016-01-11 17:05:13 -0800257 remote_server_.clear();
258}
259
Casey Dahlin242fa232016-02-17 17:01:55 -0800260bool BinderServer::BuildLocalState(sp<IBinder> server) {
Christopher Wileyd6197ec2016-01-11 17:05:13 -0800261 remote_server_ = android::interface_cast<RemoteServer>(server);
262 vector<sp<IBinder>> remote_raw_binders;
Casey Dahlinf42e5592016-03-02 14:09:10 -0800263 if (!remote_server_->GetProtocolHandlers("", &remote_raw_binders).isOk()) {
Christopher Wileyd6197ec2016-01-11 17:05:13 -0800264 // Possibly the server died, this is not necessarily an error.
265 LOG(INFO) << "Webservd failed to tell us about protocol handlers.";
266 return false;
267 }
268
269 // Tell the local wrappers about the remote handlers that exist now.
270 for (auto& raw_binder: remote_raw_binders) {
271 sp<RemoteProtocolHandler> remote_handler =
272 android::interface_cast<RemoteProtocolHandler>(raw_binder);
Casey Dahlin820d9972016-02-03 15:08:41 -0800273 string name;
Christopher Wileyd6197ec2016-01-11 17:05:13 -0800274 if (!remote_handler->GetName(&name).isOk()) {
275 LOG(INFO) << "Remote handler could not report its name.";
276 return false;
277 }
Casey Dahlin730b0d52016-02-16 18:22:46 -0800278
279 auto it = local_protocol_handlers_.find(name);
280
281 if (it == local_protocol_handlers_.end()) {
282 unique_ptr<BinderProtocolHandler> local_handler(
283 new BinderProtocolHandler(name));
Casey Dahlinf42e5592016-03-02 14:09:10 -0800284 it = local_protocol_handlers_.emplace(name,
285 std::move(local_handler)).first;
Casey Dahlin730b0d52016-02-16 18:22:46 -0800286 }
287
288 it->second->AddRemote(remote_handler);
Casey Dahlinef1354a2016-03-04 14:12:56 -0800289 if (!on_protocol_handler_connected_.is_null()) {
290 message_loop_->PostTask(FROM_HERE,
291 base::Bind(on_protocol_handler_connected_,
292 base::Unretained(it->second.get())));
293 }
Christopher Wileyd6197ec2016-01-11 17:05:13 -0800294 }
295 return true;
296}
297
Casey Dahlin33d72c02016-02-05 11:24:02 -0800298ProtocolHandler* BinderServer::GetDefaultHttpHandler() {
299 return GetProtocolHandler(ProtocolHandler::kHttp);
300}
301
302ProtocolHandler* BinderServer::GetDefaultHttpsHandler() {
303 return GetProtocolHandler(ProtocolHandler::kHttps);
304}
305
Casey Dahlin730b0d52016-02-16 18:22:46 -0800306ProtocolHandler* BinderServer::GetProtocolHandler(const string& name) {
307 auto it = local_protocol_handlers_.find(name);
308
309 if (it == local_protocol_handlers_.end()) {
Casey Dahlinf42e5592016-03-02 14:09:10 -0800310 unique_ptr<BinderProtocolHandler> local_handler(
311 new BinderProtocolHandler(name));
312 it = local_protocol_handlers_.emplace(name,
313 std::move(local_handler)).first;
Casey Dahlin730b0d52016-02-16 18:22:46 -0800314 }
315
316 return it->second.get();
Casey Dahlin33d72c02016-02-05 11:24:02 -0800317}
318
319bool BinderServer::IsConnected() const {
320 return remote_server_.get() != nullptr;
321}
322
323void BinderServer::OnProtocolHandlerConnected(
Casey Dahlinef1354a2016-03-04 14:12:56 -0800324 const base::Callback<void(ProtocolHandler*)>& callback) {
325 on_protocol_handler_connected_ = callback;
326
327 for (auto& handler : local_protocol_handlers_) {
328 if (handler.second->IsConnected()) {
329 message_loop_->PostTask(
330 FROM_HERE,
331 base::Bind(callback, base::Unretained(handler.second.get())));
332 }
333 }
Casey Dahlin33d72c02016-02-05 11:24:02 -0800334}
335
336void BinderServer::OnProtocolHandlerDisconnected(
Casey Dahlinef1354a2016-03-04 14:12:56 -0800337 const base::Callback<void(ProtocolHandler*)>& callback) {
338 on_protocol_handler_disconnected_ = callback;
Casey Dahlin33d72c02016-02-05 11:24:02 -0800339
Casey Dahlinef1354a2016-03-04 14:12:56 -0800340 for (auto& handler : local_protocol_handlers_) {
341 if (!handler.second->IsConnected()) {
342 message_loop_->PostTask(
343 FROM_HERE,
344 base::Bind(callback, base::Unretained(handler.second.get())));
345 }
346 }
Casey Dahlin33d72c02016-02-05 11:24:02 -0800347}
348
349base::TimeDelta BinderServer::GetDefaultRequestTimeout() const {
Casey Dahlin2f69b812016-02-16 14:10:48 -0800350 int32_t timeout_seconds;
351 if (!remote_server_->GetDefaultRequestTimeout(&timeout_seconds).isOk()) {
352 LOG(ERROR) << "Could not get request timeout from remote server.";
353
354 // Precedent from the DBus server says this is the error return value.
355 return base::TimeDelta::Max();
356 }
357
358 return base::TimeDelta::FromSeconds(timeout_seconds);
Casey Dahlin33d72c02016-02-05 11:24:02 -0800359}
360
Christopher Wileyd6197ec2016-01-11 17:05:13 -0800361} // namespace libwebserv