1// 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.
14
15#ifndef WEBSERVER_WEBSERVD_DBUS_PROTOCOL_HANDLER_H_
16#define WEBSERVER_WEBSERVD_DBUS_PROTOCOL_HANDLER_H_
17
18#include <map>
19#include <memory>
20#include <set>
21#include <string>
22#include <tuple>
23#include <vector>
24
25#include <base/macros.h>
26#include <base/memory/weak_ptr.h>
27#include <brillo/dbus/dbus_object.h>
28#include <dbus/bus.h>
29
30#include "libwebserv/dbus-proxies.h"
31#include "dbus_bindings/org.chromium.WebServer.ProtocolHandler.h"
32
33namespace brillo {
34namespace dbus_utils {
35class ExportedObjectManager;
36}  // dbus_utils
37}  // brillo
38
39namespace webservd {
40
41class ProtocolHandler;
42class Request;
43class Server;
44
45// This is a D-Bus interface object for the internal ProtocolHandler class.
46class DBusProtocolHandler final
47    : public org::chromium::WebServer::ProtocolHandlerInterface {
48 public:
49  DBusProtocolHandler(
50      brillo::dbus_utils::ExportedObjectManager* object_manager,
51      const dbus::ObjectPath& object_path,
52      ProtocolHandler* protocol_handler,
53      Server* server);
54  ~DBusProtocolHandler();
55
56  void RegisterAsync(
57      const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb);
58
59  // Returns the instance of D-Bus exported object manager.
60  brillo::dbus_utils::ExportedObjectManager* GetObjectManager() const;
61
62  // Overrides from org::chromium::WebServer::DBusProtocolHandlerInterface.
63  bool AddRequestHandler(
64      brillo::ErrorPtr* error,
65      dbus::Message* message,
66      const std::string& in_url,
67      const std::string& in_method,
68      const std::string& in_service_name,
69      std::string* out_request_handler_id) override;
70
71  bool RemoveRequestHandler(brillo::ErrorPtr* error,
72                            const std::string& in_request_handler_id) override;
73
74  bool GetRequestFileData(brillo::ErrorPtr* error,
75                          const std::string& in_request_id,
76                          int32_t in_file_id,
77                          dbus::FileDescriptor* out_contents) override;
78
79  bool CompleteRequest(
80      brillo::ErrorPtr* error,
81      const std::string& in_request_id,
82      int32_t in_status_code,
83      const std::vector<std::tuple<std::string, std::string>>& in_headers,
84      int64_t in_data_size,
85      dbus::FileDescriptor* out_response_stream) override;
86
87 private:
88  using RequestHandlerProxy = org::chromium::WebServer::RequestHandlerProxy;
89
90  // Information about a request handler D-Bus back-end client.
91  struct DBusServiceData {
92    // D-Bus unique address of the process owning this service.
93    std::string owner;
94    // A D-Bus proxy to the client's request handler object that actually
95    // processes requests registered for this client.
96    std::unique_ptr<RequestHandlerProxy> handler_proxy;
97    // A list of handler IDs registered by this client.
98    std::set<std::string> handler_ids;
99    // Called when the owner of the well known service name associated with this
100    // client changes.  Since clients start up, this is called for the first
101    // time when they die.
102    dbus::Bus::GetServiceOwnerCallback on_client_disconnected_callback;
103  };
104
105  // Looks up a request with |request_id|.
106  // Returns nullptr and sets additional |error| information, if not found.
107  Request* GetRequest(const std::string& request_id, brillo::ErrorPtr* error);
108
109  // Callback invoked when a client owning |service_name| is changed.
110  void OnClientDisconnected(const std::string& service_name,
111                            const std::string& service_owner);
112
113  // D-Bus object adaptor for ProtocolHandler D-Bus object.
114  org::chromium::WebServer::ProtocolHandlerAdaptor dbus_adaptor_{this};
115  std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object_;
116
117  // Reference back to the real ProtocolHandler object.
118  ProtocolHandler* protocol_handler_{nullptr};
119  // Reference back to the Server class.
120  Server* server_{nullptr};
121
122  // Called when the owner of a service name changes.  We're only interested in
123  // transitions to the empty string, indicating that a service name owner has
124  // died.
125  dbus::Bus::GetServiceOwnerCallback on_client_disconnected_callback_;
126
127  // A map that holds information regarding a server back-end client processing
128  // requests on the D-Bus service with the name used in the key of the map.
129  std::map<std::string, DBusServiceData> dbus_service_data_;
130  // Handler ID to service name map.
131  std::map<std::string, std::string> handler_to_service_name_map_;
132
133  base::WeakPtrFactory<DBusProtocolHandler> weak_ptr_factory_{this};
134  DISALLOW_COPY_AND_ASSIGN(DBusProtocolHandler);
135};
136
137}  // namespace webservd
138
139#endif  // WEBSERVER_WEBSERVD_DBUS_PROTOCOL_HANDLER_H_
140