xref: /aosp_15_r20/external/perfetto/src/traced_relay/relay_service.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker  * Copyright (C) 2023 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker  *
4*6dbdd20aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker  *
8*6dbdd20aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker  *
10*6dbdd20aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker  * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker  */
16*6dbdd20aSAndroid Build Coastguard Worker 
17*6dbdd20aSAndroid Build Coastguard Worker #include "src/traced_relay/relay_service.h"
18*6dbdd20aSAndroid Build Coastguard Worker 
19*6dbdd20aSAndroid Build Coastguard Worker #include <functional>
20*6dbdd20aSAndroid Build Coastguard Worker #include <memory>
21*6dbdd20aSAndroid Build Coastguard Worker 
22*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/build_config.h"
23*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
24*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/task_runner.h"
25*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/clock_snapshots.h"
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/file_utils.h"
27*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/hash.h"
28*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_utils.h"
29*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/unix_socket.h"
30*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/utils.h"
31*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/ipc/client.h"
32*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/tracing/core/forward_decls.h"
33*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/ipc/wire_protocol.gen.h"
34*6dbdd20aSAndroid Build Coastguard Worker #include "src/ipc/buffered_frame_deserializer.h"
35*6dbdd20aSAndroid Build Coastguard Worker #include "src/traced_relay/socket_relay_handler.h"
36*6dbdd20aSAndroid Build Coastguard Worker #include "src/tracing/ipc/producer/relay_ipc_client.h"
37*6dbdd20aSAndroid Build Coastguard Worker 
38*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
39*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
40*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
41*6dbdd20aSAndroid Build Coastguard Worker #include <fcntl.h>
42*6dbdd20aSAndroid Build Coastguard Worker #include <sys/stat.h>
43*6dbdd20aSAndroid Build Coastguard Worker #include <sys/syscall.h>
44*6dbdd20aSAndroid Build Coastguard Worker #include <sys/utsname.h>
45*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h>
46*6dbdd20aSAndroid Build Coastguard Worker #endif
47*6dbdd20aSAndroid Build Coastguard Worker 
48*6dbdd20aSAndroid Build Coastguard Worker using ::perfetto::protos::gen::IPCFrame;
49*6dbdd20aSAndroid Build Coastguard Worker 
50*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
51*6dbdd20aSAndroid Build Coastguard Worker namespace {
52*6dbdd20aSAndroid Build Coastguard Worker 
GenerateSetPeerIdentityRequest(int32_t pid,int32_t uid,const std::string & machine_id_hint)53*6dbdd20aSAndroid Build Coastguard Worker std::string GenerateSetPeerIdentityRequest(int32_t pid,
54*6dbdd20aSAndroid Build Coastguard Worker                                            int32_t uid,
55*6dbdd20aSAndroid Build Coastguard Worker                                            const std::string& machine_id_hint) {
56*6dbdd20aSAndroid Build Coastguard Worker   IPCFrame ipc_frame;
57*6dbdd20aSAndroid Build Coastguard Worker   ipc_frame.set_request_id(0);
58*6dbdd20aSAndroid Build Coastguard Worker 
59*6dbdd20aSAndroid Build Coastguard Worker   auto* set_peer_identity = ipc_frame.mutable_set_peer_identity();
60*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
61*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
62*6dbdd20aSAndroid Build Coastguard Worker   set_peer_identity->set_pid(pid);
63*6dbdd20aSAndroid Build Coastguard Worker #else
64*6dbdd20aSAndroid Build Coastguard Worker   base::ignore_result(pid);
65*6dbdd20aSAndroid Build Coastguard Worker #endif
66*6dbdd20aSAndroid Build Coastguard Worker   set_peer_identity->set_uid(uid);
67*6dbdd20aSAndroid Build Coastguard Worker   set_peer_identity->set_machine_id_hint(machine_id_hint);
68*6dbdd20aSAndroid Build Coastguard Worker 
69*6dbdd20aSAndroid Build Coastguard Worker   return ipc::BufferedFrameDeserializer::Serialize(ipc_frame);
70*6dbdd20aSAndroid Build Coastguard Worker }
71*6dbdd20aSAndroid Build Coastguard Worker 
72*6dbdd20aSAndroid Build Coastguard Worker }  // Anonymous namespace.
73*6dbdd20aSAndroid Build Coastguard Worker 
74*6dbdd20aSAndroid Build Coastguard Worker RelayClient::~RelayClient() = default;
RelayClient(const std::string & client_sock_name,const std::string & machine_id_hint,base::TaskRunner * task_runner,OnErrorCallback on_error_callback)75*6dbdd20aSAndroid Build Coastguard Worker RelayClient::RelayClient(const std::string& client_sock_name,
76*6dbdd20aSAndroid Build Coastguard Worker                          const std::string& machine_id_hint,
77*6dbdd20aSAndroid Build Coastguard Worker                          base::TaskRunner* task_runner,
78*6dbdd20aSAndroid Build Coastguard Worker                          OnErrorCallback on_error_callback)
79*6dbdd20aSAndroid Build Coastguard Worker     : task_runner_(task_runner),
80*6dbdd20aSAndroid Build Coastguard Worker       on_error_callback_(on_error_callback),
81*6dbdd20aSAndroid Build Coastguard Worker       client_sock_name_(client_sock_name),
82*6dbdd20aSAndroid Build Coastguard Worker       machine_id_hint_(machine_id_hint) {
83*6dbdd20aSAndroid Build Coastguard Worker   Connect();
84*6dbdd20aSAndroid Build Coastguard Worker }
85*6dbdd20aSAndroid Build Coastguard Worker 
Connect()86*6dbdd20aSAndroid Build Coastguard Worker void RelayClient::Connect() {
87*6dbdd20aSAndroid Build Coastguard Worker   auto sock_family = base::GetSockFamily(client_sock_name_.c_str());
88*6dbdd20aSAndroid Build Coastguard Worker   client_sock_ =
89*6dbdd20aSAndroid Build Coastguard Worker       base::UnixSocket::Connect(client_sock_name_, this, task_runner_,
90*6dbdd20aSAndroid Build Coastguard Worker                                 sock_family, base::SockType::kStream);
91*6dbdd20aSAndroid Build Coastguard Worker }
92*6dbdd20aSAndroid Build Coastguard Worker 
NotifyError()93*6dbdd20aSAndroid Build Coastguard Worker void RelayClient::NotifyError() {
94*6dbdd20aSAndroid Build Coastguard Worker   if (!on_error_callback_)
95*6dbdd20aSAndroid Build Coastguard Worker     return;
96*6dbdd20aSAndroid Build Coastguard Worker 
97*6dbdd20aSAndroid Build Coastguard Worker   // Can only notify once.
98*6dbdd20aSAndroid Build Coastguard Worker   on_error_callback_();
99*6dbdd20aSAndroid Build Coastguard Worker   on_error_callback_ = nullptr;
100*6dbdd20aSAndroid Build Coastguard Worker }
101*6dbdd20aSAndroid Build Coastguard Worker 
OnConnect(base::UnixSocket * self,bool connected)102*6dbdd20aSAndroid Build Coastguard Worker void RelayClient::OnConnect(base::UnixSocket* self, bool connected) {
103*6dbdd20aSAndroid Build Coastguard Worker   if (!connected) {
104*6dbdd20aSAndroid Build Coastguard Worker     return NotifyError();
105*6dbdd20aSAndroid Build Coastguard Worker   }
106*6dbdd20aSAndroid Build Coastguard Worker 
107*6dbdd20aSAndroid Build Coastguard Worker   // The RelayClient needs to send its peer identity to the host.
108*6dbdd20aSAndroid Build Coastguard Worker   auto req = GenerateSetPeerIdentityRequest(
109*6dbdd20aSAndroid Build Coastguard Worker       getpid(), static_cast<int32_t>(geteuid()), machine_id_hint_);
110*6dbdd20aSAndroid Build Coastguard Worker   if (!self->SendStr(req)) {
111*6dbdd20aSAndroid Build Coastguard Worker     return NotifyError();
112*6dbdd20aSAndroid Build Coastguard Worker   }
113*6dbdd20aSAndroid Build Coastguard Worker 
114*6dbdd20aSAndroid Build Coastguard Worker   // Create the IPC client with a connected socket.
115*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(self == client_sock_.get());
116*6dbdd20aSAndroid Build Coastguard Worker   auto sock_fd = client_sock_->ReleaseSocket().ReleaseFd();
117*6dbdd20aSAndroid Build Coastguard Worker   client_sock_ = nullptr;
118*6dbdd20aSAndroid Build Coastguard Worker   relay_ipc_client_ = std::make_unique<RelayIPCClient>(
119*6dbdd20aSAndroid Build Coastguard Worker       ipc::Client::ConnArgs(std::move(sock_fd)),
120*6dbdd20aSAndroid Build Coastguard Worker       weak_factory_for_ipc_client.GetWeakPtr(), task_runner_);
121*6dbdd20aSAndroid Build Coastguard Worker }
122*6dbdd20aSAndroid Build Coastguard Worker 
OnServiceConnected()123*6dbdd20aSAndroid Build Coastguard Worker void RelayClient::OnServiceConnected() {
124*6dbdd20aSAndroid Build Coastguard Worker   phase_ = Phase::PING;
125*6dbdd20aSAndroid Build Coastguard Worker   SendSyncClockRequest();
126*6dbdd20aSAndroid Build Coastguard Worker }
127*6dbdd20aSAndroid Build Coastguard Worker 
OnServiceDisconnected()128*6dbdd20aSAndroid Build Coastguard Worker void RelayClient::OnServiceDisconnected() {
129*6dbdd20aSAndroid Build Coastguard Worker   NotifyError();
130*6dbdd20aSAndroid Build Coastguard Worker }
131*6dbdd20aSAndroid Build Coastguard Worker 
SendSyncClockRequest()132*6dbdd20aSAndroid Build Coastguard Worker void RelayClient::SendSyncClockRequest() {
133*6dbdd20aSAndroid Build Coastguard Worker   protos::gen::SyncClockRequest request;
134*6dbdd20aSAndroid Build Coastguard Worker   switch (phase_) {
135*6dbdd20aSAndroid Build Coastguard Worker     case Phase::CONNECTING:
136*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DFATAL("Should be unreachable.");
137*6dbdd20aSAndroid Build Coastguard Worker       return;
138*6dbdd20aSAndroid Build Coastguard Worker     case Phase::PING:
139*6dbdd20aSAndroid Build Coastguard Worker       request.set_phase(SyncClockRequest::PING);
140*6dbdd20aSAndroid Build Coastguard Worker       break;
141*6dbdd20aSAndroid Build Coastguard Worker     case Phase::UPDATE:
142*6dbdd20aSAndroid Build Coastguard Worker       request.set_phase(SyncClockRequest::UPDATE);
143*6dbdd20aSAndroid Build Coastguard Worker       break;
144*6dbdd20aSAndroid Build Coastguard Worker   }
145*6dbdd20aSAndroid Build Coastguard Worker 
146*6dbdd20aSAndroid Build Coastguard Worker   base::ClockSnapshotVector snapshot_data = base::CaptureClockSnapshots();
147*6dbdd20aSAndroid Build Coastguard Worker   for (auto& clock : snapshot_data) {
148*6dbdd20aSAndroid Build Coastguard Worker     auto* clock_proto = request.add_clocks();
149*6dbdd20aSAndroid Build Coastguard Worker     clock_proto->set_clock_id(clock.clock_id);
150*6dbdd20aSAndroid Build Coastguard Worker     clock_proto->set_timestamp(clock.timestamp);
151*6dbdd20aSAndroid Build Coastguard Worker   }
152*6dbdd20aSAndroid Build Coastguard Worker 
153*6dbdd20aSAndroid Build Coastguard Worker   relay_ipc_client_->SyncClock(request);
154*6dbdd20aSAndroid Build Coastguard Worker }
155*6dbdd20aSAndroid Build Coastguard Worker 
OnSyncClockResponse(const protos::gen::SyncClockResponse &)156*6dbdd20aSAndroid Build Coastguard Worker void RelayClient::OnSyncClockResponse(const protos::gen::SyncClockResponse&) {
157*6dbdd20aSAndroid Build Coastguard Worker   static constexpr uint32_t kSyncClockIntervalMs = 30000;  // 30 Sec.
158*6dbdd20aSAndroid Build Coastguard Worker   switch (phase_) {
159*6dbdd20aSAndroid Build Coastguard Worker     case Phase::CONNECTING:
160*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DFATAL("Should be unreachable.");
161*6dbdd20aSAndroid Build Coastguard Worker       break;
162*6dbdd20aSAndroid Build Coastguard Worker     case Phase::PING:
163*6dbdd20aSAndroid Build Coastguard Worker       phase_ = Phase::UPDATE;
164*6dbdd20aSAndroid Build Coastguard Worker       SendSyncClockRequest();
165*6dbdd20aSAndroid Build Coastguard Worker       break;
166*6dbdd20aSAndroid Build Coastguard Worker     case Phase::UPDATE:
167*6dbdd20aSAndroid Build Coastguard Worker       // The client finished one run of clock sync. Schedule for next sync after
168*6dbdd20aSAndroid Build Coastguard Worker       // 30 sec.
169*6dbdd20aSAndroid Build Coastguard Worker       clock_synced_with_service_for_testing_ = true;
170*6dbdd20aSAndroid Build Coastguard Worker       task_runner_->PostDelayedTask(
171*6dbdd20aSAndroid Build Coastguard Worker           [self = weak_factory_.GetWeakPtr()]() {
172*6dbdd20aSAndroid Build Coastguard Worker             if (!self)
173*6dbdd20aSAndroid Build Coastguard Worker               return;
174*6dbdd20aSAndroid Build Coastguard Worker 
175*6dbdd20aSAndroid Build Coastguard Worker             self->phase_ = Phase::PING;
176*6dbdd20aSAndroid Build Coastguard Worker             self->SendSyncClockRequest();
177*6dbdd20aSAndroid Build Coastguard Worker           },
178*6dbdd20aSAndroid Build Coastguard Worker           kSyncClockIntervalMs);
179*6dbdd20aSAndroid Build Coastguard Worker       break;
180*6dbdd20aSAndroid Build Coastguard Worker   }
181*6dbdd20aSAndroid Build Coastguard Worker }
182*6dbdd20aSAndroid Build Coastguard Worker 
RelayService(base::TaskRunner * task_runner)183*6dbdd20aSAndroid Build Coastguard Worker RelayService::RelayService(base::TaskRunner* task_runner)
184*6dbdd20aSAndroid Build Coastguard Worker     : task_runner_(task_runner), machine_id_hint_(GetMachineIdHint()) {}
185*6dbdd20aSAndroid Build Coastguard Worker 
Start(const char * listening_socket_name,const char * client_socket_name)186*6dbdd20aSAndroid Build Coastguard Worker void RelayService::Start(const char* listening_socket_name,
187*6dbdd20aSAndroid Build Coastguard Worker                          const char* client_socket_name) {
188*6dbdd20aSAndroid Build Coastguard Worker   auto sock_family = base::GetSockFamily(listening_socket_name);
189*6dbdd20aSAndroid Build Coastguard Worker   listening_socket_ =
190*6dbdd20aSAndroid Build Coastguard Worker       base::UnixSocket::Listen(listening_socket_name, this, task_runner_,
191*6dbdd20aSAndroid Build Coastguard Worker                                sock_family, base::SockType::kStream);
192*6dbdd20aSAndroid Build Coastguard Worker   bool producer_socket_listening =
193*6dbdd20aSAndroid Build Coastguard Worker       listening_socket_ && listening_socket_->is_listening();
194*6dbdd20aSAndroid Build Coastguard Worker   if (!producer_socket_listening) {
195*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_FATAL("Failed to listen to socket %s", listening_socket_name);
196*6dbdd20aSAndroid Build Coastguard Worker   }
197*6dbdd20aSAndroid Build Coastguard Worker 
198*6dbdd20aSAndroid Build Coastguard Worker   // Save |client_socket_name| for opening new client connection to remote
199*6dbdd20aSAndroid Build Coastguard Worker   // service when a local producer connects.
200*6dbdd20aSAndroid Build Coastguard Worker   client_socket_name_ = client_socket_name;
201*6dbdd20aSAndroid Build Coastguard Worker 
202*6dbdd20aSAndroid Build Coastguard Worker   ConnectRelayClient();
203*6dbdd20aSAndroid Build Coastguard Worker }
204*6dbdd20aSAndroid Build Coastguard Worker 
Start(base::ScopedSocketHandle server_socket_handle,const char * client_socket_name)205*6dbdd20aSAndroid Build Coastguard Worker void RelayService::Start(base::ScopedSocketHandle server_socket_handle,
206*6dbdd20aSAndroid Build Coastguard Worker                          const char* client_socket_name) {
207*6dbdd20aSAndroid Build Coastguard Worker   // Called when the service is started by Android init, where
208*6dbdd20aSAndroid Build Coastguard Worker   // |server_socket_handle| is a unix socket.
209*6dbdd20aSAndroid Build Coastguard Worker   listening_socket_ = base::UnixSocket::Listen(
210*6dbdd20aSAndroid Build Coastguard Worker       std::move(server_socket_handle), this, task_runner_,
211*6dbdd20aSAndroid Build Coastguard Worker       base::SockFamily::kUnix, base::SockType::kStream);
212*6dbdd20aSAndroid Build Coastguard Worker   bool producer_socket_listening =
213*6dbdd20aSAndroid Build Coastguard Worker       listening_socket_ && listening_socket_->is_listening();
214*6dbdd20aSAndroid Build Coastguard Worker   if (!producer_socket_listening) {
215*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_FATAL("Failed to listen to the server socket");
216*6dbdd20aSAndroid Build Coastguard Worker   }
217*6dbdd20aSAndroid Build Coastguard Worker 
218*6dbdd20aSAndroid Build Coastguard Worker   // Save |client_socket_name| for opening new client connection to remote
219*6dbdd20aSAndroid Build Coastguard Worker   // service when a local producer connects.
220*6dbdd20aSAndroid Build Coastguard Worker   client_socket_name_ = client_socket_name;
221*6dbdd20aSAndroid Build Coastguard Worker 
222*6dbdd20aSAndroid Build Coastguard Worker   ConnectRelayClient();
223*6dbdd20aSAndroid Build Coastguard Worker }
224*6dbdd20aSAndroid Build Coastguard Worker 
OnNewIncomingConnection(base::UnixSocket * listen_socket,std::unique_ptr<base::UnixSocket> server_conn)225*6dbdd20aSAndroid Build Coastguard Worker void RelayService::OnNewIncomingConnection(
226*6dbdd20aSAndroid Build Coastguard Worker     base::UnixSocket* listen_socket,
227*6dbdd20aSAndroid Build Coastguard Worker     std::unique_ptr<base::UnixSocket> server_conn) {
228*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(listen_socket == listening_socket_.get());
229*6dbdd20aSAndroid Build Coastguard Worker 
230*6dbdd20aSAndroid Build Coastguard Worker   // Create a connection to the host to pair with |listen_conn|.
231*6dbdd20aSAndroid Build Coastguard Worker   auto sock_family = base::GetSockFamily(client_socket_name_.c_str());
232*6dbdd20aSAndroid Build Coastguard Worker   auto client_conn =
233*6dbdd20aSAndroid Build Coastguard Worker       base::UnixSocket::Connect(client_socket_name_, this, task_runner_,
234*6dbdd20aSAndroid Build Coastguard Worker                                 sock_family, base::SockType::kStream);
235*6dbdd20aSAndroid Build Coastguard Worker 
236*6dbdd20aSAndroid Build Coastguard Worker   // Pre-queue the SetPeerIdentity request. By enqueueing it into the buffer,
237*6dbdd20aSAndroid Build Coastguard Worker   // this will be sent out as first frame as soon as we connect to the real
238*6dbdd20aSAndroid Build Coastguard Worker   // traced.
239*6dbdd20aSAndroid Build Coastguard Worker   //
240*6dbdd20aSAndroid Build Coastguard Worker   // This code pretends that we received a SetPeerIdentity frame from the
241*6dbdd20aSAndroid Build Coastguard Worker   // connecting producer (while instead we are just forging it). The host traced
242*6dbdd20aSAndroid Build Coastguard Worker   // will only accept only one SetPeerIdentity request pre-queued here.
243*6dbdd20aSAndroid Build Coastguard Worker   int32_t pid = base::kInvalidPid;
244*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
245*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
246*6dbdd20aSAndroid Build Coastguard Worker   pid = server_conn->peer_pid_linux();
247*6dbdd20aSAndroid Build Coastguard Worker #endif
248*6dbdd20aSAndroid Build Coastguard Worker   auto req = GenerateSetPeerIdentityRequest(
249*6dbdd20aSAndroid Build Coastguard Worker       pid, static_cast<int32_t>(server_conn->peer_uid_posix()),
250*6dbdd20aSAndroid Build Coastguard Worker       machine_id_hint_);
251*6dbdd20aSAndroid Build Coastguard Worker   // Buffer the SetPeerIdentity request.
252*6dbdd20aSAndroid Build Coastguard Worker   SocketWithBuffer server, client;
253*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(server.available_bytes() >= req.size());
254*6dbdd20aSAndroid Build Coastguard Worker   memcpy(server.buffer(), req.data(), req.size());
255*6dbdd20aSAndroid Build Coastguard Worker   server.EnqueueData(req.size());
256*6dbdd20aSAndroid Build Coastguard Worker 
257*6dbdd20aSAndroid Build Coastguard Worker   // Shut down all callbacks associated with the socket in preparation for the
258*6dbdd20aSAndroid Build Coastguard Worker   // transfer to |socket_relay_handler_|.
259*6dbdd20aSAndroid Build Coastguard Worker   server.sock = server_conn->ReleaseSocket();
260*6dbdd20aSAndroid Build Coastguard Worker   auto new_socket_pair =
261*6dbdd20aSAndroid Build Coastguard Worker       std::make_unique<SocketPair>(std::move(server), std::move(client));
262*6dbdd20aSAndroid Build Coastguard Worker   pending_connections_.push_back(
263*6dbdd20aSAndroid Build Coastguard Worker       {std::move(new_socket_pair), std::move(client_conn)});
264*6dbdd20aSAndroid Build Coastguard Worker }
265*6dbdd20aSAndroid Build Coastguard Worker 
OnConnect(base::UnixSocket * self,bool connected)266*6dbdd20aSAndroid Build Coastguard Worker void RelayService::OnConnect(base::UnixSocket* self, bool connected) {
267*6dbdd20aSAndroid Build Coastguard Worker   // This only happens when the client connection is connected or has failed.
268*6dbdd20aSAndroid Build Coastguard Worker   auto it =
269*6dbdd20aSAndroid Build Coastguard Worker       std::find_if(pending_connections_.begin(), pending_connections_.end(),
270*6dbdd20aSAndroid Build Coastguard Worker                    [&](const PendingConnection& pending_conn) {
271*6dbdd20aSAndroid Build Coastguard Worker                      return pending_conn.connecting_client_conn.get() == self;
272*6dbdd20aSAndroid Build Coastguard Worker                    });
273*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(it != pending_connections_.end());
274*6dbdd20aSAndroid Build Coastguard Worker   // Need to remove the element in |pending_connections_| regardless of
275*6dbdd20aSAndroid Build Coastguard Worker   // |connected|.
276*6dbdd20aSAndroid Build Coastguard Worker   auto remover = base::OnScopeExit([&]() { pending_connections_.erase(it); });
277*6dbdd20aSAndroid Build Coastguard Worker 
278*6dbdd20aSAndroid Build Coastguard Worker   if (!connected)
279*6dbdd20aSAndroid Build Coastguard Worker     return;  // This closes both sockets in PendingConnection.
280*6dbdd20aSAndroid Build Coastguard Worker 
281*6dbdd20aSAndroid Build Coastguard Worker   // Shut down event handlers and pair with a server connection.
282*6dbdd20aSAndroid Build Coastguard Worker   it->socket_pair->second.sock = self->ReleaseSocket();
283*6dbdd20aSAndroid Build Coastguard Worker 
284*6dbdd20aSAndroid Build Coastguard Worker   // Transfer the socket pair to SocketRelayHandler.
285*6dbdd20aSAndroid Build Coastguard Worker   socket_relay_handler_.AddSocketPair(std::move(it->socket_pair));
286*6dbdd20aSAndroid Build Coastguard Worker }
287*6dbdd20aSAndroid Build Coastguard Worker 
OnDisconnect(base::UnixSocket *)288*6dbdd20aSAndroid Build Coastguard Worker void RelayService::OnDisconnect(base::UnixSocket*) {
289*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DFATAL("Should be unreachable.");
290*6dbdd20aSAndroid Build Coastguard Worker }
291*6dbdd20aSAndroid Build Coastguard Worker 
OnDataAvailable(base::UnixSocket *)292*6dbdd20aSAndroid Build Coastguard Worker void RelayService::OnDataAvailable(base::UnixSocket*) {
293*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DFATAL("Should be unreachable.");
294*6dbdd20aSAndroid Build Coastguard Worker }
295*6dbdd20aSAndroid Build Coastguard Worker 
ReconnectRelayClient()296*6dbdd20aSAndroid Build Coastguard Worker void RelayService::ReconnectRelayClient() {
297*6dbdd20aSAndroid Build Coastguard Worker   static constexpr uint32_t kMaxRelayClientRetryDelayMs = 30000;
298*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->PostDelayedTask([this]() { this->ConnectRelayClient(); },
299*6dbdd20aSAndroid Build Coastguard Worker                                 relay_client_retry_delay_ms_);
300*6dbdd20aSAndroid Build Coastguard Worker   relay_client_retry_delay_ms_ =
301*6dbdd20aSAndroid Build Coastguard Worker       relay_client_->ipc_client_connected()
302*6dbdd20aSAndroid Build Coastguard Worker           ? kDefaultRelayClientRetryDelayMs
303*6dbdd20aSAndroid Build Coastguard Worker           : std::min(kMaxRelayClientRetryDelayMs,
304*6dbdd20aSAndroid Build Coastguard Worker                      relay_client_retry_delay_ms_ * 2);
305*6dbdd20aSAndroid Build Coastguard Worker }
306*6dbdd20aSAndroid Build Coastguard Worker 
ConnectRelayClient()307*6dbdd20aSAndroid Build Coastguard Worker void RelayService::ConnectRelayClient() {
308*6dbdd20aSAndroid Build Coastguard Worker   if (relay_client_disabled_for_testing_)
309*6dbdd20aSAndroid Build Coastguard Worker     return;
310*6dbdd20aSAndroid Build Coastguard Worker 
311*6dbdd20aSAndroid Build Coastguard Worker   relay_client_ = std::make_unique<RelayClient>(
312*6dbdd20aSAndroid Build Coastguard Worker       client_socket_name_, machine_id_hint_, task_runner_,
313*6dbdd20aSAndroid Build Coastguard Worker       [this]() { this->ReconnectRelayClient(); });
314*6dbdd20aSAndroid Build Coastguard Worker }
315*6dbdd20aSAndroid Build Coastguard Worker 
GetMachineIdHint(bool use_pseudo_boot_id_for_testing)316*6dbdd20aSAndroid Build Coastguard Worker std::string RelayService::GetMachineIdHint(
317*6dbdd20aSAndroid Build Coastguard Worker     bool use_pseudo_boot_id_for_testing) {
318*6dbdd20aSAndroid Build Coastguard Worker   // Gets kernel boot ID if available.
319*6dbdd20aSAndroid Build Coastguard Worker   std::string boot_id;
320*6dbdd20aSAndroid Build Coastguard Worker   if (!use_pseudo_boot_id_for_testing &&
321*6dbdd20aSAndroid Build Coastguard Worker       base::ReadFile("/proc/sys/kernel/random/boot_id", &boot_id)) {
322*6dbdd20aSAndroid Build Coastguard Worker     return base::StripSuffix(boot_id, "\n");
323*6dbdd20aSAndroid Build Coastguard Worker   }
324*6dbdd20aSAndroid Build Coastguard Worker 
325*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
326*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
327*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
328*6dbdd20aSAndroid Build Coastguard Worker   auto get_pseudo_boot_id = []() -> std::string {
329*6dbdd20aSAndroid Build Coastguard Worker     base::Hasher hasher;
330*6dbdd20aSAndroid Build Coastguard Worker     const char* dev_path = "/dev";
331*6dbdd20aSAndroid Build Coastguard Worker     // Generate a pseudo-unique identifier for the current machine.
332*6dbdd20aSAndroid Build Coastguard Worker     // Source 1: system boot timestamp from the creation time of /dev inode.
333*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
334*6dbdd20aSAndroid Build Coastguard Worker     // Mac or iOS, just use stat(2).
335*6dbdd20aSAndroid Build Coastguard Worker     struct stat stat_buf {};
336*6dbdd20aSAndroid Build Coastguard Worker     int rc = PERFETTO_EINTR(stat(dev_path, &stat_buf));
337*6dbdd20aSAndroid Build Coastguard Worker     if (rc == -1)
338*6dbdd20aSAndroid Build Coastguard Worker       return std::string();
339*6dbdd20aSAndroid Build Coastguard Worker     hasher.Update(reinterpret_cast<const char*>(&stat_buf.st_birthtimespec),
340*6dbdd20aSAndroid Build Coastguard Worker                   sizeof(stat_buf.st_birthtimespec));
341*6dbdd20aSAndroid Build Coastguard Worker #else
342*6dbdd20aSAndroid Build Coastguard Worker     // Android or Linux, use statx(2)
343*6dbdd20aSAndroid Build Coastguard Worker     struct statx stat_buf {};
344*6dbdd20aSAndroid Build Coastguard Worker     auto rc = PERFETTO_EINTR(syscall(__NR_statx, /*dirfd=*/-1, dev_path,
345*6dbdd20aSAndroid Build Coastguard Worker                                      /*flags=*/0, STATX_BTIME, &stat_buf));
346*6dbdd20aSAndroid Build Coastguard Worker     if (rc == -1)
347*6dbdd20aSAndroid Build Coastguard Worker       return std::string();
348*6dbdd20aSAndroid Build Coastguard Worker     hasher.Update(reinterpret_cast<const char*>(&stat_buf.stx_btime),
349*6dbdd20aSAndroid Build Coastguard Worker                   sizeof(stat_buf.stx_btime));
350*6dbdd20aSAndroid Build Coastguard Worker #endif
351*6dbdd20aSAndroid Build Coastguard Worker 
352*6dbdd20aSAndroid Build Coastguard Worker     // Source 2: uname(2).
353*6dbdd20aSAndroid Build Coastguard Worker     utsname kernel_info{};
354*6dbdd20aSAndroid Build Coastguard Worker     if (uname(&kernel_info) == -1)
355*6dbdd20aSAndroid Build Coastguard Worker       return std::string();
356*6dbdd20aSAndroid Build Coastguard Worker 
357*6dbdd20aSAndroid Build Coastguard Worker     // Create a non-cryptographic digest of bootup timestamp and everything in
358*6dbdd20aSAndroid Build Coastguard Worker     // utsname.
359*6dbdd20aSAndroid Build Coastguard Worker     hasher.Update(reinterpret_cast<const char*>(&kernel_info),
360*6dbdd20aSAndroid Build Coastguard Worker                   sizeof(kernel_info));
361*6dbdd20aSAndroid Build Coastguard Worker     return base::Uint64ToHexStringNoPrefix(hasher.digest());
362*6dbdd20aSAndroid Build Coastguard Worker   };
363*6dbdd20aSAndroid Build Coastguard Worker 
364*6dbdd20aSAndroid Build Coastguard Worker   auto pseudo_boot_id = get_pseudo_boot_id();
365*6dbdd20aSAndroid Build Coastguard Worker   if (!pseudo_boot_id.empty())
366*6dbdd20aSAndroid Build Coastguard Worker     return pseudo_boot_id;
367*6dbdd20aSAndroid Build Coastguard Worker #endif
368*6dbdd20aSAndroid Build Coastguard Worker 
369*6dbdd20aSAndroid Build Coastguard Worker   // If all above failed, return nothing.
370*6dbdd20aSAndroid Build Coastguard Worker   return std::string();
371*6dbdd20aSAndroid Build Coastguard Worker }
372*6dbdd20aSAndroid Build Coastguard Worker 
373*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto
374