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