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