xref: /aosp_15_r20/external/perfetto/src/traced_relay/relay_service.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SRC_TRACED_RELAY_RELAY_SERVICE_H_
18 #define SRC_TRACED_RELAY_RELAY_SERVICE_H_
19 
20 #include <memory>
21 #include <vector>
22 
23 #include "perfetto/ext/base/unix_socket.h"
24 #include "perfetto/ext/tracing/core/tracing_service.h"
25 #include "src/traced_relay/socket_relay_handler.h"
26 #include "src/tracing/ipc/producer/relay_ipc_client.h"
27 
28 namespace perfetto {
29 
30 namespace base {
31 class TaskRunner;
32 }  // namespace base.
33 
34 // RelayClient provides a service that is independent of the relayed producers
35 // and is global in the machine. This class implements time synchronization with
36 // the host machine:
37 // 1. Connects to the host machine using the client socket name (e.g.
38 // vsock://2:10001) to port 10001 of VMADDR_CID_HOST.
39 // 2. After the socket is connected, send the SetPeerIdentity message to let the
40 // tracing service know the identity (machine ID) of this RelayClient.
41 // 3. Then hand over the socket to RelayIPCClient, which is the client
42 // implementation of the RelayPort RPC service.
43 // 4. On any socket error, the RelayClient notifies its user using
44 // OnErrorCallback so the user (class RelayService) may retry the connection.
45 class RelayClient : private base::UnixSocket::EventListener,
46                     private RelayIPCClient::EventListener {
47  public:
48   using OnErrorCallback = std::function<void()>;
49   RelayClient(const std::string& client_sock_name,
50               const std::string& machine_id_hint,
51               base::TaskRunner* task_runner,
52               OnErrorCallback on_destroy_callback);
53   ~RelayClient() override;
54 
ipc_client_connected()55   bool ipc_client_connected() const { return phase_ != Phase::CONNECTING; }
clock_synced_with_service_for_testing()56   bool clock_synced_with_service_for_testing() const {
57     return clock_synced_with_service_for_testing_;
58   }
59 
60  private:
61   // UnixSocket::EventListener implementation for connecting to the client
62   // socket.
OnNewIncomingConnection(base::UnixSocket *,std::unique_ptr<base::UnixSocket>)63   void OnNewIncomingConnection(base::UnixSocket*,
64                                std::unique_ptr<base::UnixSocket>) override {
65     // This class doesn't open a socket in listening mode.
66     PERFETTO_DFATAL("Should be unreachable.");
67   }
68   void OnConnect(base::UnixSocket* self, bool connected) override;
OnDisconnect(base::UnixSocket *)69   void OnDisconnect(base::UnixSocket*) override { NotifyError(); }
OnDataAvailable(base::UnixSocket *)70   void OnDataAvailable(base::UnixSocket*) override {
71     // Should be handled in the IPC client.
72     PERFETTO_DFATAL("Should be unreachable.");
73   }
74 
75   void NotifyError();
76   void Connect();
77   void SendSyncClockRequest();
78 
79   // RelayIPCClient::EventListener implementation.
80   void OnServiceConnected() override;
81   void OnServiceDisconnected() override;
82   void OnSyncClockResponse(const protos::gen::SyncClockResponse& resp) override;
83 
84   enum class Phase : uint32_t { CONNECTING = 1, PING, UPDATE };
85   Phase phase_ = Phase::CONNECTING;
86   bool clock_synced_with_service_for_testing_ = false;
87 
88   base::TaskRunner* task_runner_;
89   OnErrorCallback on_error_callback_;
90 
91   std::string client_sock_name_;
92   // A hint to the host traced for inferring the identifier of this machine.
93   std::string machine_id_hint_;
94   std::unique_ptr<base::UnixSocket> client_sock_;
95   std::unique_ptr<RelayIPCClient> relay_ipc_client_;
96 
97   base::WeakPtrFactory<RelayIPCClient::EventListener>
98       weak_factory_for_ipc_client{this};
99   base::WeakPtrFactory<RelayClient> weak_factory_{this};
100 };
101 
102 // A class for relaying the producer data between the local producers and the
103 // remote tracing service.
104 class RelayService : public base::UnixSocket::EventListener {
105  public:
106   explicit RelayService(base::TaskRunner* task_runner);
107   ~RelayService() override = default;
108 
109   // Starts the service relay that forwards messages between the
110   // |server_socket_name| and |client_socket_name| ports.
111   void Start(const char* server_socket_name, const char* client_socket_name);
112 
113   // Starts the service relay that forwards messages between the
114   // |server_socket_handle| and |client_socket_name| ports. Called when the
115   // service is started by Android init.
116   void Start(base::ScopedSocketHandle server_socket_handle,
117              const char* client_socket_name);
118 
119   static std::string GetMachineIdHint(
120       bool use_pseudo_boot_id_for_testing = false);
121 
SetRelayClientDisabledForTesting(bool disabled)122   void SetRelayClientDisabledForTesting(bool disabled) {
123     relay_client_disabled_for_testing_ = disabled;
124   }
SetMachineIdHintForTesting(std::string machine_id_hint)125   void SetMachineIdHintForTesting(std::string machine_id_hint) {
126     machine_id_hint_ = machine_id_hint;
127   }
relay_client_for_testing()128   RelayClient* relay_client_for_testing() { return relay_client_.get(); }
129 
130  private:
131   struct PendingConnection {
132     // This keeps a connected UnixSocketRaw server socket in its first element.
133     std::unique_ptr<SocketPair> socket_pair;
134     // This keeps the connecting client connection.
135     std::unique_ptr<base::UnixSocket> connecting_client_conn;
136   };
137 
138   RelayService(const RelayService&) = delete;
139   RelayService& operator=(const RelayService&) = delete;
140 
141   // UnixSocket::EventListener implementation.
142   void OnNewIncomingConnection(base::UnixSocket*,
143                                std::unique_ptr<base::UnixSocket>) override;
144   void OnConnect(base::UnixSocket* self, bool connected) override;
145   void OnDisconnect(base::UnixSocket* self) override;
146   void OnDataAvailable(base::UnixSocket* self) override;
147 
148   void ReconnectRelayClient();
149   void ConnectRelayClient();
150 
151   base::TaskRunner* const task_runner_ = nullptr;
152 
153   // A hint to the host traced for inferring the identifier of this machine.
154   std::string machine_id_hint_;
155 
156   std::unique_ptr<base::UnixSocket> listening_socket_;
157   std::string client_socket_name_;
158 
159   // Keeps the socket pairs while waiting for relay connections to be
160   // established.
161   std::vector<PendingConnection> pending_connections_;
162 
163   SocketRelayHandler socket_relay_handler_;
164 
165   std::unique_ptr<RelayClient> relay_client_;
166   // On RelayClient connection error, how long should we wait before retrying.
167   static constexpr uint32_t kDefaultRelayClientRetryDelayMs = 1000;
168   uint32_t relay_client_retry_delay_ms_ = kDefaultRelayClientRetryDelayMs;
169   bool relay_client_disabled_for_testing_ = false;
170 };
171 
172 }  // namespace perfetto
173 
174 #endif  // SRC_TRACED_RELAY_RELAY_SERVICE_H_
175