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 #ifndef DEFINE_PLUS_H
16 #define DEFINE_PLUS_H
17
18 #include <sstream>
19 #include <thread>
20 #ifdef HDC_TRACE
21 #include "hitrace_meter.h"
22 #endif
23 #include "define_enum.h"
24 #include "uv_status.h"
25 #include "heartbeat.h"
26 #include "securec.h"
27 #ifdef HDC_HOST
28 #include <libusb.h>
29 #endif
30 #include <list>
31
32 namespace Hdc {
33
MaskString(const string & str)34 static string MaskString(const string &str)
35 {
36 if (str.empty()) {
37 return str;
38 }
39 size_t len = str.length();
40 if (len <= 6) { // 6: 当字符串长度小于等于6时,只保留首尾各一个字符, 掩码的个数为字符的长度
41 return std::string(1, str.front()) + std::string(len, '*') + std::string(1, str.back());
42 } else {
43 // 3, 6: 对于较长的字符串,保留首尾各三个字符,掩码的个数为6
44 return str.substr(0, 3) + std::string(6, '*') + str.substr(len - 3) + "(L:" + std::to_string(len) + ")";
45 }
46 }
47
48 #ifndef TEMP_FAILURE_RETRY
49 #define TEMP_FAILURE_RETRY(exp) ({ \
50 __typeof__(exp) _rc; \
51 do { \
52 _rc = (exp); \
53 } while (_rc == -1 && errno == EINTR); \
54 _rc; })
55 #endif
56
57 // hitrace will increase ipc thread to upper hdcd memory
58 // IPC function SetMaxWorkThreadNum can limit thread num, default 16 threads
59 #if defined(HDC_TRACE_TEST) && defined(__OHOS__) // default close, change to open by HDC_TRACE
60 #define StartTracePoint(value) StartTrace(HITRACE_TAG_HDCD, value)
61 #define FinishTracePoint() FinishTrace(HITRACE_TAG_HDCD)
62 #define StartTraceScope(value) HITRACE_METER_NAME(HITRACE_TAG_HDCD, value)
63 #else
64 #define StartTracePoint(value)
65 #define FinishTracePoint()
66 #define StartTraceScope(value)
67 #endif
68
69 // ################################### struct define ###################################
70 #pragma pack(push)
71 #pragma pack(1)
72
73 struct USBHead {
74 uint8_t flag[2];
75 uint8_t option;
76 uint32_t sessionId;
77 uint32_t dataSize;
78 };
79
80 struct AsyncParam {
81 void *context; // context=hsession or hchannel
82 uint32_t sid; // sessionId/channelId
83 void *thisClass; // caller's class ptr
84 uint16_t method;
85 int dataSize;
86 void *data; // put it in the last
87 };
88
89 struct TaskInformation {
90 uint8_t taskType;
91 uint32_t sessionId;
92 uint32_t channelId;
93 bool hasInitial;
94 bool taskStop;
95 bool taskFree;
96 bool serverOrDaemon; // true is server, false is daemon
97 bool masterSlave;
98 uv_loop_t *runLoop;
99 LoopStatus *runLoopStatus;
100 void *taskClass;
101 void *ownerSessionClass;
102 uint32_t closeRetryCount;
103 bool channelTask;
104 void *channelClass;
105 uint8_t debugRelease; // 0:allApp 1:debugApp 2:releaseApp
106 bool isStableBuf;
107 bool isCleared; // true: RemoveInstanceTask OP_CLEAR is called
108 };
109 using HTaskInfo = TaskInformation *;
110
111 #pragma pack(pop)
112
113 #ifdef HDC_HOST
114 struct HostUSBEndpoint {
HostUSBEndpointHostUSBEndpoint115 HostUSBEndpoint(uint32_t epBufSize)
116 {
117 endpoint = 0;
118 sizeEpBuf = epBufSize; // MAX_USBFFS_BULK
119 transfer = libusb_alloc_transfer(0);
120 isShutdown = true;
121 isComplete = true;
122 bulkInOut = false;
123 buf = new (std::nothrow) uint8_t[sizeEpBuf];
124 (void)memset_s(buf, sizeEpBuf, 0, sizeEpBuf);
125 }
~HostUSBEndpointHostUSBEndpoint126 ~HostUSBEndpoint()
127 {
128 libusb_free_transfer(transfer);
129 delete[] buf;
130 }
131 uint8_t endpoint;
132 uint8_t *buf; // MAX_USBFFS_BULK
133 bool isComplete;
134 bool isShutdown;
135 bool bulkInOut; // true is bulkIn
136 uint32_t sizeEpBuf;
137 std::mutex mutexIo;
138 std::mutex mutexCb;
139 std::condition_variable cv;
140 libusb_transfer *transfer;
141 };
142 #endif
143
144 struct HdcUSB {
145 #ifdef HDC_HOST
146 libusb_context *ctxUSB = nullptr; // child-use, main null
147 libusb_device *device = nullptr;
148 libusb_device_handle *devHandle = nullptr;
149 uint16_t retryCount;
150 uint8_t devId;
151 uint8_t busId;
152 uint8_t interfaceNumber;
153 std::string serialNumber;
154 std::string usbMountPoint;
155 HostUSBEndpoint hostBulkIn;
156 HostUSBEndpoint hostBulkOut;
HdcUSBHdcUSB157 HdcUSB() : hostBulkIn(513 * 1024), hostBulkOut(512 * 1024) {} // 513: 512 + 1, 1024: 1KB
158 // 512 * 1024 + 1024 = 513 * 1024, MAX_USBFFS_BULK: 512 * 1024
159
160 #else
161 // usb accessory FunctionFS
162 // USB main thread use, sub-thread disable, sub-thread uses the main thread USB handle
163 int bulkOut; // EP1 device recv
164 bool isBulkOutClosing;
165 int bulkIn; // EP2 device send
166 bool isBulkInClosing;
167 #endif
168 uint32_t payloadSize;
169 uint16_t wMaxPacketSizeSend;
170 bool resetIO; // if true, must break write and read,default false
171 std::mutex lockDeviceHandle;
172 std::mutex lockSendUsbBlock;
173 };
174 using HUSB = struct HdcUSB *;
175
176 #ifdef HDC_SUPPORT_UART
177 struct HdcUART {
178 #ifdef HDC_HOST
179 std::string serialPort;
180 std::thread readThread;
181 uint16_t retryCount = 0;
182 #endif // HDC_HOST
183
184 #ifdef _WIN32
185 OVERLAPPED ovWrite;
186 OVERLAPPED ovRead;
187 HANDLE devUartHandle = INVALID_HANDLE_VALUE;
188 #else
189 // we also make this for daemon side
190 int devUartHandle = -1;
191 #endif
192 // if we want to cancel io (read thread exit)
193 bool ioCancel = false;
194 uint32_t dispatchedPackageIndex = 0;
195 bool resetIO = false; // if true, must break write and read,default false
196 uint64_t packageIndex = 0;
197 std::atomic_size_t streamSize = 0; // for debug only
198 HdcUART();
199 ~HdcUART();
200 };
201 using HUART = struct HdcUART *;
202 #endif
203 struct HdcSessionStat {
204 // bytes successed send to hSession->dataFd[STREAM_MAIN]
205 std::atomic<uint64_t> dataSendBytes;
206 // bytes successed read from hSession->dataPipe[STREAM_WORK]
207 std::atomic<uint64_t> dataRecvBytes;
208 };
209
210 struct HdcSession {
211 bool serverOrDaemon; // instance of daemon or server, true is server, false is daemon
212 bool handshakeOK = false; // Is an expected peer side
213 bool isDead;
214 bool voteReset;
215 bool isCheck = false;
216 std::string connectKey;
217 uint8_t connType; // ConnType
218 uint32_t sessionId;
219 std::atomic<uint32_t> ref;
220 uint8_t uvHandleRef; // libuv handle ref -- just main thread now
221 uint8_t uvChildRef; // libuv handle ref -- just main thread now
222 bool childCleared;
223 std::map<uint32_t, HTaskInfo> *mapTask;
224 std::atomic<uint32_t> clearTaskTimes;
225 // class ptr
226 void *classInstance; // HdcSessionBase instance, HdcServer or HdcDaemon
227 void *classModule; // Communicate module, TCP or USB instance,HdcDaemonUSB HdcDaemonTCP etc...
228 // io cache
229 int bufSize; // total buffer size
230 int availTailIndex; // buffer available data size
231 uint8_t *ioBuf;
232 // auth
233 std::list<void *> *listKey; // rsa private or publickey list
234 uint8_t authKeyIndex;
235 std::string tokenRSA; // SHA_DIGEST_LENGTH+1==21
236 // child work
237 uv_loop_t childLoop; // run in work thread
238 LoopStatus childLoopStatus;
239 // pipe0 in main thread(hdc server mainloop), pipe1 in work thread
240 uv_poll_t *pollHandle[2]; // control channel
241 int ctrlFd[2]; // control channel socketpair
242 // data channel(TCP with socket, USB with thread forward)
243 uv_tcp_t dataPipe[2];
244 int dataFd[2]; // data channel socketpair
245 uv_tcp_t hChildWorkTCP; // work channel,separate thread for server/daemon
246 uv_os_sock_t fdChildWorkTCP;
247 // usb handle
248 HUSB hUSB;
249 bool sslHandshake = false;
250 void *classSSL = nullptr;
251 #ifdef HDC_SUPPORT_UART
252 HUART hUART = nullptr;
253 #endif
254 // tcp handle
255 uv_tcp_t hWorkTCP;
256 uv_thread_t hWorkThread;
257 uv_thread_t hWorkChildThread;
258 std::mutex mapTaskMutex;
259 AuthVerifyType verifyType;
260 bool isSoftReset; // for daemon, Used to record whether a reset command has been received
261 HdcHeartbeat heartbeat;
262 bool supportEncrypt = false;
263 uv_timer_t heartbeatTimer;
264
265 HdcSessionStat stat;
266 #ifdef HDC_HOST
267 bool isRunningOk;
268 std::string faultInfo;
269 uint64_t commandCount = 0;
ToDisplayConnectionStrHdcSession270 std::string ToDisplayConnectionStr()
271 {
272 std::ostringstream oss;
273 oss << "HdcServer [";
274 oss << " sessionId:" << sessionId;
275 oss << " connectKey:" << Hdc::MaskString(connectKey);
276 oss << " connType:" << unsigned(connType);
277 oss << " connect state:" << isRunningOk;
278 oss << " faultInfo:" << faultInfo;
279 oss << " commandCount:" << commandCount;
280 oss << " ]";
281 return oss.str();
282 }
283 #endif
ToDebugStringHdcSession284 std::string ToDebugString()
285 {
286 std::ostringstream oss;
287 oss << "HdcSession [";
288 oss << " serverOrDaemon:" << serverOrDaemon;
289 oss << " sessionId:" << sessionId;
290 oss << " handshakeOK:" << handshakeOK;
291 oss << " connectKey:" << Hdc::MaskString(connectKey);
292 oss << " connType:" << unsigned(connType);
293 oss << " ]";
294 return oss.str();
295 }
296
HdcSessionHdcSession297 HdcSession() : serverOrDaemon(false), handshakeOK(false), isDead(false),
298 voteReset(false), childLoopStatus(&childLoop, "ChildLoop")
299 {
300 connectKey = "";
301 connType = CONN_USB;
302 sessionId = 0;
303 ref = 0;
304 uvHandleRef = 0;
305 uvChildRef = 0;
306 childCleared = false;
307 mapTask = nullptr;
308 clearTaskTimes = 0;
309 classInstance = nullptr;
310 classModule = nullptr;
311 bufSize = 0;
312 ioBuf = nullptr;
313 availTailIndex = 0;
314 listKey = nullptr;
315 authKeyIndex = 0;
316 tokenRSA = "";
317 hUSB = nullptr;
318 (void)memset_s(pollHandle, sizeof(pollHandle), 0, sizeof(pollHandle));
319 (void)memset_s(ctrlFd, sizeof(ctrlFd), 0, sizeof(ctrlFd));
320 (void)memset_s(dataFd, sizeof(dataFd), 0, sizeof(dataFd));
321 (void)memset_s(&childLoop, sizeof(childLoop), 0, sizeof(childLoop));
322 (void)memset_s(dataPipe, sizeof(dataPipe), 0, sizeof(dataPipe));
323 (void)memset_s(&hChildWorkTCP, sizeof(hChildWorkTCP), 0, sizeof(hChildWorkTCP));
324 (void)memset_s(&fdChildWorkTCP, sizeof(fdChildWorkTCP), 0, sizeof(fdChildWorkTCP));
325 (void)memset_s(&stat, sizeof(stat), 0, sizeof(stat));
326 #ifdef HDC_SUPPORT_UART
327 hUART = nullptr;
328 #endif
329 verifyType = AuthVerifyType::RSA_3072_SHA512;
330 isSoftReset = false;
331 #ifdef HDC_HOST
332 isRunningOk = true;
333 faultInfo = "";
334 #endif
335 }
336
~HdcSessionHdcSession337 ~HdcSession()
338 {
339 if (mapTask) {
340 delete mapTask;
341 mapTask = nullptr;
342 }
343 if (listKey) {
344 delete listKey;
345 listKey = nullptr;
346 }
347 }
348 };
349 using HSession = struct HdcSession *;
350
351 enum class RemoteType {
352 REMOTE_NONE = 0,
353 REMOTE_FILE = 1,
354 REMOTE_APP = 2,
355 };
356
357 struct HdcChannel {
358 void *clsChannel; // ptr Class of serverForClient or client
359 uint32_t channelId;
360 std::string connectKey;
361 #ifdef HOST_OHOS
362 bool isUds = false;
363 uv_pipe_t hWorkUds;
364 uv_pipe_t hChildWorkUds;
365 #endif
366 uv_tcp_t hWorkTCP; // work channel for client, forward channel for server
367 uv_thread_t hWorkThread;
368 uint8_t uvHandleRef = 0; // libuv handle ref -- just main thread now
369 bool handshakeOK;
370 bool isDead;
371 bool serverOrClient; // true: server's channel, false: client's channel
372 bool childCleared;
373 bool interactiveShellMode; // Is shell interactive mode
374 bool keepAlive; // channel will not auto-close by server
375 std::atomic<uint32_t> ref;
376 uint32_t targetSessionId;
377 // child work
378 uv_tcp_t hChildWorkTCP; // work channel for server, no use in client
379 uv_os_sock_t fdChildWorkTCP;
380 LoopStatus *loopStatus;
381 // read io cache
382 int bufSize; // total buffer size
383 int availTailIndex; // buffer available data size
384 uint8_t *ioBuf;
385 // std
386 uv_tty_t stdinTty;
387 uv_tty_t stdoutTty;
388 char bufStd[128];
389 bool isCheck = false;
390 std::string key;
391 RemoteType remote = RemoteType::REMOTE_NONE;
392 bool fromClient = false;
393 bool connectLocalDevice = false;
394 bool isStableBuf = false;
395 std::atomic<uint32_t> writeFailedTimes;
396 #ifdef HOST_OHOS
397 bool isSupportedKillServerCmd = false;
398 #endif
399 #ifdef HDC_HOST
400 uint64_t startTime = 0;
401 uint64_t endTime = 0;
402 bool isSuccess = false;
403 std::string faultInfo = "";
404 uint16_t commandFlag = 0;
405 std::string commandParameters = "";
406
ToDisplayChannelStrHdcChannel407 std::string ToDisplayChannelStr()
408 {
409 std::ostringstream oss;
410 oss << "HdcServerForClient [";
411 oss << " channelId:" << channelId;
412 oss << " connectKey:" << Hdc::MaskString(connectKey);
413 oss << " command flag:" << commandFlag;
414 int i = commandParameters.size() - 1;
415 while (i >= 0 && commandParameters[i] == '\0') {
416 commandParameters[i] = ' ';
417 i--;
418 }
419 oss << " command result:" << isSuccess;
420 oss << " command take time:" << (endTime - startTime) << "ms";
421 oss << " faultInfo:" << faultInfo;
422 oss << " ]";
423 return oss.str();
424 }
425 #endif
426 };
427 using HChannel = struct HdcChannel *;
428
429 struct HdcDaemonInformation {
430 uint8_t connType;
431 uint8_t connStatus;
432 std::string connectKey;
433 std::string usbMountPoint;
434 std::string devName;
435 HSession hSession;
436 std::string version;
437 std::string emgmsg;
438 std::string daemonAuthStatus;
439 std::map<std::string, std::string> daemonFeature;
440 bool inited;
441 };
442 using HDaemonInfo = struct HdcDaemonInformation *;
443
444 struct HdcForwardInformation {
445 std::string taskString;
446 bool forwardDirection; // true for forward, false is reverse;
447 uint32_t sessionId;
448 uint32_t channelId;
449 std::string connectKey;
450 };
451 using HForwardInfo = struct HdcForwardInformation *;
452
453 struct HdcSessionInfo {
454 uint32_t sessionId = 0;
455 HSession hSession = nullptr;
456
457 // class ptr
458 void *classInstance = nullptr; // HdcSessionBase instance, HdcServer or HdcDaemon
459 void *classModule = nullptr; // Communicate module, TCP or USB instance,HdcDaemonUSB HdcDaemonTCP etc...
460 };
461 using HSessionInfo = struct HdcSessionInfo *;
462
463 #ifdef HDC_SUPPORT_ENCRYPT_TCP
464 struct HdcSSLInfo {
465 bool isDaemon;
466 uint32_t sessionId;
467 std::string cipher;
468 };
469 using SSLInfoPtr = struct HdcSSLInfo *;
470 #endif
471 }
472 #endif
473