• 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 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