blob: f6543cc936895adc29fd5e55a6bd1370f0e2c6fc [file] [log] [blame]
Alex Vakulenko31a63792015-02-03 12:44:57 -08001// Copyright 2015 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef WEBSERVER_LIBWEBSERV_PROTOCOL_HANDLER_H_
6#define WEBSERVER_LIBWEBSERV_PROTOCOL_HANDLER_H_
7
8#include <map>
9#include <memory>
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080010#include <set>
Alex Vakulenko31a63792015-02-03 12:44:57 -080011#include <string>
12#include <vector>
13
14#include <base/callback_forward.h>
15#include <base/macros.h>
16#include <base/memory/weak_ptr.h>
17#include <chromeos/errors/error.h>
18#include <chromeos/secure_blob.h>
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080019#include <dbus/object_path.h>
Alex Vakulenko31a63792015-02-03 12:44:57 -080020
21#include <libwebserv/export.h>
22#include <libwebserv/request_handler_interface.h>
23
24namespace org {
25namespace chromium {
26namespace WebServer {
27
28class ProtocolHandlerProxy;
29
30} // namespace WebServer
31} // namespace chromium
32} // namespace org
33
34namespace libwebserv {
35
36class Server;
37class Request;
38
39// Wrapper around a protocol handler (e.g. HTTP or HTTPs).
40// ProtocolHandler allows consumers to add request handlers on a given protocol.
41// When the ProtocolHandler is connected, allows users to read port and protocol
42// information.
43class LIBWEBSERV_EXPORT ProtocolHandler final {
44 public:
Alex Vakulenko3d8c9122015-03-13 13:54:00 -070045 ProtocolHandler(const std::string& name, Server* server);
Alex Vakulenko31a63792015-02-03 12:44:57 -080046 ~ProtocolHandler();
47
48 // Returns true if the protocol handler object is connected to the web server
49 // daemon's proxy object and is capable of processing incoming requests.
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080050 bool IsConnected() const { return !proxies_.empty(); }
Alex Vakulenko31a63792015-02-03 12:44:57 -080051
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080052 // Handler's name identifier (as provided in "name" setting of config file).
53 // Standard/default handler names are "http" and "https".
54 std::string GetName() const;
Alex Vakulenko31a63792015-02-03 12:44:57 -080055
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080056 // Returns the ports the handler is bound to. There could be multiple.
57 // If the handler is not connected to the server, this will return an empty
58 // set.
59 std::set<uint16_t> GetPorts() const;
Alex Vakulenko31a63792015-02-03 12:44:57 -080060
61 // Returns the transport protocol that is served by this handler.
62 // Can be either "http" or "https".
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080063 // If the handler is not connected to the server, this will return an empty
64 // set.
65 std::set<std::string> GetProtocols() const;
Alex Vakulenko31a63792015-02-03 12:44:57 -080066
67 // Returns a SHA-256 fingerprint of HTTPS certificate used. Returns an empty
68 // byte buffer if this handler does not serve the HTTPS protocol.
Alex Vakulenko3d2d5632015-03-02 15:58:32 -080069 // If the handler is not connected to the server, this will return an empty
70 // array.
Alex Vakulenko31a63792015-02-03 12:44:57 -080071 chromeos::Blob GetCertificateFingerprint() const;
72
73 // Adds a request handler for given |url|. If the |url| ends with a '/', this
74 // makes the handler respond to any URL beneath this path.
75 // Note that it is not possible to add a specific handler just for the root
76 // path "/". Doing so means "respond to any URL".
77 // |method| is optional request method verb, such as "GET" or "POST".
78 // If |method| is empty, the handler responds to any request verb.
79 // If there are more than one handler for a given request, the most specific
80 // match is chosen. For example, if there are the following handlers provided:
81 // - A["/foo/", ""]
82 // - B["/foo/bar", "GET"]
83 // - C["/foo/bar", ""]
84 // Here is what handlers are called when making certain requests:
85 // - GET("/foo/bar") => B[]
86 // - POST("/foo/bar") => C[]
87 // - PUT("/foo/bar") => C[]
88 // - GET("/foo/baz") => A[]
89 // - GET("/foo") => 404 Not Found
90 // This functions returns a handler ID which can be used later to remove
91 // the handler.
92 //
93 // The handler registration information is stored inside ProtocolHandler and
94 // is used to register the handlers with the web server daemon when it becomes
95 // available. This also happens when the web server goes away and then comes
96 // back (e.g. restarted). So, there is no need to re-register the handlers
97 // once the web server process is restarted.
98 int AddHandler(const std::string& url,
99 const std::string& method,
100 std::unique_ptr<RequestHandlerInterface> handler);
101
102 // Similar to AddHandler() above but the handler is just a callback function.
103 int AddHandlerCallback(
104 const std::string& url,
105 const std::string& method,
106 const base::Callback<RequestHandlerInterface::HandlerSignature>&
107 handler_callback);
108
109 // Removes the handler with the specified |handler_id|.
110 // Returns false if the handler with the given ID is not found.
111 bool RemoveHandler(int handler_id);
112
113 static const char kHttp[];
114 static const char kHttps[];
115
116 private:
117 friend class FileInfo;
118 friend class Server;
119 friend class Response;
120
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800121 using ProtocolHandlerProxy = org::chromium::WebServer::ProtocolHandlerProxy;
122
Alex Vakulenko31a63792015-02-03 12:44:57 -0800123 struct LIBWEBSERV_PRIVATE HandlerMapEntry {
124 std::string url;
125 std::string method;
Alex Vakulenko3d8c9122015-03-13 13:54:00 -0700126 std::map<ProtocolHandlerProxy*, std::string> remote_handler_ids;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800127 std::unique_ptr<RequestHandlerInterface> handler;
128 };
129
130 // Called by the Server class when the D-Bus proxy object gets connected
131 // to the web server daemon.
132
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800133 LIBWEBSERV_PRIVATE void Connect(ProtocolHandlerProxy* proxy);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800134 // Called by the Server class when the D-Bus proxy object gets disconnected
135 // from the web server daemon.
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800136 LIBWEBSERV_PRIVATE void Disconnect(const dbus::ObjectPath& object_path);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800137
138 // Asynchronous callbacks to handle successful or failed request handler
139 // registration over D-Bus.
140 LIBWEBSERV_PRIVATE void AddHandlerSuccess(
Alex Vakulenko3d8c9122015-03-13 13:54:00 -0700141 int handler_id,
142 ProtocolHandlerProxy* proxy,
143 const std::string& remote_handler_id);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800144 LIBWEBSERV_PRIVATE void AddHandlerError(int handler_id,
145 chromeos::Error* error);
146
147 // Called by Server when an incoming request is dispatched.
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800148 LIBWEBSERV_PRIVATE bool ProcessRequest(const std::string& protocol_handler_id,
149 const std::string& remote_handler_id,
Alex Vakulenko31a63792015-02-03 12:44:57 -0800150 const std::string& request_id,
151 std::unique_ptr<Request> request,
152 chromeos::ErrorPtr* error);
153
154 // Called by Response object to finish the request and send response data.
155 LIBWEBSERV_PRIVATE void CompleteRequest(
156 const std::string& request_id,
157 int status_code,
158 const std::multimap<std::string, std::string>& headers,
159 const std::vector<uint8_t>& data);
160
161 // Makes a call to the (remote) web server request handler over D-Bus to
162 // obtain the file content of uploaded file (identified by |file_id|) during
163 // request with |request_id|.
164 LIBWEBSERV_PRIVATE void GetFileData(
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800165 const std::string& request_id,
166 int file_id,
167 const base::Callback<void(const std::vector<uint8_t>&)>& success_callback,
168 const base::Callback<void(chromeos::Error*)>& error_callback);
Alex Vakulenko31a63792015-02-03 12:44:57 -0800169
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800170 // A helper method to obtain a corresponding protocol handler D-Bus proxy for
171 // outstanding request with ID |request_id|.
172 LIBWEBSERV_PRIVATE ProtocolHandlerProxy* GetRequestProtocolHandlerProxy(
173 const std::string& request_id) const;
174
175 // Protocol Handler name.
176 std::string name_;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800177 // Back reference to the server object.
178 Server* server_{nullptr};
179 // Handler data map. The key is the client-facing request handler ID returned
180 // by AddHandler() when registering the handler.
181 std::map<int, HandlerMapEntry> request_handlers_;
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800182 // The counter to generate new handler IDs.
183 int last_handler_id_{0};
Alex Vakulenko31a63792015-02-03 12:44:57 -0800184 // Map of remote handler IDs (GUID strings) to client-facing request handler
185 // IDs (int) which are returned by AddHandler() and used as a key in
186 // |request_handlers_|.
187 std::map<std::string, int> remote_handler_id_map_;
Alex Vakulenko3d2d5632015-03-02 15:58:32 -0800188 // Remote D-Bus proxies for the server protocol handler objects.
189 // There could be multiple protocol handlers with the same name (to make
190 // it possible to server the same requests on different ports, for example).
191 std::map<dbus::ObjectPath, ProtocolHandlerProxy*> proxies_;
192 // A map of request ID to protocol handler ID. Used to locate the appropriate
193 // protocol handler D-Bus proxy for given request.
194 std::map<std::string, std::string> request_id_map_;
Alex Vakulenko31a63792015-02-03 12:44:57 -0800195
196 base::WeakPtrFactory<ProtocolHandler> weak_ptr_factory_{this};
197 DISALLOW_COPY_AND_ASSIGN(ProtocolHandler);
198};
199
200} // namespace libwebserv
201
202#endif // WEBSERVER_LIBWEBSERV_PROTOCOL_HANDLER_H_