blob: ab5e0acf16f3c04cc63f3a18d7e6250980a3ec24 [file] [log] [blame]
Daniel Erat35f65872015-08-17 20:59:29 -06001// 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.
Alex Vakulenko31a63792015-02-03 12:44:57 -080014
15#ifndef WEBSERVER_LIBWEBSERV_PROTOCOL_HANDLER_H_
16#define WEBSERVER_LIBWEBSERV_PROTOCOL_HANDLER_H_
17
18#include <map>
19#include <memory>
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080020#include <set>
Alex Vakulenko31a63792015-02-03 12:44:57 -080021#include <string>
22#include <vector>
23
24#include <base/callback_forward.h>
25#include <base/macros.h>
26#include <base/memory/weak_ptr.h>
Alex Vakulenko75d6da22015-10-13 10:01:34 -070027#include <brillo/errors/error.h>
28#include <brillo/secure_blob.h>
29#include <brillo/streams/stream.h>
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080030#include <dbus/object_path.h>
Alex Vakulenko31a63792015-02-03 12:44:57 -080031
32#include <libwebserv/export.h>
33#include <libwebserv/request_handler_interface.h>
34
35namespace org {
36namespace chromium {
37namespace WebServer {
38
39class ProtocolHandlerProxy;
40
41} // namespace WebServer
42} // namespace chromium
43} // namespace org
44
45namespace libwebserv {
46
47class Server;
48class Request;
49
50// Wrapper around a protocol handler (e.g. HTTP or HTTPs).
51// ProtocolHandler allows consumers to add request handlers on a given protocol.
52// When the ProtocolHandler is connected, allows users to read port and protocol
53// information.
54class LIBWEBSERV_EXPORT ProtocolHandler final {
55 public:
Alex Vakulenko3d8c9122015-03-13 13:54:00 -070056 ProtocolHandler(const std::string& name, Server* server);
Alex Vakulenko31a63792015-02-03 12:44:57 -080057 ~ProtocolHandler();
58
59 // Returns true if the protocol handler object is connected to the web server
60 // daemon's proxy object and is capable of processing incoming requests.
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080061 bool IsConnected() const { return !proxies_.empty(); }
Alex Vakulenko31a63792015-02-03 12:44:57 -080062
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080063 // Handler's name identifier (as provided in "name" setting of config file).
64 // Standard/default handler names are "http" and "https".
65 std::string GetName() const;
Alex Vakulenko31a63792015-02-03 12:44:57 -080066
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080067 // Returns the ports the handler is bound to. There could be multiple.
68 // If the handler is not connected to the server, this will return an empty
69 // set.
70 std::set<uint16_t> GetPorts() const;
Alex Vakulenko31a63792015-02-03 12:44:57 -080071
72 // Returns the transport protocol that is served by this handler.
73 // Can be either "http" or "https".
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080074 // If the handler is not connected to the server, this will return an empty
75 // set.
76 std::set<std::string> GetProtocols() const;
Alex Vakulenko31a63792015-02-03 12:44:57 -080077
78 // Returns a SHA-256 fingerprint of HTTPS certificate used. Returns an empty
79 // byte buffer if this handler does not serve the HTTPS protocol.
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080080 // If the handler is not connected to the server, this will return an empty
81 // array.
Alex Vakulenko75d6da22015-10-13 10:01:34 -070082 brillo::Blob GetCertificateFingerprint() const;
Alex Vakulenko31a63792015-02-03 12:44:57 -080083
84 // Adds a request handler for given |url|. If the |url| ends with a '/', this
85 // makes the handler respond to any URL beneath this path.
86 // Note that it is not possible to add a specific handler just for the root
87 // path "/". Doing so means "respond to any URL".
88 // |method| is optional request method verb, such as "GET" or "POST".
89 // If |method| is empty, the handler responds to any request verb.
90 // If there are more than one handler for a given request, the most specific
91 // match is chosen. For example, if there are the following handlers provided:
92 // - A["/foo/", ""]
93 // - B["/foo/bar", "GET"]
94 // - C["/foo/bar", ""]
95 // Here is what handlers are called when making certain requests:
96 // - GET("/foo/bar") => B[]
97 // - POST("/foo/bar") => C[]
98 // - PUT("/foo/bar") => C[]
99 // - GET("/foo/baz") => A[]
100 // - GET("/foo") => 404 Not Found
101 // This functions returns a handler ID which can be used later to remove
102 // the handler.
103 //
104 // The handler registration information is stored inside ProtocolHandler and
105 // is used to register the handlers with the web server daemon when it becomes
106 // available. This also happens when the web server goes away and then comes
107 // back (e.g. restarted). So, there is no need to re-register the handlers
108 // once the web server process is restarted.
109 int AddHandler(const std::string& url,
110 const std::string& method,
111 std::unique_ptr<RequestHandlerInterface> handler);
112
113 // Similar to AddHandler() above but the handler is just a callback function.
114 int AddHandlerCallback(
115 const std::string& url,
116 const std::string& method,
117 const base::Callback<RequestHandlerInterface::HandlerSignature>&
118 handler_callback);
119
120 // Removes the handler with the specified |handler_id|.
121 // Returns false if the handler with the given ID is not found.
122 bool RemoveHandler(int handler_id);
123
124 static const char kHttp[];
125 static const char kHttps[];
126
127 private:
128 friend class FileInfo;
129 friend class Server;
Christopher Book692fdfd2015-11-24 08:53:31 -0500130 friend class ResponseImpl;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800131
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800132 using ProtocolHandlerProxy = org::chromium::WebServer::ProtocolHandlerProxy;
133
Alex Vakulenko31a63792015-02-03 12:44:57 -0800134 struct LIBWEBSERV_PRIVATE HandlerMapEntry {
135 std::string url;
136 std::string method;
Alex Vakulenko3d8c9122015-03-13 13:54:00 -0700137 std::map<ProtocolHandlerProxy*, std::string> remote_handler_ids;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800138 std::unique_ptr<RequestHandlerInterface> handler;
139 };
140
141 // Called by the Server class when the D-Bus proxy object gets connected
142 // to the web server daemon.
143
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800144 LIBWEBSERV_PRIVATE void Connect(ProtocolHandlerProxy* proxy);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800145 // Called by the Server class when the D-Bus proxy object gets disconnected
146 // from the web server daemon.
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800147 LIBWEBSERV_PRIVATE void Disconnect(const dbus::ObjectPath& object_path);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800148
149 // Asynchronous callbacks to handle successful or failed request handler
150 // registration over D-Bus.
151 LIBWEBSERV_PRIVATE void AddHandlerSuccess(
Alex Vakulenko3d8c9122015-03-13 13:54:00 -0700152 int handler_id,
153 ProtocolHandlerProxy* proxy,
154 const std::string& remote_handler_id);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800155 LIBWEBSERV_PRIVATE void AddHandlerError(int handler_id,
Alex Vakulenko75d6da22015-10-13 10:01:34 -0700156 brillo::Error* error);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800157
158 // Called by Server when an incoming request is dispatched.
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800159 LIBWEBSERV_PRIVATE bool ProcessRequest(const std::string& protocol_handler_id,
160 const std::string& remote_handler_id,
Alex Vakulenko31a63792015-02-03 12:44:57 -0800161 const std::string& request_id,
162 std::unique_ptr<Request> request,
Alex Vakulenko75d6da22015-10-13 10:01:34 -0700163 brillo::ErrorPtr* error);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800164
165 // Called by Response object to finish the request and send response data.
166 LIBWEBSERV_PRIVATE void CompleteRequest(
167 const std::string& request_id,
168 int status_code,
169 const std::multimap<std::string, std::string>& headers,
Alex Vakulenko75d6da22015-10-13 10:01:34 -0700170 brillo::StreamPtr data_stream);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800171
172 // Makes a call to the (remote) web server request handler over D-Bus to
173 // obtain the file content of uploaded file (identified by |file_id|) during
174 // request with |request_id|.
175 LIBWEBSERV_PRIVATE void GetFileData(
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800176 const std::string& request_id,
177 int file_id,
Alex Vakulenko75d6da22015-10-13 10:01:34 -0700178 const base::Callback<void(brillo::StreamPtr)>& success_callback,
179 const base::Callback<void(brillo::Error*)>& error_callback);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800180
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800181 // A helper method to obtain a corresponding protocol handler D-Bus proxy for
182 // outstanding request with ID |request_id|.
183 LIBWEBSERV_PRIVATE ProtocolHandlerProxy* GetRequestProtocolHandlerProxy(
184 const std::string& request_id) const;
185
186 // Protocol Handler name.
187 std::string name_;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800188 // Back reference to the server object.
189 Server* server_{nullptr};
190 // Handler data map. The key is the client-facing request handler ID returned
191 // by AddHandler() when registering the handler.
192 std::map<int, HandlerMapEntry> request_handlers_;
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800193 // The counter to generate new handler IDs.
194 int last_handler_id_{0};
Alex Vakulenko31a63792015-02-03 12:44:57 -0800195 // Map of remote handler IDs (GUID strings) to client-facing request handler
196 // IDs (int) which are returned by AddHandler() and used as a key in
197 // |request_handlers_|.
198 std::map<std::string, int> remote_handler_id_map_;
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800199 // Remote D-Bus proxies for the server protocol handler objects.
200 // There could be multiple protocol handlers with the same name (to make
201 // it possible to server the same requests on different ports, for example).
202 std::map<dbus::ObjectPath, ProtocolHandlerProxy*> proxies_;
203 // A map of request ID to protocol handler ID. Used to locate the appropriate
204 // protocol handler D-Bus proxy for given request.
205 std::map<std::string, std::string> request_id_map_;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800206
207 base::WeakPtrFactory<ProtocolHandler> weak_ptr_factory_{this};
208 DISALLOW_COPY_AND_ASSIGN(ProtocolHandler);
209};
210
211} // namespace libwebserv
212
213#endif // WEBSERVER_LIBWEBSERV_PROTOCOL_HANDLER_H_