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