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