1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
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
16 #include "network_profiler_socker_client.h"
17
18 #include "network_profiler_common.h"
19 #include "network_profiler.h"
20
21 namespace {
22 std::atomic<bool> g_disableHook = false;
23
24 } // namespace
25
26 namespace OHOS::Developtools::Profiler {
NetworkProfilerSocketClient(int pid,NetworkProfiler * profiler,void (* disableHookCallback)())27 NetworkProfilerSocketClient::NetworkProfilerSocketClient(int pid, NetworkProfiler* profiler,
28 void (*disableHookCallback)()) : pid_(pid), disableHookCallback_(disableHookCallback), profiler_(profiler)
29 {
30 smbFd_ = 0;
31 eventFd_ = 0;
32 unixSocketClient_ = nullptr;
33 serviceName_ = "NetworkProfilerService";
34 Connect(NETWORK_PROFILER_UNIX_SOCKET_FULL_PATH, disableHookCallback_);
35 }
36
~NetworkProfilerSocketClient()37 NetworkProfilerSocketClient::~NetworkProfilerSocketClient()
38 {
39 if (writer_) {
40 writer_->Flush();
41 }
42 unixSocketClient_ = nullptr;
43 writer_ = nullptr;
44 }
45
Connect(const std::string addrname,void (* disableHookCallback)())46 bool NetworkProfilerSocketClient::Connect(const std::string addrname, void (*disableHookCallback)())
47 {
48 if (unixSocketClient_ != nullptr) {
49 return false;
50 }
51 unixSocketClient_ = std::make_shared<UnixSocketClient>();
52 if (!unixSocketClient_->Connect(addrname, *this, disableHookCallback)) {
53 unixSocketClient_ = nullptr;
54 return false;
55 }
56
57 unixSocketClient_->SendHookConfig(reinterpret_cast<uint8_t *>(&pid_), sizeof(pid_));
58 return true;
59 }
60
ProtocolProc(SocketContext & context,uint32_t pnum,const int8_t * buf,const uint32_t size)61 bool NetworkProfilerSocketClient::ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf,
62 const uint32_t size)
63 {
64 CHECK_TRUE(size == sizeof(NetworkConfig), true, "NetworkProfilerSocketClient config size not match = %u\n", size);
65 NetworkConfig* config = reinterpret_cast<NetworkConfig *>(const_cast<int8_t*>(buf));
66 smbFd_ = context.ReceiveFileDiscriptor();
67 eventFd_ = context.ReceiveFileDiscriptor();
68 PROFILER_LOG_INFO(LOG_CORE, "network profiler client: ProtocolProc: smbFd: %d, eventFd: %d, shmSize: %d",
69 smbFd_, eventFd_, config->shmSize);
70 flushInterval_ = config->flushCount;
71 std::string smbName = "networkProfilerSmb_" + std::to_string(pid_);
72 profiler_->SetClockId(config->clock);
73 writer_ = std::make_shared<NetworkProfilerWriter>(smbName, config->shmSize, smbFd_, eventFd_, config->block);
74 profiler_->SetEnableFlag(true);
75 profiler_->SetWaitingFlag(false);
76 profiler_->SendCachedData();
77 return true;
78 }
79
SendNetworkProfilerData(const void * data,size_t size,const void * payload,size_t payloadSize)80 bool NetworkProfilerSocketClient::SendNetworkProfilerData(const void* data, size_t size,
81 const void* payload, size_t payloadSize)
82 {
83 if (writer_ == nullptr || unixSocketClient_ == nullptr || g_disableHook) {
84 return false;
85 } else if (unixSocketClient_->GetClientState() == CLIENT_STAT_THREAD_EXITED) {
86 DisableHook();
87 return false;
88 }
89
90 bool ret = writer_->WriteWithPayloadTimeout(
91 data,
92 size,
93 payload,
94 payloadSize,
95 std::bind(&NetworkProfilerSocketClient::PeerIsConnected, this));
96 if (!ret) {
97 DisableHook();
98 return false;
99 }
100 writer_->Flush();
101 return true;
102 }
103
Flush()104 void NetworkProfilerSocketClient::Flush()
105 {
106 if (writer_ == nullptr || unixSocketClient_ == nullptr) {
107 return;
108 }
109 writer_->Flush();
110 }
111
DisableHook()112 void NetworkProfilerSocketClient::DisableHook()
113 {
114 bool expected = false;
115 if (g_disableHook.compare_exchange_strong(expected, true, std::memory_order_release, std::memory_order_relaxed)) {
116 HILOG_INFO(LOG_CORE, "%s %p", __func__, disableHookCallback_);
117 if (disableHookCallback_ != nullptr) {
118 disableHookCallback_();
119 }
120 }
121 }
122
PeerIsConnected()123 bool NetworkProfilerSocketClient::PeerIsConnected()
124 {
125 if (unixSocketClient_ == nullptr) {
126 return false;
127 }
128 return !unixSocketClient_->IsConnected();
129 }
130 }