blob: 3fe5d0ceab44cd588e34ff59ad14839617700790 [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} {
Vitaly Buka974647f2015-08-02 20:57:43 -070096 web_server_.reset(new libwebserv::Server);
97 web_server_->OnProtocolHandlerConnected(
98 base::Bind(&WebServClient::OnProtocolHandlerConnected,
99 weak_ptr_factory_.GetWeakPtr()));
100 web_server_->OnProtocolHandlerDisconnected(
101 base::Bind(&WebServClient::OnProtocolHandlerDisconnected,
102 weak_ptr_factory_.GetWeakPtr()));
103
Robert Gindacf92c662015-08-20 09:30:11 -0700104 web_server_->Connect(bus, buffet::dbus_constants::kServiceName,
Vitaly Buka974647f2015-08-02 20:57:43 -0700105 sequencer->GetHandler("Server::Connect failed.", true),
106 base::Bind(&base::DoNothing),
107 base::Bind(&base::DoNothing));
108}
109
Alex Vakulenkobe39e932015-10-09 08:10:36 -0700110WebServClient::~WebServClient() {
111 web_server_->Disconnect();
Vitaly Buka974647f2015-08-02 20:57:43 -0700112}
113
Alex Vakulenkobe39e932015-10-09 08:10:36 -0700114void WebServClient::AddHttpRequestHandler(
115 const std::string& path,
116 const RequestHandlerCallback& callback) {
117 web_server_->GetDefaultHttpHandler()->AddHandlerCallback(
118 path, "", base::Bind(&WebServClient::OnRequest,
119 weak_ptr_factory_.GetWeakPtr(), callback));
120}
121
122void WebServClient::AddHttpsRequestHandler(
123 const std::string& path,
124 const RequestHandlerCallback& callback) {
125 web_server_->GetDefaultHttpsHandler()->AddHandlerCallback(
126 path, "", base::Bind(&WebServClient::OnRequest,
127 weak_ptr_factory_.GetWeakPtr(), callback));
128}
129
130uint16_t WebServClient::GetHttpPort() const {
131 return http_port_;
132}
133
134uint16_t WebServClient::GetHttpsPort() const {
135 return https_port_;
136}
137
Alex Vakulenko41705852015-10-13 10:12:06 -0700138brillo::Blob WebServClient::GetHttpsCertificateFingerprint() const {
Alex Vakulenkobe39e932015-10-09 08:10:36 -0700139 return certificate_;
140}
141
142void WebServClient::OnRequest(const RequestHandlerCallback& callback,
143 std::unique_ptr<libwebserv::Request> request,
144 std::unique_ptr<libwebserv::Response> response) {
145 std::unique_ptr<Request> weave_request{
146 new RequestImpl{std::move(request), std::move(response)}};
147 callback.Run(std::move(weave_request));
Vitaly Buka974647f2015-08-02 20:57:43 -0700148}
149
150void WebServClient::OnProtocolHandlerConnected(
151 libwebserv::ProtocolHandler* protocol_handler) {
152 if (protocol_handler->GetName() == libwebserv::ProtocolHandler::kHttp) {
153 http_port_ = *protocol_handler->GetPorts().begin();
154 } else if (protocol_handler->GetName() ==
155 libwebserv::ProtocolHandler::kHttps) {
156 https_port_ = *protocol_handler->GetPorts().begin();
157 certificate_ = protocol_handler->GetCertificateFingerprint();
158 }
Alex Vakulenkobe39e932015-10-09 08:10:36 -0700159 if (https_port_ && https_port_)
160 server_available_callback_.Run();
Vitaly Buka974647f2015-08-02 20:57:43 -0700161}
162
163void WebServClient::OnProtocolHandlerDisconnected(
164 libwebserv::ProtocolHandler* protocol_handler) {
165 if (protocol_handler->GetName() == libwebserv::ProtocolHandler::kHttp) {
166 http_port_ = 0;
167 } else if (protocol_handler->GetName() ==
168 libwebserv::ProtocolHandler::kHttps) {
169 https_port_ = 0;
170 certificate_.clear();
171 }
Vitaly Buka974647f2015-08-02 20:57:43 -0700172}
173
174} // namespace buffet