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 bool isCleared; // true: RemoveInstanceTask OP_CLEAR is called
100 };
101 using HTaskInfo = TaskInformation *;
102
103 #pragma pack(pop)
104
105 #ifdef HDC_HOST
106 struct HostUSBEndpoint {
HostUSBEndpointHostUSBEndpoint107 HostUSBEndpoint(uint32_t epBufSize)
108 {
109 endpoint = 0;
110 sizeEpBuf = epBufSize; // MAX_USBFFS_BULK
111 transfer = libusb_alloc_transfer(0);
112 isShutdown = true;
113 isComplete = true;
114 bulkInOut = false;
115 buf = new (std::nothrow) uint8_t[sizeEpBuf];
116 (void)memset_s(buf, sizeEpBuf, 0, sizeEpBuf);
117 }
~HostUSBEndpointHostUSBEndpoint118 ~HostUSBEndpoint()
119 {
120 libusb_free_transfer(transfer);
121 delete[] buf;
122 }
123 uint8_t endpoint;
124 uint8_t *buf; // MAX_USBFFS_BULK
125 bool isComplete;
126 bool isShutdown;
127 bool bulkInOut; // true is bulkIn
128 uint32_t sizeEpBuf;
129 std::mutex mutexIo;
130 std::mutex mutexCb;
131 condition_variable cv;
132 libusb_transfer *transfer;
133 };
134 #endif
135
136 struct HdcUSB {
137 #ifdef HDC_HOST
138 libusb_context *ctxUSB = nullptr; // child-use, main null
139 libusb_device *device;
140 libusb_device_handle *devHandle;
141 uint16_t retryCount;
142 uint8_t devId;
143 uint8_t busId;
144 uint8_t interfaceNumber;
145 std::string serialNumber;
146 std::string usbMountPoint;
147 HostUSBEndpoint hostBulkIn;
148 HostUSBEndpoint hostBulkOut;
HdcUSBHdcUSB149 HdcUSB() : hostBulkIn(513 * 1024), hostBulkOut(512 * 1024) {} // 513: 512 + 1, 1024: 1KB
150 // 512 * 1024 + 1024 = 513 * 1024, MAX_USBFFS_BULK: 512 * 1024
151
152 #else
153 // usb accessory FunctionFS
154 // USB main thread use, sub-thread disable, sub-thread uses the main thread USB handle
155 int bulkOut; // EP1 device recv
156 int bulkIn; // EP2 device send
157 #endif
158 uint32_t payloadSize;
159 uint16_t wMaxPacketSizeSend;
160 bool resetIO; // if true, must break write and read,default false
161 std::mutex lockDeviceHandle;
162 std::mutex lockSendUsbBlock;
163 };
164 using HUSB = struct HdcUSB *;
165
166 #ifdef HDC_SUPPORT_UART
167 struct HdcUART {
168 #ifdef HDC_HOST
169 std::string serialPort;
170 std::thread readThread;
171 uint16_t retryCount = 0;
172 #endif // HDC_HOST
173
174 #ifdef _WIN32
175 OVERLAPPED ovWrite;
176 OVERLAPPED ovRead;
177 HANDLE devUartHandle = INVALID_HANDLE_VALUE;
178 #else
179 // we also make this for daemon side
180 int devUartHandle = -1;
181 #endif
182 // if we want to cancel io (read thread exit)
183 bool ioCancel = false;
184 uint32_t dispatchedPackageIndex = 0;
185 bool resetIO = false; // if true, must break write and read,default false
186 uint64_t packageIndex = 0;
187 std::atomic_size_t streamSize = 0; // for debug only
188 HdcUART();
189 ~HdcUART();
190 };
191 using HUART = struct HdcUART *;
192 #endif
193 struct HdcSessionStat {
194 // bytes successed send to hSession->dataFd[STREAM_MAIN]
195 std::atomic<uint64_t> dataSendBytes;
196 // bytes successed read from hSession->dataPipe[STREAM_WORK]
197 std::atomic<uint64_t> dataRecvBytes;
198 };
199
200 struct HdcSession {
201 bool serverOrDaemon; // instance of daemon or server
202 bool handshakeOK; // Is an expected peer side
203 bool isDead;
204 bool voteReset;
205 bool isCheck = false;
206 std::string connectKey;
207 uint8_t connType; // ConnType
208 uint32_t sessionId;
209 std::atomic<uint32_t> ref;
210 uint8_t uvHandleRef; // libuv handle ref -- just main thread now
211 uint8_t uvChildRef; // libuv handle ref -- just main thread now
212 bool childCleared;
213 std::map<uint32_t, HTaskInfo> *mapTask;
214 // class ptr
215 void *classInstance; // HdcSessionBase instance, HdcServer or HdcDaemon
216 void *classModule; // Communicate module, TCP or USB instance,HdcDaemonUSB HdcDaemonTCP etc...
217 // io cache
218 int bufSize; // total buffer size
219 int availTailIndex; // buffer available data size
220 uint8_t *ioBuf;
221 // auth
222 std::list<void *> *listKey; // rsa private or publickey list
223 uint8_t authKeyIndex;
224 std::string tokenRSA; // SHA_DIGEST_LENGTH+1==21
225 // child work
226 uv_loop_t childLoop; // run in work thread
227 // pipe0 in main thread(hdc server mainloop), pipe1 in work thread
228 uv_poll_t *pollHandle[2]; // control channel
229 int ctrlFd[2]; // control channel socketpair
230 // data channel(TCP with socket, USB with thread forward)
231 uv_tcp_t dataPipe[2];
232 int dataFd[2]; // data channel socketpair
233 uv_tcp_t hChildWorkTCP; // work channel,separate thread for server/daemon
234 uv_os_sock_t fdChildWorkTCP;
235 // usb handle
236 HUSB hUSB;
237 #ifdef HDC_SUPPORT_UART
238 HUART hUART = nullptr;
239 #endif
240 // tcp handle
241 uv_tcp_t hWorkTCP;
242 uv_thread_t hWorkThread;
243 uv_thread_t hWorkChildThread;
244 std::mutex mapTaskMutex;
245 AuthVerifyType verifyType;
246 std::atomic<bool> isNeedDropData; // host: Whether to discard the USB data after it is read
247 std::atomic<uint64_t> dropBytes;
248 bool isSoftReset; // for daemon, Used to record whether a reset command has been received
249
250 HdcSessionStat stat;
ToDebugStringHdcSession251 std::string ToDebugString()
252 {
253 std::ostringstream oss;
254 oss << "HdcSession [";
255 oss << " serverOrDaemon:" << serverOrDaemon;
256 oss << " sessionId:" << sessionId;
257 oss << " handshakeOK:" << handshakeOK;
258 oss << " connectKey:" << Hdc::MaskString(connectKey);
259 oss << " connType:" << unsigned(connType);
260 oss << " ]";
261 return oss.str();
262 }
263
HdcSessionHdcSession264 HdcSession():serverOrDaemon(false), handshakeOK(false), isDead(false), voteReset(false)
265 {
266 connectKey = "";
267 connType = CONN_USB;
268 sessionId = 0;
269 ref = 0;
270 uvHandleRef = 0;
271 uvChildRef = 0;
272 childCleared = false;
273 mapTask = nullptr;
274 classInstance = nullptr;
275 classModule = nullptr;
276 bufSize = 0;
277 ioBuf = nullptr;
278 availTailIndex = 0;
279 listKey = nullptr;
280 authKeyIndex = 0;
281 tokenRSA = "";
282 hUSB = nullptr;
283 (void)memset_s(pollHandle, sizeof(pollHandle), 0, sizeof(pollHandle));
284 (void)memset_s(ctrlFd, sizeof(ctrlFd), 0, sizeof(ctrlFd));
285 (void)memset_s(dataFd, sizeof(dataFd), 0, sizeof(dataFd));
286 (void)memset_s(&childLoop, sizeof(childLoop), 0, sizeof(childLoop));
287 (void)memset_s(dataPipe, sizeof(dataPipe), 0, sizeof(dataPipe));
288 (void)memset_s(&hChildWorkTCP, sizeof(hChildWorkTCP), 0, sizeof(hChildWorkTCP));
289 (void)memset_s(&fdChildWorkTCP, sizeof(fdChildWorkTCP), 0, sizeof(fdChildWorkTCP));
290 (void)memset_s(&stat, sizeof(stat), 0, sizeof(stat));
291 #ifdef HDC_SUPPORT_UART
292 hUART = nullptr;
293 #endif
294 verifyType = AuthVerifyType::RSA_3072_SHA512;
295 isNeedDropData = true;
296 isSoftReset = false;
297 }
298
~HdcSessionHdcSession299 ~HdcSession()
300 {
301 if (mapTask) {
302 delete mapTask;
303 mapTask = nullptr;
304 }
305 if (listKey) {
306 delete listKey;
307 listKey = nullptr;
308 }
309 }
310 };
311 using HSession = struct HdcSession *;
312
313 enum class RemoteType {
314 REMOTE_NONE = 0,
315 REMOTE_FILE = 1,
316 REMOTE_APP = 2,
317 };
318
319 struct HdcChannel {
320 void *clsChannel; // ptr Class of serverForClient or client
321 uint32_t channelId;
322 std::string connectKey;
323 uv_tcp_t hWorkTCP; // work channel for client, forward channel for server
324 uv_thread_t hWorkThread;
325 uint8_t uvHandleRef = 0; // libuv handle ref -- just main thread now
326 bool handshakeOK;
327 bool isDead;
328 bool serverOrClient; // client's channel/ server's channel
329 bool childCleared;
330 bool interactiveShellMode; // Is shell interactive mode
331 bool keepAlive; // channel will not auto-close by server
332 std::atomic<uint32_t> ref;
333 uint32_t targetSessionId;
334 // child work
335 uv_tcp_t hChildWorkTCP; // work channel for server, no use in client
336 uv_os_sock_t fdChildWorkTCP;
337 // read io cache
338 int bufSize; // total buffer size
339 int availTailIndex; // buffer available data size
340 uint8_t *ioBuf;
341 // std
342 uv_tty_t stdinTty;
343 uv_tty_t stdoutTty;
344 char bufStd[128];
345 bool isCheck = false;
346 std::string key;
347 RemoteType remote = RemoteType::REMOTE_NONE;
348 bool fromClient = false;
349 bool connectLocalDevice = false;
350 bool isStableBuf = false;
351 };
352 using HChannel = struct HdcChannel *;
353
354 struct HdcDaemonInformation {
355 uint8_t connType;
356 uint8_t connStatus;
357 std::string connectKey;
358 std::string usbMountPoint;
359 std::string devName;
360 HSession hSession;
361 std::string version;
362 std::string emgmsg;
363 std::string daemonAuthStatus;
364 };
365 using HDaemonInfo = struct HdcDaemonInformation *;
366
367 struct HdcForwardInformation {
368 std::string taskString;
369 bool forwardDirection; // true for forward, false is reverse;
370 uint32_t sessionId;
371 uint32_t channelId;
372 std::string connectKey;
373 };
374 using HForwardInfo = struct HdcForwardInformation *;
375
376 struct HdcSessionInfo {
377 uint32_t sessionId = 0;
378 HSession hSession = nullptr;
379
380 // class ptr
381 void *classInstance = nullptr; // HdcSessionBase instance, HdcServer or HdcDaemon
382 void *classModule = nullptr; // Communicate module, TCP or USB instance,HdcDaemonUSB HdcDaemonTCP etc...
383 };
384 using HSessionInfo = struct HdcSessionInfo *;
385 }
386 #endif
387