1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
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 "vtp_instance.h"
17
18 #include <thread>
19 #include <unistd.h>
20
21 #include "common_inner.h"
22 #include "softbus_adapter_crypto.h"
23 namespace Communication {
24 namespace SoftBus {
25 namespace {
UpdateVtpLogLevel()26 int UpdateVtpLogLevel()
27 {
28 return FILLP_DBG_LVL_DEBUG;
29 }
30 }
31 bool VtpInstance::isDebuged_ = false;
32 std::string VtpInstance::version_ = "VTP_V1.0";
33 bool VtpInstance::isDestroyed_ = true;
34 int VtpInstance::socketStreamCount_ = 0;
35 int VtpInstance::initVtpCount_ = 0;
36 std::mutex VtpInstance::vtpLock_;
37 std::vector<std::string> VtpInstance::packetNameArray_;
38 std::shared_ptr<VtpInstance> VtpInstance::instance_ = nullptr;
39
GetVtpInstance()40 std::shared_ptr<VtpInstance> VtpInstance::GetVtpInstance()
41 {
42 std::shared_ptr<VtpInstance> tmp = instance_;
43 if (tmp == nullptr) {
44 std::lock_guard<std::mutex> guard(vtpLock_);
45 tmp = instance_;
46 if (tmp == nullptr) {
47 tmp = VtpInstance::Create();
48 instance_ = tmp;
49 }
50 }
51 return instance_;
52 }
53
CryptoRand()54 FILLP_UINT32 VtpInstance::CryptoRand()
55 {
56 return SoftBusCryptoRand();
57 }
58
PrintFillpLog(FILLP_UINT32 debugType,FILLP_UINT32 debugLevel,FILLP_UINT32 debugId,FILLP_CHAR * format,...)59 void VtpInstance::PrintFillpLog(FILLP_UINT32 debugType, FILLP_UINT32 debugLevel, FILLP_UINT32 debugId,
60 FILLP_CHAR *format, ...)
61 {
62 /* unused param */
63 static_cast<void>(debugType);
64 static_cast<void>(debugId);
65
66 char debugInfo[DEBUG_BUFFER_LEN];
67 (void)memset_s(debugInfo, sizeof(debugInfo), 0, sizeof(debugInfo));
68
69 va_list vaList;
70 va_start(vaList, format);
71 #pragma clang diagnostic push
72 #pragma clang diagnostic ignored "-Wformat-nonliteral"
73 int result = vsprintf_s(debugInfo, DEBUG_BUFFER_LEN, static_cast<const char *>(format), vaList);
74 #pragma clang diagnostic pop
75 if (result < 0) {
76 TRANS_LOGE(TRANS_STREAM, "**********fillDebugSend Fail!************");
77 va_end(vaList);
78 return;
79 }
80 va_end(vaList);
81
82 switch (debugLevel) {
83 case FILLP_DBG_LVL_INFO:
84 TRANS_LOGI(TRANS_STREAM, "info=%{public}s", debugInfo);
85 break;
86 case FILLP_DBG_LVL_ERROR:
87 TRANS_LOGE(TRANS_STREAM, "errorInfo=%{public}s", debugInfo);
88 break;
89 case FILLP_DBG_LVL_WARNING:
90 TRANS_LOGW(TRANS_STREAM, "warningInfo=%{public}s", debugInfo);
91 break;
92 default:
93 TRANS_LOGD(TRANS_STREAM, "debugInfo=%{public}s", debugInfo);
94 break;
95 }
96 }
97
PreSetFillpCoreParams(void)98 void VtpInstance::PreSetFillpCoreParams(void)
99 {
100 FillpLmCallbackFunc logCallBack;
101 logCallBack.debugCallbackFunc = static_cast<FillpDebugSendFunc>(PrintFillpLog);
102 FILLP_INT32 err = FillpRegLMCallbackFn(&logCallBack);
103 if (err != ERR_OK) {
104 TRANS_LOGE(TRANS_STREAM, "failed to create the log, errno=%{public}d", FtGetErrno());
105 }
106
107 FillpSysLibCallbackFuncStruct adpLibSysFunc;
108 (void)memset_s(&adpLibSysFunc, sizeof(adpLibSysFunc), 0, sizeof(adpLibSysFunc));
109 adpLibSysFunc.sysLibBasicFunc.cryptoRand = CryptoRand;
110 err = FillpApiRegLibSysFunc(&adpLibSysFunc, nullptr);
111 if (err != FILLP_SUCCESS) {
112 TRANS_LOGE(TRANS_STREAM,
113 "failed to register fillp callback function, errno=%{public}d", FtGetErrno());
114 }
115
116 FillpApiSetDebugLogLevel(UpdateVtpLogLevel());
117
118 FILLP_UINT16 maxSocketNums = MAX_DEFAULT_SOCKET_NUM;
119 err = FtConfigSet(FT_CONF_MAX_SOCK_NUM, &maxSocketNums, nullptr);
120 if (err != ERR_OK) {
121 TRANS_LOGE(TRANS_STREAM,
122 "failed to set MAX_SOCKET_NUM config, ret=%{public}d", static_cast<int>(err));
123 }
124
125 FILLP_UINT16 maxConnectionNums = MAX_DEFAULT_SOCKET_NUM; // keep same with the nums of socket.
126 err = FtConfigSet(FT_CONF_MAX_CONNECTION_NUM, &maxConnectionNums, nullptr);
127 if (err != ERR_OK) {
128 TRANS_LOGE(TRANS_STREAM,
129 "failed to set MAX_CONNECTION_NUM config, ret=%{public}d", static_cast<int>(err));
130 }
131
132 FILLP_INT32 keepAlive = FILLP_KEEP_ALIVE_TIME;
133 FILLP_INT confSock = FILLP_CONFIG_ALL_SOCKET;
134 err = FtConfigSet(FT_CONF_TIMER_KEEP_ALIVE, &keepAlive, &confSock);
135 if (err != ERR_OK) {
136 TRANS_LOGE(TRANS_STREAM, "failed to set KA config, ret=%{public}d", static_cast<int>(err));
137 }
138 }
139
InitVtp(const std::string & pkgName)140 bool VtpInstance::InitVtp(const std::string &pkgName)
141 {
142 std::lock_guard<std::mutex> guard(vtpLock_);
143
144 if (!isDestroyed_) {
145 if (std::find(packetNameArray_.begin(), packetNameArray_.end(), pkgName) == packetNameArray_.end()) {
146 packetNameArray_.push_back(pkgName);
147 TRANS_LOGI(TRANS_STREAM,
148 "vtp instance is already created, so increase to packetNameArray");
149 }
150 initVtpCount_++;
151 TRANS_LOGI(TRANS_STREAM,
152 "vtp instance is already created, return true. pkgName=%{public}s", pkgName.c_str());
153 return true;
154 }
155
156 initVtpCount_++;
157 PreSetFillpCoreParams();
158
159 int err = static_cast<int>(FtInit());
160 if (err != ERR_OK) {
161 TRANS_LOGE(TRANS_STREAM, "failed to init fillp, pkgName=%{public}s, ret=%{public}d", pkgName.c_str(), err);
162 return false;
163 }
164 isDestroyed_ = false;
165 #ifdef FILLP_ENHANCED
166 if (static_cast<int>(FtSetDfxEventCb(NULL, DstreamHiEventCb)) != 0) {
167 TRANS_LOGE(TRANS_STREAM, "FtSetDfxEventCb set failed!");
168 }
169 #endif
170 packetNameArray_.push_back(pkgName);
171 TRANS_LOGI(TRANS_STREAM, "success to init vtp instance. pkgName=%{public}s", pkgName.c_str());
172 return true;
173 }
174
WaitForDestroy(const int & delayTimes)175 void VtpInstance::WaitForDestroy(const int &delayTimes)
176 {
177 sleep(delayTimes);
178 std::lock_guard<std::mutex> guard(vtpLock_);
179 if (!isDestroyed_) {
180 TRANS_LOGI(TRANS_STREAM, "call");
181 FtDestroyNonblock();
182 isDestroyed_ = true;
183 initVtpCount_ = 0;
184 }
185 }
186
DestroyVtp(const std::string & pkgName)187 void VtpInstance::DestroyVtp(const std::string &pkgName)
188 {
189 TRANS_LOGD(TRANS_STREAM, "enter.");
190 std::lock_guard<std::mutex> guard(vtpLock_);
191
192 if (isDestroyed_) {
193 TRANS_LOGE(TRANS_STREAM, "vtp instance is already destroyed");
194 return;
195 }
196
197 initVtpCount_--;
198 if (initVtpCount_ > 0) {
199 return;
200 }
201 for (unsigned long i = 0; i < packetNameArray_.size(); i++) {
202 if (!strcmp(packetNameArray_[i].c_str(), pkgName.c_str())) {
203 packetNameArray_.erase(packetNameArray_.begin() + i);
204 break;
205 }
206 }
207
208 if (!packetNameArray_.empty()) {
209 TRANS_LOGI(TRANS_STREAM, "vtp instance is using by other app");
210 return;
211 }
212
213 if (socketStreamCount_) {
214 // 起线程等待30s,调用FtDestroyNonblock()
215 TRANS_LOGW(TRANS_STREAM, "some socket is not destroyed, wait 30s and destroy vtp.");
216 const std::string threadName = "OS_dstyNonblk";
217 std::thread delay(WaitForDestroy, DESTROY_TIMEOUT_SECOND);
218 pthread_setname_np(delay.native_handle(), threadName.c_str());
219 delay.detach();
220 return;
221 }
222
223 TRANS_LOGD(TRANS_STREAM, "begin to destroy vtp instance");
224 FtDestroy();
225 TRANS_LOGD(TRANS_STREAM, "success to destroy vtp instance");
226 isDestroyed_ = true;
227 initVtpCount_ = 0;
228 }
229
GetVersion()230 std::string VtpInstance::GetVersion()
231 {
232 return version_;
233 }
234
UpdateSocketStreamCount(bool add)235 void VtpInstance::UpdateSocketStreamCount(bool add)
236 {
237 std::lock_guard<std::mutex> guard(vtpLock_);
238
239 if (add) {
240 socketStreamCount_++;
241 return;
242 }
243
244 if (!socketStreamCount_) {
245 TRANS_LOGW(TRANS_STREAM, "SocketStreamCount is already 0.");
246 } else {
247 socketStreamCount_--;
248 }
249
250 if (!socketStreamCount_ && !packetNameArray_.size() && !isDestroyed_) {
251 TRANS_LOGI(TRANS_STREAM, "start destroying vtp instance");
252 FtDestroy();
253 TRANS_LOGI(TRANS_STREAM, "success to destroy vtp instance");
254 isDestroyed_ = true;
255 }
256 }
257 } // namespace SoftBus
258 } // namespace Communication
259