1 /*
2 * Copyright (C) 2021-2024 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 #ifndef OHOS_IPC_DBINDER_BASE_INVOKER_OBJECT_H
17 #define OHOS_IPC_DBINDER_BASE_INVOKER_OBJECT_H
18
19 #include "dbinder_base_invoker_define.h"
20
21 namespace OHOS {
22
TranslateBinderType(flat_binder_object * binderObject,unsigned char * sessionOffset,std::shared_ptr<T> session)23 template<class T> uint32_t DBinderBaseInvoker<T>::TranslateBinderType(
24 flat_binder_object *binderObject, unsigned char *sessionOffset, std::shared_ptr<T> session)
25 {
26 std::shared_ptr<T> sessionOfPeer = CreateServerSessionObject(binderObject->cookie, session);
27 if (sessionOfPeer == nullptr) {
28 ZLOGE(LOG_LABEL, "send an wrong stub object");
29 return 0;
30 }
31 binderObject->hdr.type = BINDER_TYPE_REMOTE_HANDLE;
32 binderObject->cookie = IRemoteObject::IF_PROT_DATABUS;
33 binderObject->binder = 0;
34 return FlattenSession(sessionOffset, sessionOfPeer, SUPPORT_TOKENID_VERSION_NUM);
35 }
36
ClearBinderType(flat_binder_object * binderObject)37 template<class T> void DBinderBaseInvoker<T>::ClearBinderType(flat_binder_object *binderObject)
38 {
39 binderObject->hdr.type = BINDER_TYPE_INVALID_BINDER;
40 binderObject->cookie = IRemoteObject::IF_PROT_ERROR;
41 binderObject->binder = 0;
42 }
43
TranslateHandleType(flat_binder_object * binderObject,unsigned char * sessionOffset,std::shared_ptr<T> session)44 template<class T> uint32_t DBinderBaseInvoker<T>::TranslateHandleType(
45 flat_binder_object *binderObject, unsigned char *sessionOffset, std::shared_ptr<T> session)
46 {
47 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
48 if (current == nullptr) {
49 ZLOGE(LOG_LABEL, "IPCProcessSkeleton is nullptr");
50 return 0;
51 }
52 std::shared_ptr<T> sessionOfPeer = nullptr;
53 if (binderObject->cookie == IRemoteObject::IF_PROT_DATABUS) {
54 sessionOfPeer = QuerySessionOfBinderProxy(binderObject->handle, session);
55 } else if (binderObject->cookie == IRemoteObject::IF_PROT_BINDER) {
56 sessionOfPeer = NewSessionOfBinderProxy(binderObject->handle, session);
57 }
58 if (sessionOfPeer == nullptr) {
59 ZLOGE(LOG_LABEL, "send an wrong dbinder object");
60 return 0;
61 }
62
63 binderObject->hdr.type = BINDER_TYPE_REMOTE_HANDLE;
64 return FlattenSession(sessionOffset, sessionOfPeer, SUPPORT_TOKENID_VERSION_NUM);
65 }
66
ClearHandleType(flat_binder_object * binderObject)67 template<class T> void DBinderBaseInvoker<T>::ClearHandleType(flat_binder_object *binderObject)
68 {
69 binderObject->hdr.type = BINDER_TYPE_INVALID_HANDLE;
70 binderObject->cookie = IRemoteObject::IF_PROT_ERROR;
71 binderObject->binder = 0;
72 }
73
TranslateRemoteHandleType(flat_binder_object * binderObject,unsigned char * sessionOffset,uint32_t binderVersion)74 template<class T> bool DBinderBaseInvoker<T>::TranslateRemoteHandleType(
75 flat_binder_object *binderObject, unsigned char *sessionOffset, uint32_t binderVersion)
76 {
77 std::shared_ptr<T> sessionOfPeer = nullptr;
78 if (binderObject->cookie == IRemoteObject::IF_PROT_DATABUS ||
79 binderObject->cookie == IRemoteObject::IF_PROT_BINDER) {
80 sessionOfPeer = UnFlattenSession(sessionOffset, binderVersion);
81 }
82 if (sessionOfPeer == nullptr) {
83 ZLOGE(LOG_LABEL, "send a wrong dbinder object");
84 return false;
85 }
86
87 // 1. If we find matched session, we need to first take its ownership in case of being erased
88 // during proxy initialization
89 // 2. If translate remote handle type concurrently, we may alloc two new handle, and open session
90 // with the same sessionName and deviceId. thus get the same softbus session. this is OK because if
91 // one proxy is reclaimed, we will close session when it is no longer used
92 uint32_t handle = QueryHandleBySession(sessionOfPeer);
93 if (handle == 0) {
94 handle = MakeRemoteHandle(sessionOfPeer);
95 ZLOGI(LOG_LABEL, "create new handle:%{public}u", handle);
96 if (handle == 0) {
97 ZLOGE(LOG_LABEL, "failed to create new handle");
98 return false;
99 }
100 }
101 // If any error occurred before, hdr.type was still BINDER_TYPE_REMOTE_HANDLE
102 // Thus later UnFlattenObject will enter default case and return null
103 binderObject->hdr.type = BINDER_TYPE_HANDLE;
104 binderObject->handle = handle;
105 return true;
106 }
107
108 template<class T>
IsValidRemoteObjectOffset(unsigned char * dataBuffer,binder_size_t bufferSize,binder_size_t offset,size_t offsetIdx,binder_size_t & preOffset,binder_size_t & preObjectSize)109 bool DBinderBaseInvoker<T>::IsValidRemoteObjectOffset(unsigned char *dataBuffer, binder_size_t bufferSize,
110 binder_size_t offset, size_t offsetIdx, binder_size_t &preOffset, binder_size_t &preObjectSize)
111 {
112 if ((offset >= bufferSize) || (offset + sizeof(binder_object_header) >= bufferSize) ||
113 ((offsetIdx > 0) && ((preOffset >= offset) || (preOffset + preObjectSize > offset)))) {
114 ZLOGE(LOG_LABEL, "invalid objOffset:%{public}llu, preOffset:%{public}llu bufSize:%{public}llu",
115 offset, preOffset, bufferSize);
116 return false;
117 }
118 auto binderObject = reinterpret_cast<flat_binder_object *>(dataBuffer + offset);
119 auto sizeOfObject = IRemoteInvoker::GetRemoteObjectSize(binderObject->hdr.type);
120 if ((sizeOfObject == 0) || (offset + sizeOfObject > bufferSize)) {
121 ZLOGE(LOG_LABEL, "invalid objSize:%{public}zu, offset:%{public}llu type:%{public}u bufSize:%{public}llu",
122 sizeOfObject, offset, binderObject->hdr.type, bufferSize);
123 return false;
124 }
125 preOffset = offset;
126 preObjectSize = sizeOfObject;
127 return true;
128 }
129
130 template<class T>
PrintDBinderTransData(dbinder_transaction_data * transData)131 void DBinderBaseInvoker<T>::PrintDBinderTransData(dbinder_transaction_data *transData)
132 {
133 ZLOGI(LOG_LABEL, "sizeOfSelf:%{public}u, sizeof(dbinder_transaction_data):%{public}zu "
134 "bufSize:%{public}llu offsetsSize:%{public}llu flag:%{public}u",
135 transData->sizeOfSelf, sizeof(dbinder_transaction_data), transData->buffer_size,
136 transData->offsets_size, transData->flags);
137 std::string formatStr;
138 size_t size = (transData->sizeOfSelf - sizeof(dbinder_transaction_data)) / sizeof(int32_t);
139 auto data = reinterpret_cast<const int32_t *>(transData->buffer);
140 size_t idx = 0;
141 while (idx < size) {
142 formatStr += std::to_string(data[idx]) + ',';
143 ++idx;
144 }
145 ZLOGI(LOG_LABEL, "buffer:%{public}s", formatStr.c_str());
146 }
147
148 /* check data parcel contains object, if yes, get its session as payload of socket packet
149 * if translate any object failed, discard this parcel and do NOT send this parcel to remote
150 */
151 template<class T>
IRemoteObjectTranslateWhenSend(std::shared_ptr<dbinder_transaction_data> transData,uint32_t socketId,std::shared_ptr<T> sessionObject)152 bool DBinderBaseInvoker<T>::IRemoteObjectTranslateWhenSend(std::shared_ptr<dbinder_transaction_data> transData,
153 uint32_t socketId, std::shared_ptr<T> sessionObject)
154 {
155 if (transData == nullptr || transData->buffer_size == 0) {
156 ZLOGE(LOG_LABEL, "transData or buffer is nullptr");
157 return false;
158 }
159
160 unsigned char *dataBuffer = transData->buffer;
161 binder_size_t bufferSize = transData->buffer_size;
162 uint32_t totalSize = 0;
163 binder_size_t *binderObjectsOffsets = reinterpret_cast<binder_size_t *>(dataBuffer + transData->offsets);
164 uint32_t offsetOfSession = bufferSize + transData->offsets_size;
165 unsigned char *flatOffset = dataBuffer + offsetOfSession;
166 binder_size_t objCount = transData->offsets_size / sizeof(binder_size_t);
167 binder_size_t preOffset = 0;
168 binder_size_t preObjectSize = 0;
169
170 for (size_t i = 0; i < objCount; i++) {
171 if (!IsValidRemoteObjectOffset(dataBuffer, bufferSize, binderObjectsOffsets[i], i, preOffset, preObjectSize)) {
172 return false;
173 }
174 auto binderObject = reinterpret_cast<flat_binder_object *>(dataBuffer + binderObjectsOffsets[i]);
175 switch (binderObject->hdr.type) {
176 case BINDER_TYPE_BINDER: {
177 uint32_t flatSize = TranslateBinderType(binderObject, flatOffset + totalSize, sessionObject);
178 if (flatSize == 0) {
179 return false;
180 }
181 totalSize += flatSize;
182 continue;
183 }
184 case BINDER_TYPE_HANDLE: {
185 uint32_t flatSize = TranslateHandleType(binderObject, flatOffset + totalSize, sessionObject);
186 if (flatSize == 0) {
187 return false;
188 }
189 totalSize += flatSize;
190 continue;
191 }
192 case BINDER_TYPE_FD: {
193 binderObject->hdr.type = BINDER_TYPE_FDR;
194 binderObject->handle = -1;
195 continue;
196 }
197 default: {
198 ZLOGE(LOG_LABEL, "unexpected type:%{public}u", binderObject->hdr.type);
199 binderObject->hdr.type = BINDER_TYPE_INVALID_TYPE;
200 return false;
201 }
202 }
203 }
204 return true;
205 }
206
207 /* if translate any object failed, should translate next object flush it */
208 template<class T>
IRemoteObjectTranslateWhenRcv(unsigned char * dataBuffer,binder_size_t bufferSize,binder_uintptr_t offsets,binder_size_t offsetsSize,MessageParcel & data,uint32_t socketId)209 bool DBinderBaseInvoker<T>::IRemoteObjectTranslateWhenRcv(unsigned char *dataBuffer, binder_size_t bufferSize,
210 binder_uintptr_t offsets, binder_size_t offsetsSize, MessageParcel &data, uint32_t socketId)
211 {
212 binder_size_t *binderObjectsOffsets = reinterpret_cast<binder_size_t *>(dataBuffer + offsets);
213 uint32_t offsetOfSession = bufferSize + offsetsSize;
214 unsigned char *flatOffset = dataBuffer + offsetOfSession;
215 binder_size_t objCount = offsetsSize / sizeof(binder_size_t);
216 binder_size_t preOffset = 0, preObjectSize = 0;
217
218 for (size_t i = 0; i < objCount; i++) {
219 if (!IsValidRemoteObjectOffset(dataBuffer, bufferSize, binderObjectsOffsets[i], i, preOffset, preObjectSize)) {
220 return false;
221 }
222 auto binderObject = reinterpret_cast<flat_binder_object *>(dataBuffer + binderObjectsOffsets[i]);
223 switch (binderObject->hdr.type) {
224 case BINDER_TYPE_BINDER: {
225 ClearBinderType(binderObject);
226 ZLOGE(LOG_LABEL, "receive an wrong stub object");
227 return false;
228 }
229 case BINDER_TYPE_HANDLE: {
230 ClearHandleType(binderObject);
231 ZLOGE(LOG_LABEL, "receive an wrong proxy object");
232 return false;
233 }
234 case BINDER_TYPE_REMOTE_HANDLE: {
235 if (TranslateRemoteHandleType(binderObject, flatOffset + i * T::GetFlatSessionLen(),
236 SUPPORT_TOKENID_VERSION_NUM) != true) {
237 ZLOGE(LOG_LABEL, "receive an wrong dbiner object");
238 // do nothing, should translate other parcel object, such as fd should set to -1
239 }
240 continue;
241 }
242 case BINDER_TYPE_FD: {
243 binderObject->hdr.type = BINDER_TYPE_FDR;
244 binderObject->handle = -1;
245 return false;
246 }
247 case BINDER_TYPE_FDR: {
248 if (!TranslateRawData(dataBuffer, data, socketId)) {
249 ZLOGE(LOG_LABEL, "fail to translate big raw data");
250 // do nothing
251 }
252 binderObject->handle = -1;
253 continue;
254 }
255 default: {
256 ZLOGE(LOG_LABEL, "unexpected type:%{public}u", binderObject->hdr.type);
257 binderObject->hdr.type = BINDER_TYPE_INVALID_TYPE;
258 return false;
259 }
260 }
261 }
262 return true;
263 }
264
265 template<class T>
IRemoteObjectTranslateWhenRcv(dbinder_transaction_data * transData,MessageParcel & data,uint32_t socketId)266 bool DBinderBaseInvoker<T>::IRemoteObjectTranslateWhenRcv(dbinder_transaction_data *transData, MessageParcel &data,
267 uint32_t socketId)
268 {
269 if (transData == nullptr || transData->buffer_size == 0) {
270 ZLOGE(LOG_LABEL, "transData or buffer is nullptr");
271 return false;
272 }
273
274 return IRemoteObjectTranslateWhenRcv(transData->buffer, transData->buffer_size, transData->offsets,
275 transData->offsets_size, data, socketId);
276 }
277
GetSessionObject(uint32_t handle,uint32_t socketId)278 template <class T> std::shared_ptr<T> DBinderBaseInvoker<T>::GetSessionObject(uint32_t handle, uint32_t socketId)
279 {
280 if (handle != 0) {
281 /* transact case */
282 return QueryServerSessionObject(handle);
283 }
284 /* reply case */
285 return QueryClientSessionObject(socketId);
286 }
287
GetUniqueSeqNumber(int cmd)288 template <class T> uint64_t DBinderBaseInvoker<T>::GetUniqueSeqNumber(int cmd)
289 {
290 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
291 if (current == nullptr) {
292 ZLOGE(LOG_LABEL, "IPCProcessSkeleton is nullptr");
293 return 0;
294 }
295
296 if (cmd == BC_TRANSACTION) {
297 return current->GetSeqNumber();
298 } else if (cmd == BC_REPLY) {
299 /* use sender sequence number */
300 return GetSeqNum();
301 } else {
302 return 0;
303 }
304 }
305
306 template <class T>
ConstructTransData(MessageParcel & data,dbinder_transaction_data & transData,size_t totalSize,uint64_t seqNum,int cmd,__u32 code,__u32 flags)307 void DBinderBaseInvoker<T>::ConstructTransData(MessageParcel &data, dbinder_transaction_data &transData,
308 size_t totalSize, uint64_t seqNum, int cmd, __u32 code, __u32 flags)
309 {
310 transData.sizeOfSelf = totalSize;
311 transData.magic = DBINDER_MAGICWORD;
312 transData.version = SUPPORT_TOKENID_VERSION_NUM;
313 transData.cmd = cmd;
314 transData.code = code;
315 transData.flags = flags;
316 transData.cookie = 0;
317 transData.seqNumber = seqNum;
318 transData.buffer_size = 0;
319 transData.offsets_size = 0;
320 transData.offsets = 0;
321 }
322
323 template <class T>
TranslateRawData(unsigned char * dataBuffer,MessageParcel & data,uint32_t socketId)324 bool DBinderBaseInvoker<T>::TranslateRawData(unsigned char *dataBuffer, MessageParcel &data, uint32_t socketId)
325 {
326 if (socketId == 0) {
327 ZLOGI(LOG_LABEL, "no raw data to translate.");
328 return true;
329 }
330
331 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
332 if (current == nullptr) {
333 ZLOGE(LOG_LABEL, "IPCProcessSkeleton is nullptr");
334 return false;
335 }
336 std::shared_ptr<InvokerRawData> receivedRawData = current->QueryRawData(socketId);
337 if (receivedRawData == nullptr) {
338 ZLOGE(LOG_LABEL, "cannot found rawData according to the socketId:%{public}u", socketId);
339 return false;
340 }
341 std::shared_ptr<char> rawData = receivedRawData->GetData();
342 size_t rawSize = receivedRawData->GetSize();
343 current->DetachRawData(socketId);
344 if (!data.RestoreRawData(rawData, rawSize)) {
345 ZLOGE(LOG_LABEL, "found rawData, but cannot restore them, socketId:%{public}u", socketId);
346 return false;
347 }
348 return true;
349 }
350
351 template <class T>
MoveTransData2Buffer(std::shared_ptr<T> sessionObject,std::shared_ptr<dbinder_transaction_data> transData)352 bool DBinderBaseInvoker<T>::MoveTransData2Buffer(std::shared_ptr<T> sessionObject,
353 std::shared_ptr<dbinder_transaction_data> transData)
354 {
355 std::shared_ptr<BufferObject> sessionBuff = sessionObject->GetSessionBuff();
356 if (sessionBuff == nullptr) {
357 ZLOGE(LOG_LABEL, "get session buffer fail");
358 return false;
359 }
360 if (transData == nullptr) {
361 ZLOGE(LOG_LABEL, "transData is nullptr");
362 return false;
363 }
364 uint32_t sendSize = transData->sizeOfSelf;
365 char *sendBuffer = sessionBuff->GetSendBufferAndLock(sendSize);
366 /* session buffer contain mutex, need release mutex */
367 if (sendBuffer == nullptr) {
368 ZLOGE(LOG_LABEL, "buffer alloc failed in session");
369 return false;
370 }
371
372 sessionBuff->UpdateSendBuffer(sendSize);
373 ssize_t writeCursor = sessionBuff->GetSendBufferWriteCursor();
374 ssize_t readCursor = sessionBuff->GetSendBufferReadCursor();
375 if (writeCursor < 0 || readCursor < 0 || static_cast<uint32_t>(writeCursor) > sessionBuff->GetSendBufferSize() ||
376 sendSize > sessionBuff->GetSendBufferSize() - static_cast<uint32_t>(writeCursor)) {
377 sessionBuff->ReleaseSendBufferLock();
378 ZLOGE(LOG_LABEL, "sender's data is large than idle buffer, writecursor:%{public}zd readcursor:%{public}zd,\
379 sendSize:%{public}u bufferSize:%{public}u",
380 writeCursor, readCursor, sendSize, sessionBuff->GetSendBufferSize());
381 return false;
382 }
383 if (memcpy_s(sendBuffer + writeCursor, sendSize, transData.get(), sendSize)) {
384 sessionBuff->ReleaseSendBufferLock();
385 ZLOGE(LOG_LABEL, "fail to copy from tr to sendBuffer, parcelSize:%{public}u", sendSize);
386 return false;
387 }
388
389 writeCursor += static_cast<ssize_t>(sendSize);
390 sessionBuff->SetSendBufferWriteCursor(writeCursor);
391 sessionBuff->SetSendBufferReadCursor(readCursor);
392 sessionBuff->ReleaseSendBufferLock();
393 return true;
394 }
395
396 template <class T>
HandleReply(uint64_t seqNumber,MessageParcel * reply,std::shared_ptr<ThreadMessageInfo> messageInfo)397 int DBinderBaseInvoker<T>::HandleReply(uint64_t seqNumber, MessageParcel *reply,
398 std::shared_ptr<ThreadMessageInfo> messageInfo)
399 {
400 if (reply == nullptr) {
401 ZLOGE(LOG_LABEL, "no need reply, free the buffer");
402 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_NO_NEED_REPLY, __FUNCTION__);
403 return RPC_BASE_INVOKER_INVALID_REPLY_ERR;
404 }
405 if (messageInfo == nullptr) {
406 ZLOGE(LOG_LABEL, "receive buffer is nullptr");
407 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_RECEIVE_BUFFER_NULL, __FUNCTION__);
408 return RPC_BASE_INVOKER_INVALID_REPLY_ERR;
409 }
410 if (messageInfo->flags & MessageOption::TF_STATUS_CODE) {
411 int32_t err = static_cast<int32_t>(messageInfo->offsetsSize);
412 return err;
413 }
414 if (messageInfo->buffer == nullptr) {
415 ZLOGE(LOG_LABEL, "need reply message, but buffer is nullptr");
416 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_BUFFER_NULL, __FUNCTION__);
417 return RPC_BASE_INVOKER_INVALID_REPLY_ERR;
418 }
419
420 if (!IRemoteObjectTranslateWhenRcv(reinterpret_cast<unsigned char *>(messageInfo->buffer), messageInfo->bufferSize,
421 messageInfo->offsets, messageInfo->offsetsSize, *reply, messageInfo->socketId)) {
422 ZLOGE(LOG_LABEL, "translate object failed, socketId:%{public}u", messageInfo->socketId);
423 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_TRANSLATE_OBJECT_FAIL, __FUNCTION__);
424 return RPC_BASE_INVOKER_INVALID_REPLY_ERR;
425 }
426
427 auto allocator = new (std::nothrow) DBinderRecvAllocator();
428 if (allocator == nullptr) {
429 ZLOGE(LOG_LABEL, "create DBinderRecvAllocator object failed");
430 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_CREATE_RECV_ALLOCATOR_FAIL, __FUNCTION__);
431 return RPC_BASE_INVOKER_INVALID_REPLY_ERR;
432 }
433 if (!reply->SetAllocator(allocator)) {
434 ZLOGE(LOG_LABEL, "SetAllocator failed");
435 DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_SET_ALLOCATOR_FAIL, __FUNCTION__);
436 delete allocator;
437 return RPC_BASE_INVOKER_INVALID_REPLY_ERR;
438 }
439 reply->ParseFrom(reinterpret_cast<uintptr_t>(messageInfo->buffer), messageInfo->bufferSize);
440
441 if (messageInfo->offsetsSize > 0) {
442 reply->InjectOffsets(
443 reinterpret_cast<binder_uintptr_t>(reinterpret_cast<char *>(messageInfo->buffer) + messageInfo->offsets),
444 messageInfo->offsetsSize / sizeof(binder_size_t));
445 }
446 return ERR_NONE;
447 }
448
Dealloc(void * data)449 template <class T> void DBinderBaseInvoker<T>::DBinderSendAllocator::Dealloc(void *data) {}
450
Dealloc(void * data)451 template <class T> void DBinderBaseInvoker<T>::DBinderRecvAllocator::Dealloc(void *data)
452 {
453 delete[](unsigned char *) data;
454 }
455
456 template <class T>
WaitForReply(uint64_t seqNumber,MessageParcel * reply,uint32_t handle,int userWaitTime)457 int DBinderBaseInvoker<T>::WaitForReply(uint64_t seqNumber, MessageParcel *reply, uint32_t handle, int userWaitTime)
458 {
459 /* if reply == nullptr, this is a one way message */
460 if (reply == nullptr) {
461 return NO_ERROR;
462 }
463
464 std::shared_ptr<ThreadMessageInfo> messageInfo = MakeThreadMessageInfo(handle);
465 if (messageInfo == nullptr) {
466 ZLOGE(LOG_LABEL, "make thread message info failed, handle:%{public}u seq:%{public}" PRIu64,
467 handle, seqNumber);
468 return RPC_BASE_INVOKER_WAIT_REPLY_ERR;
469 }
470
471 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
472 if (current == nullptr) {
473 ZLOGE(LOG_LABEL, "IPCProcessSkeleton is nullptr, handle:%{public}u seq:%{public}" PRIu64,
474 handle, seqNumber);
475 return RPC_BASE_INVOKER_WAIT_REPLY_ERR;
476 }
477 /* wait for reply */
478 if (!current->AddSendThreadInWait(seqNumber, messageInfo, userWaitTime)) {
479 current->EraseThreadBySeqNumber(seqNumber);
480 ZLOGE(LOG_LABEL, "sender thread wait reply message time out, "
481 "waitTime:%{public}d handle:%{public}u seq:%{public}" PRIu64, userWaitTime, handle, seqNumber);
482 return RPC_BASE_INVOKER_WAIT_REPLY_ERR;
483 }
484
485 int32_t err = HandleReply(seqNumber, reply, messageInfo);
486 current->EraseThreadBySeqNumber(seqNumber);
487 messageInfo->buffer = nullptr;
488 messageInfo->ready = false;
489 return err;
490 }
491
AddDeathRecipient(int32_t handle,void * cookie)492 template <class T> bool DBinderBaseInvoker<T>::AddDeathRecipient(int32_t handle, void *cookie)
493 {
494 return true;
495 }
496
RemoveDeathRecipient(int32_t handle,void * cookie)497 template <class T> bool DBinderBaseInvoker<T>::RemoveDeathRecipient(int32_t handle, void *cookie)
498 {
499 return true;
500 }
501
StartProcessLoop(int32_t socketId,const char * buffer,uint32_t size)502 template <class T> void DBinderBaseInvoker<T>::StartProcessLoop(int32_t socketId, const char *buffer, uint32_t size)
503 {
504 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
505 if (current == nullptr) {
506 ZLOGE(LOG_LABEL, "IPCProcessSkeleton is nullptr");
507 StartLoopFailSendReply(buffer, size, RPC_BASE_INVOKER_CURRENT_NULL_ERR);
508 return;
509 }
510 std::shared_ptr<ThreadProcessInfo> processInfo = MakeThreadProcessInfo(socketId, buffer, size);
511 if (processInfo == nullptr) {
512 ZLOGE(LOG_LABEL, "processInfo is nullptr");
513 StartLoopFailSendReply(buffer, size, RPC_BASE_INVOKER_MALLOC_ERR);
514 return;
515 }
516 std::thread::id threadId = current->GetIdleDataThread();
517 if (threadId == std::thread::id()) {
518 bool result = CreateProcessThread();
519 if (!result) {
520 int socketThreadNum = current->GetSocketTotalThreadNum();
521 ZLOGE(LOG_LABEL, "create IO thread failed, current socket thread num:%{public}d socketId:%{public}d",
522 socketThreadNum, socketId);
523 /* thread create too much, wait some thread be idle */
524 }
525 do {
526 /* no IO thread in idle state, wait a monent */
527 std::this_thread::sleep_for(std::chrono::milliseconds(1));
528 } while ((threadId = current->GetIdleDataThread()) == std::thread::id());
529 }
530
531 current->AddDataInfoToThread(threadId, processInfo);
532 current->WakeUpDataThread(threadId);
533 return;
534 }
535
MakeThreadMessageInfo(int32_t socketId)536 template <class T> std::shared_ptr<ThreadMessageInfo> DBinderBaseInvoker<T>::MakeThreadMessageInfo(int32_t socketId)
537 {
538 std::shared_ptr<ThreadMessageInfo> messageInfo = std::make_shared<struct ThreadMessageInfo>();
539 if (messageInfo == nullptr) {
540 ZLOGE(LOG_LABEL, "make ThreadMessageInfo fail");
541 return nullptr;
542 }
543
544 messageInfo->buffer = nullptr;
545 messageInfo->offsets = 0;
546 messageInfo->socketId = static_cast<uint32_t>(socketId);
547 messageInfo->ready = false;
548 return messageInfo;
549 }
550
MakeRemoteHandle(std::shared_ptr<T> session)551 template<class T> uint32_t DBinderBaseInvoker<T>::MakeRemoteHandle(std::shared_ptr<T> session)
552 {
553 if (session == nullptr) {
554 ZLOGE(LOG_LABEL, "session is nullptr");
555 return 0;
556 }
557 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
558 if (current == nullptr) {
559 ZLOGE(LOG_LABEL, "IPCProcessSkeleton is nullptr");
560 return 0;
561 }
562
563 if (!UpdateClientSession(session)) {
564 ZLOGE(LOG_LABEL, "open session failed");
565 return 0;
566 }
567 uint32_t handle = current->GetDBinderIdleHandle(session);
568 if (handle == 0) {
569 ZLOGE(LOG_LABEL, "get dbinder handle failed");
570 if (current->QuerySessionByInfo(session->GetServiceName(), session->GetDeviceId()) == nullptr) {
571 session->CloseDatabusSession();
572 }
573 return 0;
574 }
575 return handle;
576 }
577
578 } // namespace OHOS
579 #endif // OHOS_IPC_DBINDER_BASE_INVOKER_OBJECT_H