blob: 648f0fffaed201ae07d674cc9e093e290d3b5bde [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>
27#include <chromeos/errors/error.h>
28#include <chromeos/secure_blob.h>
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080029#include <dbus/object_path.h>
Alex Vakulenko31a63792015-02-03 12:44:57 -080030
31#include <libwebserv/export.h>
32#include <libwebserv/request_handler_interface.h>
33
34namespace org {
35namespace chromium {
36namespace WebServer {
37
38class ProtocolHandlerProxy;
39
40} // namespace WebServer
41} // namespace chromium
42} // namespace org
43
44namespace libwebserv {
45
46class Server;
47class Request;
48
49// Wrapper around a protocol handler (e.g. HTTP or HTTPs).
50// ProtocolHandler allows consumers to add request handlers on a given protocol.
51// When the ProtocolHandler is connected, allows users to read port and protocol
52// information.
53class LIBWEBSERV_EXPORT ProtocolHandler final {
54 public:
Alex Vakulenko3d8c9122015-03-13 13:54:00 -070055 ProtocolHandler(const std::string& name, Server* server);
Alex Vakulenko31a63792015-02-03 12:44:57 -080056 ~ProtocolHandler();
57
58 // Returns true if the protocol handler object is connected to the web server
59 // daemon's proxy object and is capable of processing incoming requests.
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080060 bool IsConnected() const { return !proxies_.empty(); }
Alex Vakulenko31a63792015-02-03 12:44:57 -080061
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080062 // Handler's name identifier (as provided in "name" setting of config file).
63 // Standard/default handler names are "http" and "https".
64 std::string GetName() const;
Alex Vakulenko31a63792015-02-03 12:44:57 -080065
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080066 // Returns the ports the handler is bound to. There could be multiple.
67 // If the handler is not connected to the server, this will return an empty
68 // set.
69 std::set<uint16_t> GetPorts() const;
Alex Vakulenko31a63792015-02-03 12:44:57 -080070
71 // Returns the transport protocol that is served by this handler.
72 // Can be either "http" or "https".
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080073 // If the handler is not connected to the server, this will return an empty
74 // set.
75 std::set<std::string> GetProtocols() const;
Alex Vakulenko31a63792015-02-03 12:44:57 -080076
77 // Returns a SHA-256 fingerprint of HTTPS certificate used. Returns an empty
78 // byte buffer if this handler does not serve the HTTPS protocol.
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080079 // If the handler is not connected to the server, this will return an empty
80 // array.
Alex Vakulenko31a63792015-02-03 12:44:57 -080081 chromeos::Blob GetCertificateFingerprint() const;
82
83 // Adds a request handler for given |url|. If the |url| ends with a '/', this
84 // makes the handler respond to any URL beneath this path.
85 // Note that it is not possible to add a specific handler just for the root
86 // path "/". Doing so means "respond to any URL".
87 // |method| is optional request method verb, such as "GET" or "POST".
88 // If |method| is empty, the handler responds to any request verb.
89 // If there are more than one handler for a given request, the most specific
90 // match is chosen. For example, if there are the following handlers provided:
91 // - A["/foo/", ""]
92 // - B["/foo/bar", "GET"]
93 // - C["/foo/bar", ""]
94 // Here is what handlers are called when making certain requests:
95 // - GET("/foo/bar") => B[]
96 // - POST("/foo/bar") => C[]
97 // - PUT("/foo/bar") => C[]
98 // - GET("/foo/baz") => A[]
99 // - GET("/foo") => 404 Not Found
100 // This functions returns a handler ID which can be used later to remove
101 // the handler.
102 //
103 // The handler registration information is stored inside ProtocolHandler and
104 // is used to register the handlers with the web server daemon when it becomes
105 // available. This also happens when the web server goes away and then comes
106 // back (e.g. restarted). So, there is no need to re-register the handlers
107 // once the web server process is restarted.
108 int AddHandler(const std::string& url,
109 const std::string& method,
110 std::unique_ptr<RequestHandlerInterface> handler);
111
112 // Similar to AddHandler() above but the handler is just a callback function.
113 int AddHandlerCallback(
114 const std::string& url,
115 const std::string& method,
116 const base::Callback<RequestHandlerInterface::HandlerSignature>&
117 handler_callback);
118
119 // Removes the handler with the specified |handler_id|.
120 // Returns false if the handler with the given ID is not found.
121 bool RemoveHandler(int handler_id);
122
123 static const char kHttp[];
124 static const char kHttps[];
125
126 private:
127 friend class FileInfo;
128 friend class Server;
129 friend class Response;
130
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800131 using ProtocolHandlerProxy = org::chromium::WebServer::ProtocolHandlerProxy;
132
Alex Vakulenko31a63792015-02-03 12:44:57 -0800133 struct LIBWEBSERV_PRIVATE HandlerMapEntry {
134 std::string url;
135 std::string method;
Alex Vakulenko3d8c9122015-03-13 13:54:00 -0700136 std::map<ProtocolHandlerProxy*, std::string> remote_handler_ids;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800137 std::unique_ptr<RequestHandlerInterface> handler;
138 };
139
140 // Called by the Server class when the D-Bus proxy object gets connected
141 // to the web server daemon.
142
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800143 LIBWEBSERV_PRIVATE void Connect(ProtocolHandlerProxy* proxy);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800144 // Called by the Server class when the D-Bus proxy object gets disconnected
145 // from the web server daemon.
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800146 LIBWEBSERV_PRIVATE void Disconnect(const dbus::ObjectPath& object_path);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800147
148 // Asynchronous callbacks to handle successful or failed request handler
149 // registration over D-Bus.
150 LIBWEBSERV_PRIVATE void AddHandlerSuccess(
Alex Vakulenko3d8c9122015-03-13 13:54:00 -0700151 int handler_id,
152 ProtocolHandlerProxy* proxy,
153 const std::string& remote_handler_id);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800154 LIBWEBSERV_PRIVATE void AddHandlerError(int handler_id,
155 chromeos::Error* error);
156
157 // Called by Server when an incoming request is dispatched.
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800158 LIBWEBSERV_PRIVATE bool ProcessRequest(const std::string& protocol_handler_id,
159 const std::string& remote_handler_id,
Alex Vakulenko31a63792015-02-03 12:44:57 -0800160 const std::string& request_id,
161 std::unique_ptr<Request> request,
162 chromeos::ErrorPtr* error);
163
164 // Called by Response object to finish the request and send response data.
165 LIBWEBSERV_PRIVATE void CompleteRequest(
166 const std::string& request_id,
167 int status_code,
168 const std::multimap<std::string, std::string>& headers,
169 const std::vector<uint8_t>& data);
170
171 // Makes a call to the (remote) web server request handler over D-Bus to
172 // obtain the file content of uploaded file (identified by |file_id|) during
173 // request with |request_id|.
174 LIBWEBSERV_PRIVATE void GetFileData(
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800175 const std::string& request_id,
176 int file_id,
177 const base::Callback<void(const std::vector<uint8_t>&)>& success_callback,
178 const base::Callback<void(chromeos::Error*)>& error_callback);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800179
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800180 // A helper method to obtain a corresponding protocol handler D-Bus proxy for
181 // outstanding request with ID |request_id|.
182 LIBWEBSERV_PRIVATE ProtocolHandlerProxy* GetRequestProtocolHandlerProxy(
183 const std::string& request_id) const;
184
185 // Protocol Handler name.
186 std::string name_;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800187 // Back reference to the server object.
188 Server* server_{nullptr};
189 // Handler data map. The key is the client-facing request handler ID returned
190 // by AddHandler() when registering the handler.
191 std::map<int, HandlerMapEntry> request_handlers_;
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800192 // The counter to generate new handler IDs.
193 int last_handler_id_{0};
Alex Vakulenko31a63792015-02-03 12:44:57 -0800194 // Map of remote handler IDs (GUID strings) to client-facing request handler
195 // IDs (int) which are returned by AddHandler() and used as a key in
196 // |request_handlers_|.
197 std::map<std::string, int> remote_handler_id_map_;
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800198 // Remote D-Bus proxies for the server protocol handler objects.
199 // There could be multiple protocol handlers with the same name (to make
200 // it possible to server the same requests on different ports, for example).
201 std::map<dbus::ObjectPath, ProtocolHandlerProxy*> proxies_;
202 // A map of request ID to protocol handler ID. Used to locate the appropriate
203 // protocol handler D-Bus proxy for given request.
204 std::map<std::string, std::string> request_id_map_;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800205
206 base::WeakPtrFactory<ProtocolHandler> weak_ptr_factory_{this};
207 DISALLOW_COPY_AND_ASSIGN(ProtocolHandler);
208};
209
210} // namespace libwebserv
211
212#endif // WEBSERVER_LIBWEBSERV_PROTOCOL_HANDLER_H_