• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.h"
17 
18 #include <charconv>
19 #include <fstream>
20 #include <unistd.h>
21 #include <sched.h>
22 #include <sys/prctl.h>
23 
24 #include "logging.h"
25 #include "parameters.h"
26 
27 namespace {
28 CachedHandle g_cachedHandle;
29 #define EXPECTANTLY(exp) (__builtin_expect(!!(exp), true))
30 #define UNEXPECTANTLY(exp) (__builtin_expect(!!(exp), false))
31 
32 std::mutex g_cachedMtx;
33 std::mutex g_mtx;
34 std::once_flag g_flag;
35 thread_local std::string g_threadName;
36 const std::string PARAM_KAY = "hiviewdfx.hiprofiler.networkprofiler.target";
37 static std::atomic<bool> g_serverClosing{false};
38 static std::atomic<bool> waitingConnect_{false};
39 static std::vector<OHOS::Developtools::Profiler::NetworkProfiler::CachedData> cachedData_;
40 static std::atomic<bool> enable_{false};
41 static std::shared_ptr<OHOS::Developtools::Profiler::NetworkProfilerSocketClient> socketClent_{nullptr};
42 static std::string processName_;
43 static int32_t pid_{0};
44 static int g_changed{0};
45 } // namespace
46 
47 namespace OHOS::Developtools::Profiler {
48 NetworkProfiler* NetworkProfiler::instance_ = nullptr;
49 
GetInstance()50 NetworkProfiler* NetworkProfiler::GetInstance()
51 {
52     if (instance_ == nullptr) {
53         std::unique_lock<std::mutex> lock(g_mtx);
54         if (instance_ == nullptr) {
55             instance_ = new (std::nothrow) NetworkProfiler();
56         }
57     }
58     return instance_;
59 }
60 
NetworkProfiler()61 NetworkProfiler::NetworkProfiler()
62 {
63     pid_ = getprocpid();
64     processName_ = GetProcessNameByPid(pid_);
65     isDeveloperMode_ = OHOS::system::GetBoolParameter("const.security.developermode.state", false);
66 }
67 
~NetworkProfiler()68 NetworkProfiler::~NetworkProfiler() {}
69 
SetEnableFlag(bool flag)70 void NetworkProfiler::SetEnableFlag(bool flag)
71 {
72     enable_ = flag;
73 }
74 
SetWaitingFlag(bool flag)75 void NetworkProfiler::SetWaitingFlag(bool flag)
76 {
77     waitingConnect_ = flag;
78 }
79 
IsProfilerEnable()80 bool NetworkProfiler::IsProfilerEnable()
81 {
82     if (g_serverClosing) {
83         PROFILER_LOG_ERROR(LOG_CORE, "network profiler server is closing");
84         return false;
85     }
86     CheckNetworkProfilerParam();
87     return enable_ || waitingConnect_;
88 }
89 
CheckNetworkProfilerParam()90 void NetworkProfiler::CheckNetworkProfilerParam()
91 {
92     if (!isDeveloperMode_) {
93         return;
94     }
95     if (UNEXPECTANTLY(g_cachedHandle == nullptr)) {
96         std::unique_lock<std::mutex> lock(g_mtx);
97         if (g_cachedHandle == nullptr) {
98             g_cachedHandle = CachedParameterCreate(PARAM_KAY.c_str(), "");
99         }
100     }
101     int changed = 0;
102     const char *paramValue = CachedParameterGetChanged(g_cachedHandle, &changed);
103     std::call_once(g_flag, [&]() { changed = 1; });
104 
105     if ((UNEXPECTANTLY(changed == 1) || g_changed) && paramValue != nullptr) {
106         if (!enable_ && strlen(paramValue) > 0) {
107             std::vector<std::string> values;
108             SplitParamValue(paramValue, ",", values);
109             for (auto& item : values) {
110                 int32_t pid = static_cast<int32_t>(strtoull(item.c_str(), nullptr, 0));
111                 if (((pid > 0) && (pid == pid_)) || ((pid == 0) && (item == processName_))) {
112                     Enable();
113                     break;
114                 }
115             }
116         }
117     }
118 }
119 
Enable()120 void NetworkProfiler::Enable()
121 {
122     if (enable_) {
123         return;
124     }
125     waitingConnect_ = true;
126     socketClent_ = std::make_shared<NetworkProfilerSocketClient>(pid_, this,
127     reinterpret_cast<void (*)()>(&ServiceCloseCallback));
128     if (!socketClent_->ClientConnectState()) {
129         waitingConnect_ = false;
130         PROFILER_LOG_ERROR(LOG_CORE, "network profiler start failed");
131         return;
132     }
133     PROFILER_LOG_DEBUG(LOG_CORE, "network profiler clent start, pid: %d, processName: %s", pid_, processName_.c_str());
134 }
135 
ServiceCloseCallback()136 void NetworkProfiler::ServiceCloseCallback()
137 {
138     bool expected = false;
139     if (g_serverClosing.compare_exchange_strong(expected, true, std::memory_order_release, std::memory_order_relaxed)) {
140         g_changed = 1;
141         Disable();
142         g_serverClosing = false;
143         g_changed = 0;
144         waitingConnect_ = false;
145         cachedData_.clear();
146     }
147 }
148 
Disable()149 void NetworkProfiler::Disable()
150 {
151     if (!enable_) {
152         return;
153     }
154     PROFILER_LOG_DEBUG(LOG_CORE, "network profiler clent stop, pid: %d, processName: %s", pid_, processName_.c_str());
155     if (socketClent_) {
156         socketClent_->Reset();
157     }
158     enable_ = false;
159 }
160 
SendCachedData()161 void NetworkProfiler::SendCachedData()
162 {
163     std::unique_lock<std::mutex> lock(g_cachedMtx);
164     for (size_t index = 0; index < cachedData_.size(); ++index) {
165         NetworkProfiling(cachedData_[index].cachedType, cachedData_[index].cachedData,
166                          cachedData_[index].cachedDataSize);
167     }
168     cachedData_.clear();
169 }
170 
NetworkProfiling(const uint8_t type,const char * data,size_t dataSize)171 void NetworkProfiler::NetworkProfiling(const uint8_t type, const char* data, size_t dataSize)
172 {
173     if (EXPECTANTLY((!enable_))) {
174         if (waitingConnect_) {
175             std::unique_lock<std::mutex> lock(g_cachedMtx);
176             cachedData_.push_back({type, data, dataSize});
177         }
178         return;
179     }
180     NetworkEvent event;
181     event.type = type;
182     event.tid = getproctid();
183     clock_gettime(clockType_, &event.ts);
184     GetThreadName(event.threadName);
185     if (g_threadName.size() == 0) {
186         GetThreadName(event.threadName);
187     } else {
188         if (sprintf_s(event.threadName, sizeof(event.threadName), "%s", g_threadName.c_str()) < 0) {
189             PROFILER_LOG_DEBUG(LOG_CORE, "sprintf_s event.threadName failed");
190             return;
191         }
192     }
193     NetworkProfilerSendData(reinterpret_cast<const void*>(&event), sizeof(event), data, dataSize);
194 }
195 
NetworkProfilerSendData(const void * src,size_t size,const char * payload,size_t payloadSize)196 void NetworkProfiler::NetworkProfilerSendData(const void* src, size_t size, const char* payload, size_t payloadSize)
197 {
198     if (EXPECTANTLY((!enable_)) || src == nullptr) {
199         return;
200     }
201     std::weak_ptr<NetworkProfilerSocketClient> weakClient = socketClent_;
202     auto holder = weakClient.lock();
203     if (holder == nullptr) {
204         return;
205     }
206 
207     if (!holder->SendNetworkProfilerData(src, size, payload, payloadSize)) {
208         PROFILER_LOG_ERROR(LOG_CORE, "network profiler SendNetworkProfilerData failed");
209     }
210 }
211 
GetThreadName(const char * src)212 void NetworkProfiler::GetThreadName(const char* src)
213 {
214     prctl(PR_GET_NAME, src);
215     std::string tmp(src);
216     g_threadName = tmp;
217 }
218 } // namespace OHOS::Developtools::Profiler
219