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