blob: 4a67d75e5a96566baa6208c4d88e9478c852c2fa [file] [log] [blame]
Vitaly Bukacad20f02015-10-16 17:27:15 -07001// 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.
Vitaly Buka974647f2015-08-02 20:57:43 -070014
15#include "buffet/webserv_client.h"
16
17#include <memory>
18#include <string>
19
20#include <libwebserv/protocol_handler.h>
21#include <libwebserv/request.h>
22#include <libwebserv/response.h>
23#include <libwebserv/server.h>
24
25#include "buffet/dbus_constants.h"
Alex Vakulenkob7a325c2015-09-21 10:57:17 -070026#include "buffet/socket_stream.h"
Vitaly Buka974647f2015-08-02 20:57:43 -070027
28namespace buffet {
29
30namespace {
31
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070032using weave::provider::HttpServer;
33
34class RequestImpl : public HttpServer::Request {
Vitaly Buka974647f2015-08-02 20:57:43 -070035 public:
Alex Vakulenkobe39e932015-10-09 08:10:36 -070036 explicit RequestImpl(std::unique_ptr<libwebserv::Request> request,
37 std::unique_ptr<libwebserv::Response> response)
38 : request_{std::move(request)}, response_{std::move(response)} {}
Vitaly Buka974647f2015-08-02 20:57:43 -070039 ~RequestImpl() override {}
40
41 // HttpServer::Request implementation.
Alex Vakulenkobe39e932015-10-09 08:10:36 -070042 std::string GetPath() const override { return request_->GetPath(); }
Alex Vakulenkoe32375b2015-09-28 08:55:40 -070043
Vitaly Buka974647f2015-08-02 20:57:43 -070044 std::string GetFirstHeader(const std::string& name) const override {
45 return request_->GetFirstHeader(name);
46 }
Alex Vakulenkob7a325c2015-09-21 10:57:17 -070047
48 // TODO(avakulenko): Remove this method and rewrite all call sites in libweave
49 // to use GetDataStream() instead.
Alex Vakulenkobe39e932015-10-09 08:10:36 -070050 std::string GetData() override {
Alex Vakulenko458e2c52015-09-25 13:23:43 -070051 if (request_data_)
Alex Vakulenkob7a325c2015-09-21 10:57:17 -070052 return *request_data_;
53
Alex Vakulenkobe39e932015-10-09 08:10:36 -070054 request_data_.reset(new std::string);
Alex Vakulenkob7a325c2015-09-21 10:57:17 -070055 auto stream = request_->GetDataStream();
56 if (stream) {
57 if (stream->CanGetSize())
58 request_data_->reserve(stream->GetRemainingSize());
Alex Vakulenkobe39e932015-10-09 08:10:36 -070059 std::vector<char> buffer(16 * 1024); // 16K seems to be good enough.
Alex Vakulenkob7a325c2015-09-21 10:57:17 -070060 size_t sz = 0;
61 while (stream->ReadBlocking(buffer.data(), buffer.size(), &sz, nullptr) &&
62 sz > 0) {
Alex Vakulenkobe39e932015-10-09 08:10:36 -070063 request_data_->append(buffer.data(), buffer.data() + sz);
Alex Vakulenkob7a325c2015-09-21 10:57:17 -070064 }
65 }
66 return *request_data_;
67 }
68
Alex Vakulenkobe39e932015-10-09 08:10:36 -070069 void SendReply(int status_code,
70 const std::string& data,
71 const std::string& mime_type) override {
72 response_->ReplyWithText(status_code, data, mime_type);
73 }
74
75 std::unique_ptr<weave::Stream> GetDataStream() const {
Alex Vakulenkob7a325c2015-09-21 10:57:17 -070076 auto stream = std::unique_ptr<weave::Stream>{
77 new SocketStream{request_->GetDataStream()}};
78 return stream;
Vitaly Buka974647f2015-08-02 20:57:43 -070079 }
80
81 private:
82 std::unique_ptr<libwebserv::Request> request_;
Alex Vakulenkobe39e932015-10-09 08:10:36 -070083 std::unique_ptr<libwebserv::Response> response_;
84 mutable std::unique_ptr<std::string> request_data_;
Vitaly Buka974647f2015-08-02 20:57:43 -070085
86 DISALLOW_COPY_AND_ASSIGN(RequestImpl);
87};
88
89} // namespace
90
Vitaly Buka974647f2015-08-02 20:57:43 -070091WebServClient::WebServClient(
92 const scoped_refptr<dbus::Bus>& bus,
Alex Vakulenko41705852015-10-13 10:12:06 -070093 brillo::dbus_utils::AsyncEventSequencer* sequencer,
Alex Vakulenkobe39e932015-10-09 08:10:36 -070094 const base::Closure& server_available_callback)
95 : server_available_callback_{server_available_callback} {
Christopher Wileyea011322015-12-22 11:53:23 -080096 web_server_ = libwebserv::Server::ConnectToServerViaDBus(
97 bus, buffet::dbus_constants::kServiceName,
98 sequencer->GetHandler("Server::Connect failed.", true),
99 base::Bind(&base::DoNothing),
100 base::Bind(&base::DoNothing));
Vitaly Buka974647f2015-08-02 20:57:43 -0700101 web_server_->OnProtocolHandlerConnected(
102 base::Bind(&WebServClient::OnProtocolHandlerConnected,
103 weak_ptr_factory_.GetWeakPtr()));
104 web_server_->OnProtocolHandlerDisconnected(
105 base::Bind(&WebServClient::OnProtocolHandlerDisconnected,
106 weak_ptr_factory_.GetWeakPtr()));
Vitaly Buka974647f2015-08-02 20:57:43 -0700107}
108
Christopher Wileyea011322015-12-22 11:53:23 -0800109WebServClient::~WebServClient() {}
Vitaly Buka974647f2015-08-02 20:57:43 -0700110
Alex Vakulenkobe39e932015-10-09 08:10:36 -0700111void WebServClient::AddHttpRequestHandler(
112 const std::string& path,
113 const RequestHandlerCallback& callback) {
114 web_server_->GetDefaultHttpHandler()->AddHandlerCallback(
115 path, "", base::Bind(&WebServClient::OnRequest,
116 weak_ptr_factory_.GetWeakPtr(), callback));
117}
118
119void WebServClient::AddHttpsRequestHandler(
120 const std::string& path,
121 const RequestHandlerCallback& callback) {
122 web_server_->GetDefaultHttpsHandler()->AddHandlerCallback(
123 path, "", base::Bind(&WebServClient::OnRequest,
124 weak_ptr_factory_.GetWeakPtr(), callback));
125}
126
127uint16_t WebServClient::GetHttpPort() const {
128 return http_port_;
129}
130
131uint16_t WebServClient::GetHttpsPort() const {
132 return https_port_;
133}
134
Alex Vakulenkoa071cd92015-11-13 16:11:17 -0800135base::TimeDelta WebServClient::GetRequestTimeout() const {
Alex Vakulenkob55800b2015-11-18 08:49:28 -0800136 return web_server_->GetDefaultRequestTimeout();
Alex Vakulenkoa071cd92015-11-13 16:11:17 -0800137}
138
Alex Vakulenko41705852015-10-13 10:12:06 -0700139brillo::Blob WebServClient::GetHttpsCertificateFingerprint() const {
Alex Vakulenkobe39e932015-10-09 08:10:36 -0700140 return certificate_;
141}
142
143void WebServClient::OnRequest(const RequestHandlerCallback& callback,
144 std::unique_ptr<libwebserv::Request> request,
145 std::unique_ptr<libwebserv::Response> response) {
146 std::unique_ptr<Request> weave_request{
147 new RequestImpl{std::move(request), std::move(response)}};
148 callback.Run(std::move(weave_request));
Vitaly Buka974647f2015-08-02 20:57:43 -0700149}
150
151void WebServClient::OnProtocolHandlerConnected(
152 libwebserv::ProtocolHandler* protocol_handler) {
153 if (protocol_handler->GetName() == libwebserv::ProtocolHandler::kHttp) {
154 http_port_ = *protocol_handler->GetPorts().begin();
155 } else if (protocol_handler->GetName() ==
156 libwebserv::ProtocolHandler::kHttps) {
157 https_port_ = *protocol_handler->GetPorts().begin();
158 certificate_ = protocol_handler->GetCertificateFingerprint();
159 }
Alex Vakulenkobe39e932015-10-09 08:10:36 -0700160 if (https_port_ && https_port_)
161 server_available_callback_.Run();
Vitaly Buka974647f2015-08-02 20:57:43 -0700162}
163
164void WebServClient::OnProtocolHandlerDisconnected(
165 libwebserv::ProtocolHandler* protocol_handler) {
166 if (protocol_handler->GetName() == libwebserv::ProtocolHandler::kHttp) {
167 http_port_ = 0;
168 } else if (protocol_handler->GetName() ==
169 libwebserv::ProtocolHandler::kHttps) {
170 https_port_ = 0;
171 certificate_.clear();
172 }
Vitaly Buka974647f2015-08-02 20:57:43 -0700173}
174
175} // namespace buffet