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_INTERFACE_H
17 #define OHOS_IPC_DBINDER_BASE_INVOKER_INTERFACE_H
18
19 #include "dbinder_base_invoker_object.h"
20 #include "dbinder_base_invoker_process.h"
21
22 namespace OHOS {
23
24 template <class T>
WriteTransaction(int cmd,uint32_t flags,int32_t handle,int32_t socketId,uint32_t code,MessageParcel & data,uint64_t & seqNumber,int status)25 std::shared_ptr<T> DBinderBaseInvoker<T>::WriteTransaction(int cmd, uint32_t flags, int32_t handle, int32_t socketId,
26 uint32_t code, MessageParcel &data, uint64_t &seqNumber, int status)
27 {
28 std::shared_ptr<T> sessionObject = GetSessionObject(handle, socketId);
29 if (sessionObject == nullptr) {
30 ZLOGE(LOG_LABEL, "session is not exist for listenFd:%{public}d handle:%{public}d", socketId, handle);
31 DfxReportFailListenEvent(DbinderErrorCode::RPC_DRIVER, socketId, RADAR_GET_SESSION_FAIL, __FUNCTION__);
32 return nullptr;
33 }
34
35 uint64_t seqNum = GetUniqueSeqNumber(cmd);
36 if (seqNum == 0) {
37 ZLOGE(LOG_LABEL, "seqNum invalid, listenFd:%{public}d handle:%{public}d", socketId, handle);
38 DfxReportFailListenEvent(DbinderErrorCode::RPC_DRIVER, socketId, RADAR_SEQ_INVALID, __FUNCTION__);
39 return nullptr;
40 }
41 /* save seqNum for wait thread */
42 seqNumber = seqNum;
43 /* if MessageParcel has raw data, send raw data first, then send MessageParcel to peer */
44 if (ProcessRawData(sessionObject, data, seqNum) != true) {
45 ZLOGE(LOG_LABEL, "send rawdata failed, listenFd:%{public}d handle:%{public}d", socketId, handle);
46 DfxReportFailListenEvent(DbinderErrorCode::RPC_DRIVER, socketId, RADAR_SEND_RAW_DATA_FAIL, __FUNCTION__);
47 return nullptr;
48 }
49 std::shared_ptr<dbinder_transaction_data> transData =
50 ProcessNormalData(sessionObject, data, handle, socketId, seqNum, cmd, code, flags, status);
51 if (transData == nullptr) {
52 ZLOGE(LOG_LABEL, "send normal data failed, listenFd:%{public}d handle:%{public}d", socketId, handle);
53 DfxReportFailListenEvent(DbinderErrorCode::RPC_DRIVER, socketId, RADAR_SEND_NORMAL_DATA_FAIL, __FUNCTION__);
54 return nullptr;
55 }
56
57 if (MoveTransData2Buffer(sessionObject, transData) != true) {
58 ZLOGE(LOG_LABEL, "move transaction data to buffer failed, listenFd:%{public}d handle:%{public}d",
59 socketId, handle);
60 DfxReportFailListenEvent(DbinderErrorCode::RPC_DRIVER, socketId,
61 RADAR_MOVE_TRANS_DATA_TO_BUFFER_FAIL, __FUNCTION__);
62 return nullptr;
63 }
64 return sessionObject;
65 }
66
67 template <class T>
SendOrWaitForCompletion(int userWaitTime,uint64_t seqNumber,std::shared_ptr<T> sessionOfPeer,MessageParcel * reply)68 int DBinderBaseInvoker<T>::SendOrWaitForCompletion(int userWaitTime, uint64_t seqNumber,
69 std::shared_ptr<T> sessionOfPeer, MessageParcel *reply)
70 {
71 if (seqNumber == 0) {
72 ZLOGE(LOG_LABEL, "seqNumber can not be zero");
73 return RPC_BASE_INVOKER_INVALID_DATA_ERR;
74 }
75 if (sessionOfPeer == nullptr) {
76 ZLOGE(LOG_LABEL, "current session is invalid, seq:%{public}" PRIu64, seqNumber);
77 return RPC_BASE_INVOKER_INVALID_DATA_ERR;
78 }
79 int result = OnSendMessage(sessionOfPeer);
80 if (result != 0) {
81 ZLOGE(LOG_LABEL, "fail to send to remote session, error:%{public}d seq:%{public}" PRIu64, result, seqNumber);
82 return RPC_BASE_INVOKER_INVALID_DATA_ERR;
83 }
84 result = WaitForReply(seqNumber, reply, sessionOfPeer->GetSocketId(), userWaitTime);
85 if (result != ERR_NONE) {
86 ZLOGE(LOG_LABEL, "dbinder wait for reply error:%{public}d seq:%{public}" PRIu64, result, seqNumber);
87 }
88 return result;
89 }
90
91 template <class T>
SendRequest(int32_t handle,uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)92 int DBinderBaseInvoker<T>::SendRequest(int32_t handle, uint32_t code, MessageParcel &data, MessageParcel &reply,
93 MessageOption &option)
94 {
95 uint64_t seqNumber = 0;
96 int ret;
97
98 uint32_t flags = static_cast<uint32_t>(option.GetFlags());
99 int userWaitTime = option.GetWaitTime();
100 MessageParcel &newData = const_cast<MessageParcel &>(data);
101 size_t oldWritePosition = newData.GetWritePosition();
102 HiTraceId traceId = HiTraceChain::GetId();
103 // set client send trace point if trace is enabled
104 HiTraceId childId = HitraceInvoker::TraceClientSend(handle, code, newData, flags, traceId);
105 std::shared_ptr<T> session = WriteTransaction(BC_TRANSACTION, flags, handle, 0, code, data, seqNumber, 0);
106 if (session == nullptr) {
107 newData.RewindWrite(oldWritePosition);
108 ZLOGE(LOG_LABEL, "WriteTransaction fail, handle:%{public}d", handle);
109 return RPC_BASE_INVOKER_WRITE_TRANS_ERR;
110 }
111
112 if (flags & TF_ONE_WAY) {
113 ret = SendOrWaitForCompletion(userWaitTime, seqNumber, session, nullptr);
114 } else {
115 ret = SendOrWaitForCompletion(userWaitTime, seqNumber, session, &reply);
116 }
117 HitraceInvoker::TraceClientReceieve(handle, code, flags, traceId, childId);
118 // restore Parcel data
119 newData.RewindWrite(oldWritePosition);
120 return ret;
121 }
122
SetMaxWorkThread(int maxThreadNum)123 template <class T> bool DBinderBaseInvoker<T>::SetMaxWorkThread(int maxThreadNum)
124 {
125 return true;
126 }
127
SendReply(MessageParcel & reply,uint32_t flags,int32_t result)128 template <class T> int DBinderBaseInvoker<T>::SendReply(MessageParcel &reply, uint32_t flags, int32_t result)
129 {
130 uint64_t seqNumber = 0;
131 std::shared_ptr<T> sessionObject = WriteTransaction(BC_REPLY, flags, 0,
132 GetClientFd(), 0, reply, seqNumber, result);
133 if (seqNumber == 0) {
134 ZLOGE(LOG_LABEL, "WriteTransaction fail, seqNumber can not be zero");
135 return RPC_BASE_INVOKER_SEND_REPLY_ERR;
136 }
137 SendOrWaitForCompletion(0, seqNumber, sessionObject, nullptr);
138 return 0;
139 }
140
OnTransaction(std::shared_ptr<ThreadProcessInfo> processInfo)141 template <class T> void DBinderBaseInvoker<T>::OnTransaction(std::shared_ptr<ThreadProcessInfo> processInfo)
142 {
143 if (processInfo == nullptr) {
144 ZLOGE(LOG_LABEL, "processInfo is error!");
145 return;
146 }
147 int32_t listenFd = processInfo->listenFd;
148 char *package = processInfo->buffer.get();
149
150 if (package == nullptr || listenFd < 0) {
151 ZLOGE(LOG_LABEL, "package is null or listenFd:%{public}d invalid!", listenFd);
152 return;
153 }
154
155 dbinder_transaction_data *tr = reinterpret_cast<dbinder_transaction_data *>(package);
156 if (tr->sizeOfSelf < sizeof(dbinder_transaction_data)) {
157 ZLOGE(LOG_LABEL, "package size:%{public}u is invalid, expected size:%{public}zu",
158 tr->sizeOfSelf, sizeof(dbinder_transaction_data));
159 return;
160 }
161
162 if (tr->cmd == BC_TRANSACTION) {
163 ProcessTransaction(tr, listenFd);
164 } else if (tr->cmd == BC_REPLY) {
165 ProcessReply(tr, listenFd);
166 }
167 return;
168 }
169
PingService(int32_t handle)170 template <class T> bool DBinderBaseInvoker<T>::PingService(int32_t handle)
171 {
172 return true;
173 }
174
GetSAMgrObject()175 template <class T> sptr<IRemoteObject> DBinderBaseInvoker<T>::GetSAMgrObject()
176 {
177 return nullptr;
178 }
179
180
SetRegistryObject(sptr<IRemoteObject> & object)181 template <class T> bool DBinderBaseInvoker<T>::SetRegistryObject(sptr<IRemoteObject> &object)
182 {
183 return true;
184 }
185
FreeBuffer(void * data)186 template <class T> void DBinderBaseInvoker<T>::FreeBuffer(void *data)
187 {
188 return;
189 }
190
CheckTransactionData(const dbinder_transaction_data * tr)191 template <class T> bool DBinderBaseInvoker<T>::CheckTransactionData(const dbinder_transaction_data *tr) const
192 {
193 if (tr->sizeOfSelf == 0 || tr->sizeOfSelf > SOCKET_MAX_BUFF_SIZE || tr->buffer_size > SOCKET_MAX_BUFF_SIZE ||
194 tr->buffer_size == 0 || tr->offsets != tr->buffer_size ||
195 tr->sizeOfSelf < sizeof(dbinder_transaction_data) + tr->buffer_size) {
196 return false;
197 }
198 if ((tr->flags & MessageOption::TF_STATUS_CODE) && (tr->offsets != sizeof(binder_size_t))) {
199 return false;
200 }
201 if (!(tr->flags & MessageOption::TF_STATUS_CODE)) {
202 if (tr->offsets_size > (tr->sizeOfSelf - sizeof(dbinder_transaction_data) - tr->buffer_size)) {
203 return false;
204 }
205 binder_size_t sessionSize =
206 tr->sizeOfSelf - tr->buffer_size - sizeof(dbinder_transaction_data) - tr->offsets_size;
207 if (sessionSize * sizeof(binder_size_t) != tr->offsets_size * T::GetFlatSessionLen()) {
208 return false;
209 }
210 }
211
212 return true;
213 }
214
GetObjectMutex()215 template <class T> std::mutex &DBinderBaseInvoker<T>::GetObjectMutex()
216 {
217 return objectMutex_;
218 }
219 } // namespace OHOS
220 #endif // OHOS_IPC_DBINDER_BASE_INVOKER_INTERFACE_H