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