• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /* check data parcel contains object, if yes, get its session as payload of socket packet
131  * if translate any object failed, discard this parcel and do NOT send this parcel to remote
132  */
133 template<class T>
IRemoteObjectTranslateWhenSend(std::shared_ptr<dbinder_transaction_data> transData,uint32_t socketId,std::shared_ptr<T> sessionObject)134 bool DBinderBaseInvoker<T>::IRemoteObjectTranslateWhenSend(std::shared_ptr<dbinder_transaction_data> transData,
135     uint32_t socketId, std::shared_ptr<T> sessionObject)
136 {
137     if (transData == nullptr || transData->buffer_size == 0) {
138         ZLOGE(LOG_LABEL, "transData or buffer is nullptr");
139         return false;
140     }
141 
142     unsigned char *dataBuffer = transData->buffer;
143     binder_size_t bufferSize = transData->buffer_size;
144     uint32_t totalSize = 0;
145     binder_size_t *binderObjectsOffsets = reinterpret_cast<binder_size_t *>(dataBuffer + transData->offsets);
146     uint32_t offsetOfSession = bufferSize + transData->offsets_size;
147     unsigned char *flatOffset = dataBuffer + offsetOfSession;
148     binder_size_t objCount = transData->offsets_size / sizeof(binder_size_t);
149     binder_size_t preOffset = 0;
150     binder_size_t preObjectSize = 0;
151 
152     for (size_t i = 0; i < objCount; i++) {
153         if (!IsValidRemoteObjectOffset(dataBuffer, bufferSize, binderObjectsOffsets[i], i, preOffset, preObjectSize)) {
154             return false;
155         }
156         auto binderObject = reinterpret_cast<flat_binder_object *>(dataBuffer + binderObjectsOffsets[i]);
157         switch (binderObject->hdr.type) {
158             case BINDER_TYPE_BINDER: {
159                 uint32_t flatSize = TranslateBinderType(binderObject, flatOffset + totalSize, sessionObject);
160                 if (flatSize == 0) {
161                     return false;
162                 }
163                 totalSize += flatSize;
164                 continue;
165             }
166             case BINDER_TYPE_HANDLE: {
167                 uint32_t flatSize = TranslateHandleType(binderObject, flatOffset + totalSize, sessionObject);
168                 if (flatSize == 0) {
169                     return false;
170                 }
171                 totalSize += flatSize;
172                 continue;
173             }
174             case BINDER_TYPE_FD: {
175                 binderObject->hdr.type = BINDER_TYPE_FDR;
176                 binderObject->handle = -1;
177                 continue;
178             }
179             default: {
180                 ZLOGE(LOG_LABEL, "unexpected type:%{public}u", binderObject->hdr.type);
181                 binderObject->hdr.type = BINDER_TYPE_INVALID_TYPE;
182                 return false;
183             }
184         }
185     }
186     return true;
187 }
188 
189 /* if translate any object failed, should translate next object flush it */
190 template<class T>
IRemoteObjectTranslateWhenRcv(unsigned char * dataBuffer,binder_size_t bufferSize,binder_uintptr_t offsets,binder_size_t offsetsSize,MessageParcel & data,uint32_t socketId,uint64_t seqNumber)191 bool DBinderBaseInvoker<T>::IRemoteObjectTranslateWhenRcv(unsigned char *dataBuffer, binder_size_t bufferSize,
192     binder_uintptr_t offsets, binder_size_t offsetsSize, MessageParcel &data, uint32_t socketId, uint64_t seqNumber)
193 {
194     binder_size_t *binderObjectsOffsets = reinterpret_cast<binder_size_t *>(dataBuffer + offsets);
195     uint32_t offsetOfSession = bufferSize + offsetsSize;
196     unsigned char *flatOffset = dataBuffer + offsetOfSession;
197     binder_size_t objCount = offsetsSize / sizeof(binder_size_t);
198     binder_size_t preOffset = 0, preObjectSize = 0;
199 
200     for (size_t i = 0; i < objCount; i++) {
201         if (!IsValidRemoteObjectOffset(dataBuffer, bufferSize, binderObjectsOffsets[i], i, preOffset, preObjectSize)) {
202             return false;
203         }
204         auto binderObject = reinterpret_cast<flat_binder_object *>(dataBuffer + binderObjectsOffsets[i]);
205         switch (binderObject->hdr.type) {
206             case BINDER_TYPE_BINDER: {
207                 ClearBinderType(binderObject);
208                 ZLOGE(LOG_LABEL, "receive an wrong stub object");
209                 return false;
210             }
211             case BINDER_TYPE_HANDLE: {
212                 ClearHandleType(binderObject);
213                 ZLOGE(LOG_LABEL, "receive an wrong proxy object");
214                 return false;
215             }
216             case BINDER_TYPE_REMOTE_HANDLE: {
217                 if (TranslateRemoteHandleType(binderObject, flatOffset + i * T::GetFlatSessionLen(),
218                     SUPPORT_TOKENID_VERSION_NUM) != true) {
219                     ZLOGE(LOG_LABEL, "receive an wrong dbiner object");
220                     // do nothing, should translate other parcel object, such as fd should set to -1
221                 }
222                 continue;
223             }
224             case BINDER_TYPE_FD: {
225                 binderObject->hdr.type = BINDER_TYPE_FDR;
226                 binderObject->handle = -1;
227                 return false;
228             }
229             case BINDER_TYPE_FDR: {
230                 if (!TranslateRawData(dataBuffer, data, socketId, seqNumber)) {
231                     ZLOGE(LOG_LABEL, "fail to translate big raw data");
232                     // do nothing
233                 }
234                 binderObject->handle = -1;
235                 continue;
236             }
237             default: {
238                 ZLOGE(LOG_LABEL, "unexpected type:%{public}u", binderObject->hdr.type);
239                 binderObject->hdr.type = BINDER_TYPE_INVALID_TYPE;
240                 return false;
241             }
242         }
243     }
244     return true;
245 }
246 
247 template<class T>
IRemoteObjectTranslateWhenRcv(dbinder_transaction_data * transData,MessageParcel & data,uint32_t socketId,uint64_t seqNumber)248 bool DBinderBaseInvoker<T>::IRemoteObjectTranslateWhenRcv(dbinder_transaction_data *transData, MessageParcel &data,
249     uint32_t socketId, uint64_t seqNumber)
250 {
251     if (transData == nullptr || transData->buffer_size == 0) {
252         ZLOGE(LOG_LABEL, "transData or buffer is nullptr");
253         return false;
254     }
255 
256     return IRemoteObjectTranslateWhenRcv(transData->buffer, transData->buffer_size, transData->offsets,
257         transData->offsets_size, data, socketId, seqNumber);
258 }
259 
GetSessionObject(uint32_t handle,uint32_t socketId)260 template <class T> std::shared_ptr<T> DBinderBaseInvoker<T>::GetSessionObject(uint32_t handle, uint32_t socketId)
261 {
262     if (handle != 0) {
263         /* transact case */
264         return QueryServerSessionObject(handle);
265     }
266     /* reply case */
267     return QueryClientSessionObject(socketId);
268 }
269 
GetUniqueSeqNumber(int cmd)270 template <class T> uint64_t DBinderBaseInvoker<T>::GetUniqueSeqNumber(int cmd)
271 {
272     IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
273     if (current == nullptr) {
274         ZLOGE(LOG_LABEL, "IPCProcessSkeleton is nullptr");
275         return 0;
276     }
277 
278     if (cmd == BC_TRANSACTION) {
279         auto seqNumber = current->GetSeqNumber();
280         SetSeqNum(seqNumber);
281         return seqNumber;
282     } else if (cmd == BC_REPLY) {
283         /* use sender sequence number */
284         return GetSeqNum();
285     } else {
286         return 0;
287     }
288 }
289 
290 template <class T>
ConstructTransData(MessageParcel & data,dbinder_transaction_data & transData,size_t totalSize,uint64_t seqNum,int cmd,__u32 code,__u32 flags)291 void DBinderBaseInvoker<T>::ConstructTransData(MessageParcel &data, dbinder_transaction_data &transData,
292     size_t totalSize, uint64_t seqNum, int cmd, __u32 code, __u32 flags)
293 {
294     transData.sizeOfSelf = totalSize;
295     transData.magic = DBINDER_MAGICWORD;
296     transData.version = SUPPORT_TOKENID_VERSION_NUM;
297     transData.cmd = cmd;
298     transData.code = code;
299     transData.flags = flags;
300     transData.cookie = 0;
301     transData.seqNumber = seqNum;
302     transData.buffer_size = 0;
303     transData.offsets_size = 0;
304     transData.offsets = 0;
305 }
306 
307 template <class T>
TranslateRawData(unsigned char * dataBuffer,MessageParcel & data,uint32_t socketId,uint64_t seqNumber)308 bool DBinderBaseInvoker<T>::TranslateRawData(unsigned char *dataBuffer, MessageParcel &data, uint32_t socketId,
309     uint64_t seqNumber)
310 {
311     if (socketId == 0) {
312         ZLOGI(LOG_LABEL, "no raw data to translate.");
313         return true;
314     }
315 
316     IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
317     if (current == nullptr) {
318         ZLOGE(LOG_LABEL, "IPCProcessSkeleton is nullptr");
319         return false;
320     }
321     std::shared_ptr<InvokerRawData> receivedRawData = current->QueryRawData(socketId, seqNumber);
322     if (receivedRawData == nullptr) {
323         ZLOGE(LOG_LABEL, "cannot found rawData according to the socketId:%{public}u", socketId);
324         return false;
325     }
326     std::shared_ptr<char> rawData = receivedRawData->GetData();
327     size_t rawSize = receivedRawData->GetSize();
328     current->DetachRawData(socketId, seqNumber);
329     if (!data.RestoreRawData(rawData, rawSize)) {
330         ZLOGE(LOG_LABEL, "found rawData, but cannot restore them, socketId:%{public}u", socketId);
331         return false;
332     }
333     return true;
334 }
335 
336 template <class T>
MoveTransData2Buffer(std::shared_ptr<T> sessionObject,std::shared_ptr<dbinder_transaction_data> transData)337 bool DBinderBaseInvoker<T>::MoveTransData2Buffer(std::shared_ptr<T> sessionObject,
338     std::shared_ptr<dbinder_transaction_data> transData)
339 {
340     std::shared_ptr<BufferObject> sessionBuff = sessionObject->GetSessionBuff();
341     if (sessionBuff == nullptr) {
342         ZLOGE(LOG_LABEL, "get session buffer fail");
343         return false;
344     }
345     if (transData == nullptr) {
346         ZLOGE(LOG_LABEL, "transData is nullptr");
347         return false;
348     }
349     uint32_t sendSize = transData->sizeOfSelf;
350     char *sendBuffer = sessionBuff->GetSendBufferAndLock(sendSize);
351     /* session buffer contain mutex, need release mutex */
352     if (sendBuffer == nullptr) {
353         ZLOGE(LOG_LABEL, "buffer alloc failed in session");
354         return false;
355     }
356 
357     sessionBuff->UpdateSendBuffer(sendSize);
358     ssize_t writeCursor = sessionBuff->GetSendBufferWriteCursor();
359     ssize_t readCursor = sessionBuff->GetSendBufferReadCursor();
360     uint32_t bufferSize = sessionBuff->GetSendBufferSize();
361     if (writeCursor < 0 || readCursor < 0 || static_cast<uint32_t>(writeCursor) > bufferSize ||
362         sendSize > bufferSize - static_cast<uint32_t>(writeCursor)) {
363         sessionBuff->ReleaseSendBufferLock();
364         ZLOGE(LOG_LABEL, "sender's data is large than idle buffer, writecursor:%{public}zd readcursor:%{public}zd, "
365             "sendSize:%{public}u bufferSize:%{public}u", writeCursor, readCursor, sendSize, bufferSize);
366         return false;
367     }
368     if (memcpy_s(sendBuffer + writeCursor, bufferSize - writeCursor, transData.get(), sendSize)) {
369         sessionBuff->ReleaseSendBufferLock();
370         ZLOGE(LOG_LABEL, "fail to copy tr to sendBuffer, writecursor:%{public}zd readcursor:%{public}zd, "
371             "sendSize:%{public}u bufferSize:%{public}u", writeCursor, readCursor, sendSize, bufferSize);
372         return false;
373     }
374 
375     writeCursor += static_cast<ssize_t>(sendSize);
376     sessionBuff->SetSendBufferWriteCursor(writeCursor);
377     sessionBuff->SetSendBufferReadCursor(readCursor);
378     sessionBuff->ReleaseSendBufferLock();
379     return true;
380 }
381 
382 template <class T>
HandleReply(uint64_t seqNumber,MessageParcel * reply,std::shared_ptr<ThreadMessageInfo> messageInfo)383 int DBinderBaseInvoker<T>::HandleReply(uint64_t seqNumber, MessageParcel *reply,
384     std::shared_ptr<ThreadMessageInfo> messageInfo)
385 {
386     if (reply == nullptr) {
387         ZLOGE(LOG_LABEL, "no need reply, free the buffer");
388         DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_NO_NEED_REPLY, __FUNCTION__);
389         return RPC_BASE_INVOKER_INVALID_REPLY_ERR;
390     }
391     if (messageInfo == nullptr) {
392         ZLOGE(LOG_LABEL, "receive buffer is nullptr");
393         DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_RECEIVE_BUFFER_NULL, __FUNCTION__);
394         return RPC_BASE_INVOKER_INVALID_REPLY_ERR;
395     }
396     if (messageInfo->flags & MessageOption::TF_STATUS_CODE) {
397         int32_t err = static_cast<int32_t>(messageInfo->offsetsSize);
398         return err;
399     }
400     if (messageInfo->buffer == nullptr) {
401         ZLOGE(LOG_LABEL, "need reply message, but buffer is nullptr");
402         DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_BUFFER_NULL, __FUNCTION__);
403         return RPC_BASE_INVOKER_INVALID_REPLY_ERR;
404     }
405 
406     if (!IRemoteObjectTranslateWhenRcv(reinterpret_cast<unsigned char *>(messageInfo->buffer), messageInfo->bufferSize,
407         messageInfo->offsets, messageInfo->offsetsSize, *reply, messageInfo->socketId, seqNumber)) {
408         ZLOGE(LOG_LABEL, "translate object failed, socketId:%{public}u", messageInfo->socketId);
409         DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_TRANSLATE_OBJECT_FAIL, __FUNCTION__);
410         return RPC_BASE_INVOKER_INVALID_REPLY_ERR;
411     }
412 
413     auto allocator = new (std::nothrow) DBinderRecvAllocator();
414     if (allocator == nullptr) {
415         ZLOGE(LOG_LABEL, "create DBinderRecvAllocator object failed");
416         DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_CREATE_RECV_ALLOCATOR_FAIL, __FUNCTION__);
417         return RPC_BASE_INVOKER_INVALID_REPLY_ERR;
418     }
419     if (!reply->SetAllocator(allocator)) {
420         ZLOGE(LOG_LABEL, "SetAllocator failed");
421         DfxReportFailEvent(DbinderErrorCode::RPC_DRIVER, RADAR_SET_ALLOCATOR_FAIL, __FUNCTION__);
422         delete allocator;
423         return RPC_BASE_INVOKER_INVALID_REPLY_ERR;
424     }
425     reply->ParseFrom(reinterpret_cast<uintptr_t>(messageInfo->buffer), messageInfo->bufferSize);
426 
427     if (messageInfo->offsetsSize > 0) {
428         reply->InjectOffsets(
429             reinterpret_cast<binder_uintptr_t>(reinterpret_cast<char *>(messageInfo->buffer) + messageInfo->offsets),
430             messageInfo->offsetsSize / sizeof(binder_size_t));
431     }
432     return ERR_NONE;
433 }
434 
Dealloc(void * data)435 template <class T> void DBinderBaseInvoker<T>::DBinderSendAllocator::Dealloc(void *data) {}
436 
Dealloc(void * data)437 template <class T> void DBinderBaseInvoker<T>::DBinderRecvAllocator::Dealloc(void *data)
438 {
439     delete[](unsigned char *) data;
440 }
441 
442 template <class T>
WaitForReply(uint64_t seqNumber,MessageParcel * reply,uint32_t handle,int userWaitTime)443 int DBinderBaseInvoker<T>::WaitForReply(uint64_t seqNumber, MessageParcel *reply, uint32_t handle, int userWaitTime)
444 {
445     /* if reply == nullptr, this is a one way message */
446     if (reply == nullptr) {
447         return NO_ERROR;
448     }
449 
450     std::shared_ptr<ThreadMessageInfo> messageInfo = MakeThreadMessageInfo(handle);
451     if (messageInfo == nullptr) {
452         ZLOGE(LOG_LABEL, "make thread message info failed, handle:%{public}u seq:%{public}" PRIu64,
453             handle, seqNumber);
454         return RPC_BASE_INVOKER_WAIT_REPLY_ERR;
455     }
456 
457     IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
458     if (current == nullptr) {
459         ZLOGE(LOG_LABEL, "IPCProcessSkeleton is nullptr, handle:%{public}u seq:%{public}" PRIu64,
460             handle, seqNumber);
461         return RPC_BASE_INVOKER_WAIT_REPLY_ERR;
462     }
463     /* wait for reply */
464     if (!current->AddSendThreadInWait(seqNumber, messageInfo, userWaitTime)) {
465         current->EraseThreadBySeqNumber(seqNumber);
466         ZLOGE(LOG_LABEL, "sender thread wait reply message time out, "
467             "waitTime:%{public}d handle:%{public}u seq:%{public}" PRIu64, userWaitTime, handle, seqNumber);
468         return RPC_BASE_INVOKER_WAIT_REPLY_ERR;
469     }
470 
471     int32_t err = HandleReply(seqNumber, reply, messageInfo);
472     current->EraseThreadBySeqNumber(seqNumber);
473     messageInfo->buffer = nullptr;
474     messageInfo->ready = false;
475     return err;
476 }
477 
AddDeathRecipient(int32_t handle,void * cookie)478 template <class T> bool DBinderBaseInvoker<T>::AddDeathRecipient(int32_t handle, void *cookie)
479 {
480     return true;
481 }
482 
RemoveDeathRecipient(int32_t handle,void * cookie)483 template <class T> bool DBinderBaseInvoker<T>::RemoveDeathRecipient(int32_t handle, void *cookie)
484 {
485     return true;
486 }
487 
StartProcessLoop(int32_t socketId,const char * buffer,uint32_t size)488 template <class T> void DBinderBaseInvoker<T>::StartProcessLoop(int32_t socketId, const char *buffer, uint32_t size)
489 {
490     IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
491     if (current == nullptr) {
492         ZLOGE(LOG_LABEL, "IPCProcessSkeleton is nullptr");
493         StartLoopFailSendReply(buffer, size, RPC_BASE_INVOKER_CURRENT_NULL_ERR);
494         return;
495     }
496     std::shared_ptr<ThreadProcessInfo> processInfo = MakeThreadProcessInfo(socketId, buffer, size);
497     if (processInfo == nullptr) {
498         ZLOGE(LOG_LABEL, "processInfo is nullptr");
499         StartLoopFailSendReply(buffer, size, RPC_BASE_INVOKER_MALLOC_ERR);
500         return;
501     }
502     std::thread::id threadId = current->GetIdleDataThread();
503     if (threadId == std::thread::id()) {
504         bool result = CreateProcessThread();
505         if (!result) {
506             int socketThreadNum = current->GetSocketTotalThreadNum();
507             ZLOGE(LOG_LABEL, "create IO thread failed, current socket thread num:%{public}d socketId:%{public}d",
508                 socketThreadNum, socketId);
509             /* thread create too much, wait some thread be idle */
510         }
511         do {
512             /*  no IO thread in idle state, wait a monent */
513             std::this_thread::sleep_for(std::chrono::milliseconds(1));
514         } while ((threadId = current->GetIdleDataThread()) == std::thread::id());
515     }
516 
517     current->AddDataInfoToThread(threadId, processInfo);
518     current->WakeUpDataThread(threadId);
519     return;
520 }
521 
MakeThreadMessageInfo(int32_t socketId)522 template <class T> std::shared_ptr<ThreadMessageInfo> DBinderBaseInvoker<T>::MakeThreadMessageInfo(int32_t socketId)
523 {
524     std::shared_ptr<ThreadMessageInfo> messageInfo = std::make_shared<struct ThreadMessageInfo>();
525     if (messageInfo == nullptr) {
526         ZLOGE(LOG_LABEL, "make ThreadMessageInfo fail");
527         return nullptr;
528     }
529 
530     messageInfo->buffer = nullptr;
531     messageInfo->offsets = 0;
532     messageInfo->socketId = static_cast<uint32_t>(socketId);
533     messageInfo->ready = false;
534     return messageInfo;
535 }
536 
MakeRemoteHandle(std::shared_ptr<T> session)537 template<class T> uint32_t DBinderBaseInvoker<T>::MakeRemoteHandle(std::shared_ptr<T> session)
538 {
539     if (session == nullptr) {
540         ZLOGE(LOG_LABEL, "session is nullptr");
541         return 0;
542     }
543     IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
544     if (current == nullptr) {
545         ZLOGE(LOG_LABEL, "IPCProcessSkeleton is nullptr");
546         return 0;
547     }
548 
549     if (!UpdateClientSession(session)) {
550         ZLOGE(LOG_LABEL, "open session failed");
551         return 0;
552     }
553     uint32_t handle = current->GetDBinderIdleHandle(session);
554     if (handle == 0) {
555         ZLOGE(LOG_LABEL, "get dbinder handle failed");
556         if (current->QuerySessionByInfo(session->GetServiceName(), session->GetDeviceId()) == nullptr) {
557             session->CloseDatabusSession();
558         }
559         return 0;
560     }
561     return handle;
562 }
563 
564 } // namespace OHOS
565 #endif // OHOS_IPC_DBINDER_BASE_INVOKER_OBJECT_H