未验证 提交 78d7e61d 编写于 作者: O openharmony_ci 提交者: Gitee

!98 RPC支持跨设备收发及死亡通知

Merge pull request !98 from pilipala195/master
......@@ -14,10 +14,18 @@
import("//build/lite/config/component/lite_component.gni")
lite_component("rpc") {
features = [ "ipc:ipc_single" ]
features = [
"ipc:rpc_manager",
"dbinder:dbinder",
]
if (ohos_kernel_type != "liteos_m") {
features += [ "ipc:ipc_single" ]
}
if (ohos_build_type == "debug") {
features += [
"//foundation/communication/ipc/ipc/test/unittest/ipc:ipc_test_gtest",
"//foundation/communication/ipc/ipc/test/rpc:rpc_test",
]
}
}
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/lite/config/component/lite_component.gni")
SUBSYSTEM_DIR = "//foundation/communication/ipc"
DBINDER_ROOT = "$SUBSYSTEM_DIR/services/dbinder/c"
config("ipc_rpc_interface") {
include_dirs = [
"$SUBSYSTEM_DIR/interfaces/innerkits/c/ipc/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/c/dbinder/include",
]
}
if (ohos_kernel_type == "linux") {
SYSTEM_LEVEL = "small"
shared_library("dbinder") {
sources = [
"$DBINDER_ROOT/ipc_adapter/${SYSTEM_LEVEL}/dbinder_ipc_adapter.c",
"$DBINDER_ROOT/src/dbinder_service.c",
"$DBINDER_ROOT/src/dbinder_stub.c",
"$DBINDER_ROOT/src/dbinder_trans_callback.c",
]
public_configs = [ ":ipc_rpc_interface" ]
include_dirs = [
"$DBINDER_ROOT/include",
"$DBINDER_ROOT/ipc_adapter/include",
"$SUBSYSTEM_DIR/ipc/native/c/ipc/include",
"$SUBSYSTEM_DIR/ipc/native/c/rpc/include",
"$SUBSYSTEM_DIR/ipc/native/c/rpc/ipc_adapter/include",
"$SUBSYSTEM_DIR/ipc/native/c/rpc/trans_adapter/include",
"$SUBSYSTEM_DIR/ipc/native/c/manager/include",
"//third_party/bounds_checking_function/include",
"//utils/native/lite/include",
]
ldflags = [
"-lstdc++",
"-lpthread",
]
public_deps = [
"$SUBSYSTEM_DIR/interfaces/innerkits/c/ipc:rpc_log",
"//third_party/bounds_checking_function/:libsec_shared",
]
}
} else if (ohos_kernel_type == "liteos_m") {
SYSTEM_LEVEL = "mini"
static_library("dbinder") {
sources = [
"$DBINDER_ROOT/ipc_adapter/${SYSTEM_LEVEL}/dbinder_ipc_adapter.c",
"$DBINDER_ROOT/src/dbinder_service.c",
"$DBINDER_ROOT/src/dbinder_stub.c",
"$DBINDER_ROOT/src/dbinder_trans_callback.c",
]
public_configs = [ ":ipc_rpc_interface" ]
include_dirs = [
"$DBINDER_ROOT/include",
"$DBINDER_ROOT/ipc_adapter/include",
"$SUBSYSTEM_DIR/ipc/native/c/ipc/include",
"$SUBSYSTEM_DIR/ipc/native/c/rpc/include",
"$SUBSYSTEM_DIR/ipc/native/c/rpc/ipc_adapter/include",
"$SUBSYSTEM_DIR/ipc/native/c/rpc/trans_adapter/include",
"$SUBSYSTEM_DIR/ipc/native/c/manager/include",
"$SUBSYSTEM_DIR/ipc/test/rpc/include",
"//third_party/bounds_checking_function/include",
"//utils/native/lite/include",
"//base/hiviewdfx/hilog_lite/interfaces/native/kits/hilog_lite",
]
ldflags = [ "-lpthread" ]
deps = [ "//foundation/communication/ipc/ipc/native/c/adapter:rpc_adapter" ]
}
}
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DBINDER_SERVICE_H
#define DBINDER_SERVICE_H
#include <pthread.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include "dbinder_types.h"
#include "utils_list.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef struct {
struct DHandleEntryHead head;
uint32_t transType;
uint32_t dBinderCode;
uint16_t fromPort;
uint16_t toPort;
uint64_t stubIndex;
uint32_t seqNumber;
uintptr_t binderObject;
struct DeviceIdInfo deviceIdInfo;
uintptr_t stub;
uint16_t serviceNameLength;
char serviceName[SERVICENAME_LENGTH + 1];
uint32_t pid;
uint32_t uid;
} DHandleEntryTxRx;
int32_t StartDBinderService(void);
int32_t RegisterRemoteProxy(const void *name, uint32_t len, int32_t systemAbility);
int32_t MakeRemoteBinder(const void *serviceName, uint32_t nameLen, const char *deviceID, uint32_t idLen,
uintptr_t binderObject, uint64_t pid, void *remoteObject);
int32_t OnRemoteMessageTask(const DHandleEntryTxRx *message);
SessionInfo *QuerySessionObject(uintptr_t stub);
void DetachProxyObject(ProxyObject *proxy);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* DBINDER_SERVICE_H */
\ No newline at end of file
......@@ -17,7 +17,10 @@ SUBSYSTEM_DIR = "//foundation/communication/ipc"
IPC_CORE_ROOT = "$SUBSYSTEM_DIR/ipc/native/c"
config("ipc_rpc_interface") {
include_dirs = [ "$SUBSYSTEM_DIR/interfaces/innerkits/c/ipc/include" ]
include_dirs = [
"$SUBSYSTEM_DIR/interfaces/innerkits/c/ipc/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/c/dbinder/include",
]
}
if (ohos_kernel_type == "liteos_m") {
......@@ -45,14 +48,40 @@ ipc_common_src = [
]
if (ohos_kernel_type == "liteos_m") {
static_library("ipc_single") {
SYSTEM_LEVEL = "mini"
static_library("rpc_manager") {
sources = ipc_common_src
sources += [
"$IPC_CORE_ROOT/ipc/src/binder_invoker_virtual.c",
"$IPC_CORE_ROOT/manager/src/rpc_log.c",
"$IPC_CORE_ROOT/rpc/ipc_adapter/${SYSTEM_LEVEL}/ipc_proxy_inner.c",
"$IPC_CORE_ROOT/rpc/ipc_adapter/${SYSTEM_LEVEL}/ipc_stub_inner.c",
"$IPC_CORE_ROOT/rpc/src/dbinder_invoker.c",
"$IPC_CORE_ROOT/rpc/src/rpc_process_skeleton.c",
"$IPC_CORE_ROOT/rpc/src/rpc_trans_callback.c",
"$IPC_CORE_ROOT/rpc/trans_adapter/src/rpc_trans.c",
]
include_dirs = ipc_common_include
public_configs = [ ":ipc_rpc_interface" ]
include_dirs = ipc_common_include
include_dirs += [
"$IPC_CORE_ROOT/rpc/include",
"$IPC_CORE_ROOT/rpc/ipc_adapter/include",
"$IPC_CORE_ROOT/rpc/trans_adapter/include",
"$SUBSYSTEM_DIR/services/dbinder/c/include",
]
if (ohos_build_type == "debug") {
sources += [
"$SUBSYSTEM_DIR/ipc/test/rpc/samgr/rpc_mini_samgr.c",
"$SUBSYSTEM_DIR/ipc/test/rpc/socket_trans/src/rpc_${SYSTEM_LEVEL}_socket_trans.c",
]
include_dirs += [
"$SUBSYSTEM_DIR/ipc/test/rpc/include",
"$SUBSYSTEM_DIR/ipc/test/rpc/socket_trans/include",
"//third_party/lwip/src/include",
]
defines = [ "RPC_SOCKET_TRANS" ]
}
ldflags = [ "-lpthread" ]
deps = [ "//foundation/communication/ipc/ipc/native/c/adapter:rpc_adapter" ]
}
} else if (ohos_kernel_type == "liteos_a") {
......@@ -85,6 +114,9 @@ if (ohos_kernel_type == "liteos_m") {
"//third_party/bounds_checking_function/:libsec_shared",
]
}
shared_library("rpc_manager") {
}
} else {
shared_library("rpc_log") {
sources = [ "$IPC_CORE_ROOT/manager/src/rpc_log.c" ]
......@@ -100,9 +132,17 @@ if (ohos_kernel_type == "liteos_m") {
shared_library("ipc_single") {
sources = ipc_common_src
sources += [ "$IPC_CORE_ROOT/ipc/src/binder_invoker.c" ]
sources += [
"$IPC_CORE_ROOT/ipc/src/binder_invoker.c",
"$IPC_CORE_ROOT/rpc/src/rpc_process_skeleton_virtual.c",
]
public_configs = [ ":ipc_rpc_interface" ]
include_dirs = ipc_common_include
include_dirs += [
"$IPC_CORE_ROOT/rpc/include",
"$IPC_CORE_ROOT/rpc/trans_adapter/include",
"$SUBSYSTEM_DIR/services/dbinder/c/include",
]
ldflags = [
"-lstdc++",
"-lpthread",
......@@ -116,4 +156,45 @@ if (ohos_kernel_type == "liteos_m") {
]
configs -= [ "//build/lite/config:clang_opt" ]
}
SYSTEM_LEVEL = "small"
shared_library("rpc_manager") {
sources = ipc_common_src
sources += [
"$IPC_CORE_ROOT/ipc/src/binder_invoker.c",
"$IPC_CORE_ROOT/rpc/ipc_adapter/${SYSTEM_LEVEL}/ipc_proxy_inner.c",
"$IPC_CORE_ROOT/rpc/ipc_adapter/${SYSTEM_LEVEL}/ipc_stub_inner.c",
"$IPC_CORE_ROOT/rpc/src/dbinder_invoker.c",
"$IPC_CORE_ROOT/rpc/src/rpc_process_skeleton.c",
"$IPC_CORE_ROOT/rpc/src/rpc_trans_callback.c",
"$IPC_CORE_ROOT/rpc/trans_adapter/src/rpc_trans.c",
]
public_configs = [ ":ipc_rpc_interface" ]
include_dirs = ipc_common_include
include_dirs += [
"$IPC_CORE_ROOT/rpc/include",
"$IPC_CORE_ROOT/rpc/ipc_adapter/include",
"$IPC_CORE_ROOT/rpc/trans_adapter/include",
"$SUBSYSTEM_DIR/services/dbinder/c/include",
"//third_party/bounds_checking_function/include",
]
ldflags = [
"-lstdc++",
"-lpthread",
]
cflags = [ "-fPIC" ]
cflags_cc = cflags
public_deps = [
":rpc_log",
"//foundation/communication/ipc/ipc/native/c/adapter:rpc_adapter",
"//third_party/bounds_checking_function/:libsec_shared",
]
if (ohos_build_type == "debug") {
sources +=
[ "$SUBSYSTEM_DIR/ipc/test/rpc/socket_trans/src/rpc_socket_trans.c" ]
include_dirs += [ "$SUBSYSTEM_DIR/ipc/test/rpc/socket_trans/include" ]
defines = [ "RPC_SOCKET_TRANS" ]
}
}
}
......@@ -22,6 +22,7 @@
#include "ipc_skeleton.h"
#include "iremote_invoker.h"
#include "dbinder_types.h"
#ifdef __cplusplus
#if __cplusplus
......@@ -43,7 +44,7 @@ typedef struct {
IpcObjectStub *objectStub;
pid_t callerPid;
pid_t callerUid;
char callerDeviceID[64];
char callerDeviceID[DEVICEID_LENGTH + 1];
bool stopWorkThread;
uint64_t seqNumber;
uint32_t clientFd;
......
......@@ -20,6 +20,7 @@
#include "rpc_errno.h"
#include "rpc_log.h"
#include "rpc_os_adapter.h"
#include "rpc_process_skeleton.h"
#include "rpc_types.h"
#include "securec.h"
#include "utils_list.h"
......@@ -81,6 +82,10 @@ IpcSkeleton *GetCurrentSkeleton(void)
return NULL;
}
g_ipcSkeleton = temp;
int32_t ret = RpcProcessSkeleton();
if (ret != ERR_NONE) {
RPC_LOG_ERROR("rpc process skeleton init failed");
}
}
pthread_mutex_unlock(&g_ipcSkeletonMutex);
}
......@@ -265,7 +270,7 @@ static uint32_t SetDeathHandlerPair(DeathCallback *node, uint32_t index, OnRemot
int32_t ProcessAddDeathRecipient(int32_t handle, OnRemoteDead deathFunc, void *args, uint32_t *cbId)
{
int32_t ret = ERR_INVALID_PARAM;
int32_t ret = ERR_NONE;
if (g_ipcSkeleton == NULL) {
return ERR_IPC_SKELETON_NOT_INIT;
}
......@@ -359,6 +364,7 @@ int32_t ProcessRemoveDeathRecipient(int32_t handle, uint32_t cbId)
int32_t OnRemoteRequestInner(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option, IpcObjectStub *objectStub)
{
int32_t result = ERR_NOT_RPC;
result = RpcOnRemoteRequestInner(code, data, reply, option, objectStub);
if (result == ERR_NOT_RPC) {
if (objectStub != NULL && objectStub->func != NULL) {
result = (OnRemoteRequest)(objectStub->func)(code, data, reply, option);
......@@ -417,4 +423,5 @@ void WaitForProxyInit(int32_t handle)
{
RPC_LOG_INFO("ipc skeleton wait for proxy init");
OnFirstStrongRef(handle);
UpdateProtoIfNeed(handle);
}
\ No newline at end of file
......@@ -16,6 +16,7 @@
#include "iremote_invoker.h"
#include "binder_invoker.h"
#include "dbinder_invoker.h"
#include "rpc_types.h"
RemoteInvoker *InitRemoteInvoker(int32_t proto)
......@@ -23,6 +24,8 @@ RemoteInvoker *InitRemoteInvoker(int32_t proto)
RemoteInvoker *remoteInvoker = NULL;
if (proto == IF_PROT_BINDER) {
remoteInvoker = GetIpcInvoker();
} else {
remoteInvoker = GetRpcInvoker();
}
return remoteInvoker;
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_RPC_INVOKER_H
#define OHOS_RPC_INVOKER_H
#include <stdbool.h>
#include <stdint.h>
#include "rpc_process_skeleton.h"
#include "iremote_invoker.h"
#ifdef __cplusplus
extern "C" {
#endif
RemoteInvoker *GetRpcInvoker(void);
void DeleteRpcInvoker(RemoteInvoker *remoteInvoker);
void RpcStopWorkThread(void);
int32_t OnReceiveNewConnection(int sessionId);
void OnDatabusSessionClosed(int sessionId);
void OnMessageAvailable(int sessionId, const void *data, unsigned int len);
void UpdateClientSession(int32_t handle, HandleSessionList *sessionObject, const char *sessionName,
const char *serviceName, const char *deviceId);
int32_t CreateTransServer(const char *sessionName);
#ifdef __cplusplus
}
#endif
#endif // OHOS_RPC_INVOKER_H
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_RPC_PROCESS_SKELETON_H
#define OHOS_RPC_PROCESS_SKELETON_H
#include <stdint.h>
#include <pthread.h>
#include "ipc_skeleton.h"
#include "rpc_trans.h"
#include "utils_list.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
pthread_mutex_t lock;
uint64_t stubIndex;
char *sessionName;
uint64_t seqNumber;
TransInterface *rpcTrans;
int32_t isServerCreated;
} RpcSkeleton;
typedef struct {
UTILS_DL_LIST list;
uint64_t stubIndex;
OnRemoteRequest func;
} StubObject;
typedef struct {
UTILS_DL_LIST stubObjects;
pthread_mutex_t mutex;
} StubObjectList;
typedef struct {
UTILS_DL_LIST list;
pthread_t threadId;
uint32_t listenFd;
uint32_t packageSize;
char *buffer;
} ThreadProcessInfo;
typedef struct {
UTILS_DL_LIST processInfo;
pthread_mutex_t mutex;
} ThreadProcessInfoList;
typedef struct {
UTILS_DL_LIST list;
pthread_t threadId;
pthread_mutex_t mutex;
pthread_cond_t condition;
} SocketThreadLockInfo;
typedef struct {
UTILS_DL_LIST socketLockInfo;
pthread_mutex_t mutex;
} SocketThreadLockInfoList;
typedef struct {
UTILS_DL_LIST list;
pthread_t threadId;
} IdleDataThread;
typedef struct {
UTILS_DL_LIST idleDataThread;
pthread_mutex_t mutex;
} IdleDataThreadsList;
typedef struct {
UTILS_DL_LIST list;
uint32_t handle;
uint32_t sessionId;
char *buffer;
uint32_t len;
} HandleSessionList;
typedef struct {
UTILS_DL_LIST list;
uint32_t handle;
uint64_t index;
} HandleToIndexList;
typedef struct {
UTILS_DL_LIST list;
pthread_t threadId;
uint64_t seqNumber;
uint32_t flags;
size_t bufferSize;
size_t offsetsSize;
uintptr_t offsets;
uint32_t socketId;
void *buffer;
} ThreadMessageInfo;
int32_t RpcProcessSkeleton(void);
RpcSkeleton *GetCurrentRpcSkeleton(void);
int32_t AddStubByIndex(StubObject *stubObject);
StubObject *QueryStubByIndex(uint64_t stubIndex);
void AddDataThreadInWait(pthread_t threadId);
IdleDataThread *GetIdleDataThread(void);
void AddDataInfoToThread(ThreadProcessInfo *processInfo);
ThreadProcessInfo *PopDataInfoFromThread(pthread_t threadId);
uint32_t ConvertChannelID2Int(int64_t databusChannelId);
int32_t AttachStubSession(HandleSessionList *handleSession);
void DetachStubSession(HandleSessionList *handleSession);
HandleSessionList *QueryStubSession(uint32_t handle);
int32_t AttachProxySession(HandleSessionList *handleSession);
void DetachProxySession(HandleSessionList *handleSession);
HandleSessionList *QueryProxySession(uint32_t handle);
HandleSessionList *QueryProxySessionBySessionId(uint32_t sessionId);
uint64_t ProcessGetSeqNumber(void);
int32_t AttachHandleToIndex(HandleToIndexList *handleToIndex);
void DetachHandleToIndex(HandleToIndexList *handleToIndex);
HandleToIndexList *QueryHandleToIndex(uint32_t handle);
int32_t AddSendThreadInWait(uint64_t seqNumber, ThreadMessageInfo *messageInfo, int userWaitTime);
void EraseThreadBySeqNumber(ThreadMessageInfo *messageInfo);
ThreadMessageInfo *QueryThreadBySeqNumber(uint64_t seqNumber);
void WakeUpThreadBySeqNumber(uint64_t seqNumber, uint32_t handle);
int32_t RpcOnRemoteRequestInner(uint32_t code, IpcIo *data, IpcIo *reply,
MessageOption option, IpcObjectStub *objectStub);
void UpdateProtoIfNeed(int32_t handle);
void WakeUpDataThread(pthread_t threadId);
uint64_t GetNewStubIndex(void);
#ifdef __cplusplus
}
#endif
#endif // OHOS_RPC_PROCESS_SKELETON_H
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_RPC_TRANS_CALLBACK_H
#define OHOS_RPC_TRANS_CALLBACK_H
#include "rpc_trans.h"
#ifdef __cplusplus
extern "C" {
#endif
TransCallback *GetRpcTransCallback(void);
#ifdef __cplusplus
}
#endif
#endif // OHOS_RPC_TRANS_CALLBACK_H
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_PROXY_INNER_H
#define OHOS_IPC_PROXY_INNER_H
#include <stdint.h>
#include "dbinder_types.h"
#include "serializer.h"
#ifdef __cplusplus
extern "C" {
#endif
int32_t InvokerListenThread(ProxyObject *proxyObject, const char *localDeviceID,
const char *remoteDeviceID, uint32_t pid, uint32_t uid, IpcIo *reply, uintptr_t *ptr);
int32_t GetPidAndUidInfo(ProxyObject *proxy);
char *GetDataBusName(void);
void UpdateProto(int32_t handle);
#ifdef __cplusplus
}
#endif
#endif // OHOS_IPC_PROXY_INNER_H
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_IPC_STUB_INNER_H
#define OHOS_IPC_STUB_INNER_H
#include <stdint.h>
#include "serializer.h"
#include "ipc_skeleton.h"
#ifdef __cplusplus
extern "C" {
#endif
int32_t InvokerListenThreadStub(uint32_t code, IpcIo *data, IpcIo *reply, int32_t option, OnRemoteRequest *func);
int32_t GetPidAndUidInfoStub(uint32_t code, IpcIo *data, IpcIo *reply, int32_t option);
int32_t GrantDataBusNameStub(uint32_t code, IpcIo *data, IpcIo *reply, int32_t option);
#ifdef __cplusplus
}
#endif
#endif // OHOS_IPC_STUB_INNER_H
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_proxy_inner.h"
#include <stddef.h>
#include <string.h>
#include <securec.h>
#include "ipc_thread_pool.h"
#include "rpc_process_skeleton.h"
#include "dbinder_invoker.h"
#include "dbinder_types.h"
#include "rpc_errno.h"
#include "rpc_log.h"
static int32_t GetDigits(int32_t number)
{
int32_t n = 0;
while (number > 0) {
n++;
number /= ID_DIGITS;
}
if (n == 0) {
n++;
}
return n;
}
static int32_t MakeInvokerListenReply(ProxyObject *proxyObject, uint64_t stubIndex, IpcIo *reply, uintptr_t *ptr)
{
ptr = (uintptr_t *)calloc(1, RPC_IPC_LENGTH);
if (ptr == NULL) {
RPC_LOG_ERROR("InvokerListenThread ptr calloc failed");
return ERR_FAILED;
}
IpcIoInit(reply, (void *)ptr, RPC_IPC_LENGTH, 0);
if (!WriteUint64(reply, stubIndex)) {
RPC_LOG_ERROR("InvokerListenThread WriteUint64 failed");
free((void *)ptr);
return ERR_FAILED;
}
if (!WriteString(reply, proxyObject->sessionName)) {
RPC_LOG_ERROR("InvokerListenThread WriteString failed");
free((void *)ptr);
return ERR_FAILED;
}
((IpcIo *)reply)->bufferCur = ((IpcIo *)reply)->bufferBase;
return ERR_NONE;
}
int32_t InvokerListenThread(ProxyObject *proxyObject, const char *localDeviceID, const char *remoteDeviceID,
uint32_t pid, uint32_t uid, IpcIo *reply, uintptr_t *ptr)
{
if (proxyObject == NULL) {
RPC_LOG_ERROR("InvokerListenThread proxy is null");
return ERR_FAILED;
}
int32_t sessionNameLen = strlen(proxyObject->sessionName);
RpcSkeleton *current = GetCurrentRpcSkeleton();
if (current == NULL) {
RPC_LOG_ERROR("GetCurrentSkeleton failed");
return ERR_FAILED;
}
if (CreateTransServer(proxyObject->sessionName) != ERR_NONE) {
return ERR_FAILED;
}
if (current->sessionName != NULL) {
free(current->sessionName);
}
if (sessionNameLen == 0 || sessionNameLen > SERVICENAME_LENGTH) {
RPC_LOG_ERROR("sessionNameLen invalid");
return ERR_FAILED;
}
current->sessionName = (char *)malloc(sessionNameLen + 1);
if (current->sessionName == NULL) {
return ERR_FAILED;
}
if (sessionNameLen == 0 || sessionNameLen > SERVICENAME_LENGTH) {
RPC_LOG_ERROR("sessionNameLen invalid");
return ERR_FAILED;
}
if (strcpy_s(current->sessionName, sessionNameLen + 1, proxyObject->sessionName) != EOK) {
free(current->sessionName);
return ERR_FAILED;
}
StubObject *stubObject = (StubObject *)malloc(sizeof(StubObject));
if (stubObject == NULL) {
return ERR_FAILED;
}
uint64_t stubIndex = GetNewStubIndex();
stubObject->stubIndex = stubIndex;
IpcObjectStub *cookie = (IpcObjectStub *)(proxyObject->proxy->cookie);
stubObject->func = cookie->func;
if (AddStubByIndex(stubObject) != ERR_NONE) {
free(stubObject);
return ERR_FAILED;
}
return MakeInvokerListenReply(proxyObject, stubIndex, reply, ptr);
}
int32_t GetPidAndUidInfo(ProxyObject *proxyObject)
{
if (proxyObject == NULL) {
RPC_LOG_ERROR("GetPidAndUidInfo proxy is null");
return ERR_FAILED;
}
int32_t pid = (int32_t)GetCallingPid();
int32_t pidLen = GetDigits(pid);
int32_t uid = (int32_t)GetCallingUid();
int32_t uidLen = GetDigits(uid);
uint32_t sessionNameLen = SESSION_NAME_LEGNTH + pidLen + uidLen;
proxyObject->sessionName = (char *)malloc(sessionNameLen + 1);
if (proxyObject->sessionName == NULL) {
RPC_LOG_ERROR("sessionName mallo failed");
return ERR_FAILED;
}
if (sprintf_s(proxyObject->sessionName, sessionNameLen + 1, "DBinder%d_%d", uid, pid) == -1) {
RPC_LOG_ERROR("sessionName sprintf failed");
free(proxyObject->sessionName);
return ERR_FAILED;
}
return ERR_NONE;
}
char *GetDataBusName(void)
{
return NULL;
}
static char *CreateDatabusName(void)
{
int32_t pid = (int32_t)GetCallingPid();
int32_t pidLen = GetDigits(pid);
int32_t uid = (int32_t)GetCallingUid();
int32_t uidLen = GetDigits(uid);
uint32_t sessionNameLen = SESSION_NAME_LEGNTH + pidLen + uidLen;
char *sessionName = (char *)malloc(sessionNameLen + 1);
if (sessionName == NULL) {
RPC_LOG_ERROR("sessionName mallo failed");
return NULL;
}
if (sprintf_s(sessionName, sessionNameLen + 1, "DBinder%d_%d", uid, pid) == -1) {
RPC_LOG_ERROR("sessionName sprintf failed");
free(sessionName);
return NULL;
}
return sessionName;
}
static int GetSessionFromDBinderService(uint32_t handle)
{
RPC_LOG_INFO("GetSessionFromDBinderService start");
int32_t proto = IF_PROT_DATABUS;
SessionInfo *session = QuerySessionObject((uintptr_t)handle);
if (session == NULL) {
RPC_LOG_ERROR("client find session is null");
return proto;
}
const char *localBusName = CreateDatabusName();
if (localBusName == NULL) {
RPC_LOG_ERROR("ProcessProto CreateDatabusName failed");
return proto;
}
HandleSessionList *sessionObject = (HandleSessionList *)malloc(sizeof(HandleSessionList));
if (sessionObject == NULL) {
RPC_LOG_ERROR("UpdateDatabusClientSession sessionObject malloc failed");
return proto;
}
HandleToIndexList *handleToIndex = (HandleToIndexList *)malloc(sizeof(HandleToIndexList));
if (handleToIndex == NULL) {
RPC_LOG_ERROR("UpdateDatabusClientSession handleToIndex malloc failed");
free(sessionObject);
return proto;
}
handleToIndex->handle = handle;
handleToIndex->index = session->stubIndex;
if (AttachHandleToIndex(handleToIndex) != ERR_NONE) {
RPC_LOG_ERROR("AttachHandleToIndex failed");
free(sessionObject);
free(handleToIndex);
return proto;
}
if (CreateTransServer(localBusName) != ERR_NONE) {
RPC_LOG_ERROR("create bus server fail name = %s, localID = %s",
localBusName, session->deviceIdInfo.fromDeviceId);
DetachHandleToIndex(handleToIndex);
free(sessionObject);
free(handleToIndex);
return proto;
}
UpdateClientSession(handle, sessionObject, localBusName, session->serviceName, session->deviceIdInfo.toDeviceId);
return proto;
}
void UpdateProto(int32_t handle)
{
if (handle < 0) {
RPC_LOG_ERROR("UpdateProto handle invalid");
return;
}
ThreadContext *threadContext = GetCurrentThreadContext();
if (threadContext == NULL) {
RPC_LOG_ERROR("UpdateProto threadContext is null");
return;
}
HandleSessionList *sessionObject = QueryProxySession(handle);
if (sessionObject != NULL) {
threadContext->proto = IF_PROT_DATABUS;
return;
}
threadContext->proto = GetSessionFromDBinderService(handle);
RPC_LOG_INFO("UpdateProto get proto: %d", threadContext->proto);
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_stub_inner.h"
#include "rpc_errno.h"
int32_t InvokerListenThreadStub(uint32_t code, IpcIo *data, IpcIo *reply, int32_t option, OnRemoteRequest *func)
{
return ERR_NONE;
}
int32_t GetPidAndUidInfoStub(uint32_t code, IpcIo *data, IpcIo *reply, int32_t option)
{
return ERR_NONE;
}
int32_t GrantDataBusNameStub(uint32_t code, IpcIo *data, IpcIo *reply, int32_t option)
{
return ERR_NONE;
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_proxy_inner.h"
#include "securec.h"
#include "serializer.h"
#include "rpc_log.h"
#include "rpc_errno.h"
#include "ipc_process_skeleton.h"
#include "ipc_thread_pool.h"
#include "dbinder_invoker.h"
#include "dbinder_types.h"
#include "rpc_process_skeleton.h"
static void UpdateDatabusClientSession(int32_t handle, IpcIo *reply)
{
uint64_t stubIndex;
if (!ReadUint64(reply, &stubIndex)) {
return;
}
size_t len;
char *serviceName = (char *)ReadString(reply, &len);
char *peerID = (char *)ReadString(reply, &len);
char *localID = (char *)ReadString(reply, &len);
char *localBusName = (char *)ReadString(reply, &len);
HandleSessionList *sessionObject = (HandleSessionList *)malloc(sizeof(HandleSessionList));
if (sessionObject == NULL) {
RPC_LOG_ERROR("UpdateDatabusClientSession sessionObject malloc failed");
return;
}
HandleToIndexList *handleToIndex = (HandleToIndexList *)malloc(sizeof(HandleToIndexList));
if (handleToIndex == NULL) {
RPC_LOG_ERROR("UpdateDatabusClientSession handleToIndex malloc failed");
free(sessionObject);
return;
}
handleToIndex->handle = handle;
handleToIndex->index = stubIndex;
if (AttachHandleToIndex(handleToIndex) != ERR_NONE) {
RPC_LOG_ERROR("AttachHandleToIndex failed");
free(sessionObject);
free(handleToIndex);
return;
}
if (CreateTransServer(localBusName) != ERR_NONE) {
RPC_LOG_ERROR("create bus server fail name = %s, localID = %s", localBusName, localID);
DetachHandleToIndex(handleToIndex);
free(sessionObject);
free(handleToIndex);
return;
}
UpdateClientSession(handle, sessionObject, localBusName, serviceName, peerID);
}
static int GetSessionFromDBinderService(uint32_t handle)
{
RPC_LOG_INFO("GetSessionFromDBinderService start");
IpcIo data;
IpcIo reply;
uint8_t dataAlloc[RPC_IPC_LENGTH_LONG];
IpcIoInit(&data, dataAlloc, RPC_IPC_LENGTH_LONG, 0);
MessageOption option = TF_OP_SYNC;
SvcIdentity target = {
.handle = handle
};
uintptr_t ptr;
int32_t ret = ProcessSendRequest(target, GET_PROTO_INFO, &data, &reply, option, &ptr);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("sendrequest GET_PROTO_INFO failed, error %d", ret);
FreeBuffer((void *)ptr);
return IF_PROT_BINDER;
}
uint32_t proto;
if (!ReadUint32(&reply, &proto)) {
FreeBuffer((void *)ptr);
return IF_PROT_BINDER;
}
switch (proto) {
case IF_PROT_BINDER:
break;
case IF_PROT_DATABUS: {
UpdateDatabusClientSession(handle, &reply);
proto = IF_PROT_DATABUS;
break;
}
default:
break;
}
FreeBuffer((void *)ptr);
return proto;
}
int32_t InvokerListenThread(ProxyObject *proxyObject, const char *localDeviceID, const char *remoteDeviceID,
uint32_t pid, uint32_t uid, IpcIo *reply, uintptr_t *ptr)
{
if (proxyObject == NULL || localDeviceID == NULL || remoteDeviceID == NULL) {
return ERR_FAILED;
}
IpcIo *ipcReply = (IpcIo *)reply;
IpcIo data;
uint8_t dataAlloc[RPC_IPC_LENGTH_LONG];
IpcIoInit(&data, dataAlloc, RPC_IPC_LENGTH_LONG, 0);
WriteUint16(&data, DATABUS_TYPE);
WriteString(&data, localDeviceID);
WriteUint32(&data, pid);
WriteUint32(&data, uid);
WriteString(&data, remoteDeviceID);
WriteString(&data, proxyObject->sessionName);
MessageOption option = TF_OP_SYNC;
int32_t ret = SendRequest(*proxyObject->proxy, INVOKE_LISTEN_THREAD, &data, ipcReply, option, ptr);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("INVOKE_LISTEN_THREAD failed");
}
return ret;
}
int32_t GetPidAndUidInfo(ProxyObject *proxyObject)
{
if (proxyObject == NULL) {
RPC_LOG_ERROR("GetPidAndUidInfo proxy is null");
return ERR_FAILED;
}
IpcIo data;
IpcIo reply;
uint8_t dataAlloc[RPC_IPC_LENGTH];
IpcIoInit(&data, dataAlloc, RPC_IPC_LENGTH, 0);
MessageOption option = TF_OP_SYNC;
uintptr_t ptr;
int32_t ret = SendRequest(*proxyObject->proxy, GET_UIDPID_INFO, &data, &reply, option, &ptr);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("sendrequest GET_UIDPID_INFO failed, error %d", ret);
FreeBuffer((void *)ptr);
return ERR_FAILED;
}
size_t len;
char *sessionName = (char *)ReadString(&reply, &len);
proxyObject->sessionName = (char *)malloc(len + 1);
if (proxyObject->sessionName == NULL) {
RPC_LOG_ERROR("GetPidAndUidInfo proxy name malloc failed");
FreeBuffer((void *)ptr);
return ERR_FAILED;
}
if (strcpy_s(proxyObject->sessionName, len + 1, sessionName) != 0) {
RPC_LOG_ERROR("GetPidAndUidInfo proxy name copy failed");
free(proxyObject->sessionName);
FreeBuffer((void *)ptr);
return ERR_FAILED;
}
FreeBuffer((void *)ptr);
return ERR_NONE;
}
char *GetDataBusName(void)
{
IpcIo data;
IpcIo reply;
uint8_t dataAlloc[RPC_IPC_LENGTH];
IpcIoInit(&data, dataAlloc, RPC_IPC_LENGTH, 0);
MessageOption option = TF_OP_SYNC;
uintptr_t ptr;
int32_t ret = ProcessSendRequest(*GetContextObject(), GRANT_DATABUS_NAME, &data, &reply, option, &ptr);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("sendrequest GRANT_DATABUS_NAME failed, error %d", ret);
FreeBuffer((void *)ptr);
return NULL;
}
int32_t proto;
if (!ReadInt32(&reply, &proto)) {
FreeBuffer((void *)ptr);
return NULL;
}
if (proto != IF_PROT_DATABUS) {
RPC_LOG_INFO("GetDataBusName normal binder");
FreeBuffer((void *)ptr);
return NULL;
}
size_t len;
const char *name = (const char *)ReadString(&reply, &len);
RPC_LOG_INFO("GetDataBusName name %s, len %d", name, len);
char *sessionName = (char *)malloc(len + 1);
if (sessionName == NULL) {
RPC_LOG_ERROR("GetDataBusName sessionName malloc failed");
FreeBuffer((void *)ptr);
return NULL;
}
if (strcpy_s(sessionName, len + 1, name) != EOK) {
RPC_LOG_ERROR("GetDataBusName sessionName copy failed");
free(sessionName);
FreeBuffer((void *)ptr);
return NULL;
}
FreeBuffer((void *)ptr);
return sessionName;
}
void UpdateProto(int32_t handle)
{
if (handle < 0) {
RPC_LOG_ERROR("UpdateProto handle invalid");
return;
}
ThreadContext *threadContext = GetCurrentThreadContext();
if (threadContext == NULL) {
RPC_LOG_ERROR("UpdateProto threadContext is null");
return;
}
HandleSessionList *sessionObject = QueryProxySession(handle);
if (sessionObject != NULL) {
threadContext->proto = IF_PROT_DATABUS;
return;
}
threadContext->proto = GetSessionFromDBinderService(handle);
RPC_LOG_INFO("UpdateProto get proto: %d", threadContext->proto);
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ipc_stub_inner.h"
#include "securec.h"
#include "dbinder_types.h"
#include "dbinder_invoker.h"
#include "rpc_process_skeleton.h"
#include "rpc_types.h"
#include "rpc_errno.h"
#include "rpc_log.h"
#include "ipc_proxy_inner.h"
#include "ipc_thread_pool.h"
static int32_t IsDeviceIdIllegal(const char *deviceID, uint32_t len)
{
if (deviceID == NULL || len > DEVICEID_LENGTH) {
return ERR_FAILED;
}
return ERR_NONE;
}
static int32_t MakeStubCached(IpcIo *reply, OnRemoteRequest func,
const char *sessionName, const char *deviceID)
{
RpcSkeleton *current = GetCurrentRpcSkeleton();
if (current == NULL) {
RPC_LOG_ERROR("GetCurrentSkeleton failed");
return ERR_FAILED;
}
StubObject *stubObject = (StubObject *)malloc(sizeof(StubObject));
if (stubObject == NULL) {
return ERR_FAILED;
}
uint64_t stubIndex = GetNewStubIndex();
stubObject->stubIndex = stubIndex;
stubObject->func = func;
if (AddStubByIndex(stubObject) != ERR_NONE) {
free(stubObject);
return ERR_FAILED;
}
WriteUint64(reply, stubIndex);
WriteString(reply, sessionName);
WriteString(reply, deviceID);
return ERR_NONE;
}
static int32_t InvokerDataBusThread(IpcIo *data, IpcIo *reply, OnRemoteRequest func)
{
size_t deviceIDLen;
const char *deviceID = (const char*)ReadString(data, &deviceIDLen);
uint32_t remotePid;
if (!ReadUint32(data, &remotePid)) {
return ERR_FAILED;
}
uint32_t remoteUid;
if (!ReadUint32(data, &remoteUid)) {
return ERR_FAILED;
}
size_t remoteDeviceIDLen;
const char *remoteDeviceID = (const char*)ReadString(data, &remoteDeviceIDLen);
size_t sessionNameLen;
const char *sessionName = (const char*)ReadString(data, &sessionNameLen);
if (IsDeviceIdIllegal(deviceID, deviceIDLen) != ERR_NONE ||
IsDeviceIdIllegal(remoteDeviceID, remoteDeviceIDLen) != ERR_NONE || sessionName == NULL) {
RPC_LOG_ERROR("deviceID invalid or session name is null");
return ERR_FAILED;
}
RpcSkeleton *current = GetCurrentRpcSkeleton();
if (current == NULL) {
RPC_LOG_ERROR("GetCurrentSkeleton failed");
return ERR_FAILED;
}
if (CreateTransServer(sessionName) != ERR_NONE) {
return ERR_FAILED;
}
if (current->sessionName != NULL) {
free(current->sessionName);
}
if (sessionNameLen == 0 || sessionNameLen > SERVICENAME_LENGTH) {
RPC_LOG_ERROR("sessionNameLen invalid");
return ERR_FAILED;
}
current->sessionName = (char *)malloc(sessionNameLen + 1);
if (current->sessionName == NULL) {
return ERR_FAILED;
}
if (strcpy_s(current->sessionName, sessionNameLen + 1, sessionName) != EOK) {
free(current->sessionName);
return ERR_FAILED;
}
return MakeStubCached(reply, func, sessionName, deviceID);
}
int32_t InvokerListenThreadStub(uint32_t code, IpcIo *data, IpcIo *reply, int32_t option, OnRemoteRequest *func)
{
uint16_t type;
if (!ReadUint16(data, &type)) {
return ERR_FAILED;
}
switch (type) {
case DATABUS_TYPE: {
if (InvokerDataBusThread(data, reply, func) != 0) {
RPC_LOG_ERROR("Invoker databus thread fail");
return ERR_FAILED;
}
break;
}
default: {
RPC_LOG_ERROR("InvokerThread Invalid Type");
return ERR_FAILED;
}
}
return ERR_NONE;
}
int32_t GetPidAndUidInfoStub(uint32_t code, IpcIo *data, IpcIo *reply, int32_t option)
{
int32_t result = ERR_NONE;
char *sessionName = GetDataBusName();
if (sessionName == NULL || strlen(sessionName) == 0) {
RPC_LOG_ERROR("GetDataBusName failed");
result = ERR_FAILED;
} else {
WriteString(reply, sessionName);
free(sessionName);
result = ERR_NONE;
}
return result;
}
static int32_t GetDigits(int32_t number)
{
int32_t n = 0;
while (number > 0) {
n++;
number /= ID_DIGITS;
}
if (n == 0) {
n++;
}
return n;
}
int32_t GrantDataBusNameStub(uint32_t code, IpcIo *data, IpcIo *reply, int32_t option)
{
int32_t pid = (int32_t)GetCallingPid();
int32_t pidLen = GetDigits(pid);
int32_t uid = (int32_t)GetCallingUid();
int32_t uidLen = GetDigits(uid);
uint32_t sessionNameLen = SESSION_NAME_LEGNTH + pidLen + uidLen;
char *sessionName = (char *)malloc(sessionNameLen + 1);
if (sessionName == NULL) {
RPC_LOG_ERROR("sessionName mallo failed");
return ERR_FAILED;
}
if (sprintf_s(sessionName, sessionNameLen + 1, "DBinder%d_%d", uid, pid) == -1) {
RPC_LOG_ERROR("sessionName sprintf failed");
free(sessionName);
return ERR_FAILED;
}
WriteInt32(reply, IF_PROT_DATABUS);
WriteString(reply, sessionName);
free(sessionName);
return ERR_NONE;
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dbinder_invoker.h"
#include <inttypes.h>
#include <pthread.h>
#include <unistd.h>
#include "securec.h"
#include "utils_list.h"
#include "rpc_log.h"
#include "rpc_errno.h"
#include "rpc_trans.h"
#include "rpc_trans_callback.h"
#include "ipc_skeleton.h"
#include "ipc_process_skeleton.h"
#include "ipc_thread_pool.h"
#include "dbinder_types.h"
#define BC_TRANSACTION 1076388608
#define BC_REPLY 1076388609
static const int DBINDER_MAGICWORD = 0X4442494E;
static const int SOCKET_MAX_BUFF_SIZE = 1024 * 1024;
static RemoteInvoker *g_rpcInvoker = NULL;
void DeleteRpcInvoker(RemoteInvoker *remoteInvoker)
{
if (remoteInvoker == NULL) {
return;
}
free(remoteInvoker);
}
static HandleSessionList *GetSessionObject(uint32_t handle, uint32_t socketId)
{
if (handle != 0) {
/* transact case */
return QueryProxySession(handle);
} else {
/* reply case */
return QueryStubSession(socketId);
}
}
static uint64_t GetUniqueSeqNumber(int cmd)
{
if (cmd == BC_TRANSACTION) {
return ProcessGetSeqNumber();
} else if (cmd == BC_REPLY) {
ThreadContext *threadContext = GetCurrentThreadContext();
if (threadContext == NULL) {
RPC_LOG_ERROR("GetUniqueSeqNumber threadContext is null");
return 0;
}
return threadContext->seqNumber;
}
return 0;
}
static void ToTransData(const IpcIo *data, dbinder_transaction_data *buf)
{
buf->buffer_size = (data == NULL) ? 0 : (data->bufferCur - data->bufferBase);
buf->offsets = buf->buffer_size;
buf->offsets_size = (data == NULL) ? 0 :
((size_t)(data->offsetsCur - data->offsetsBase) * sizeof(size_t));
}
static void ToIpcData(const dbinder_transaction_data *tr, IpcIo *data)
{
data->bufferBase = data->bufferCur = (char *)(tr->buffer);
data->offsetsBase = data->offsetsCur = (size_t *)(data->bufferBase + (size_t)tr->buffer_size);
data->bufferLeft = (size_t)tr->buffer_size;
data->offsetsLeft = (tr->offsets_size) / sizeof(size_t);
data->flag = IPC_IO_INITIALIZED;
}
static int32_t MoveIpcToTransData(IpcIo *data, dbinder_transaction_data *transData, int status)
{
if (data != NULL) {
ToTransData(data, transData);
if (memcpy_s(transData->buffer, transData->buffer_size, data->bufferBase, transData->buffer_size) != EOK) {
RPC_LOG_ERROR("transData buffer memset failed");
return ERR_FAILED;
}
uint32 offsetsSize = transData->sizeOfSelf - sizeof(dbinder_transaction_data) - transData->buffer_size;
if (offsetsSize > 0) {
if (memcpy_s(transData->buffer + transData->buffer_size, offsetsSize,
data->offsetsBase, offsetsSize) != EOK) {
RPC_LOG_ERROR("transData buffer memset failed");
return ERR_FAILED;
}
}
} else {
transData->flags |= TF_OP_STATUS_CODE;
transData->buffer_size = sizeof(size_t);
transData->offsets_size = (size_t)status;
transData->offsets = transData->buffer_size;
}
return ERR_NONE;
}
static int32_t ProcessNormalData(IpcIo *data, int32_t handle, int status, dbinder_transaction_data *transData)
{
if (transData == NULL) {
RPC_LOG_ERROR("ProcessNormalData transData is null");
return ERR_FAILED;
}
uint32_t dataSize = (uint32_t)(data->offsetsCur - data->offsetsBase) +
(uint32_t)(data->bufferCur - data->bufferBase);
transData->buffer = (char *)malloc(dataSize);
if (transData->buffer == NULL) {
RPC_LOG_ERROR("transData buffer malloc failed");
return ERR_FAILED;
}
transData->sizeOfSelf = sizeof(dbinder_transaction_data) + dataSize;
if (handle == 0) {
transData->cookie = 0;
} else {
HandleToIndexList *handleToIndex = QueryHandleToIndex(handle);
if (handleToIndex == NULL) {
RPC_LOG_ERROR("stubIndex not found for handle %{public}d", handle);
return ERR_FAILED;
}
transData->cookie = handleToIndex->index;
}
if (MoveIpcToTransData(data, transData, status) != ERR_NONE) {
RPC_LOG_ERROR("move parcel to transData failed, handle = %d", handle);
return ERR_FAILED;
}
return ERR_NONE;
}
static int32_t MoveTransData2Buffer(HandleSessionList *sessionObject, dbinder_transaction_data *transData)
{
sessionObject->buffer = (char *)malloc((size_t)transData->sizeOfSelf);
if (sessionObject->buffer == NULL) {
RPC_LOG_ERROR("sessionObject buffer malloc failed");
return ERR_FAILED;
}
sessionObject->len = (uint32_t)transData->sizeOfSelf;
if (memcpy_s(sessionObject->buffer, sizeof(dbinder_transaction_data),
transData, sizeof(dbinder_transaction_data)) != EOK) {
RPC_LOG_ERROR("sessionObject buffer memset failed");
free(sessionObject->buffer);
return ERR_FAILED;
}
if (memcpy_s(sessionObject->buffer + sizeof(dbinder_transaction_data),
transData->buffer_size, transData->buffer, transData->buffer_size) != EOK) {
RPC_LOG_ERROR("sessionObject buffer memset failed");
free(sessionObject->buffer);
return ERR_FAILED;
}
return ERR_NONE;
}
static HandleSessionList *WriteTransaction(int cmd, MessageOption option, int32_t handle,
int32_t socketId, uint32_t code, IpcIo *data, uint64_t *seqNumber, int status)
{
HandleSessionList *sessionObject = GetSessionObject(handle, socketId);
if (sessionObject == NULL) {
RPC_LOG_ERROR("session is not exist for listenFd = %d, handle = %d", socketId, handle);
return NULL;
}
uint64_t seqNum = GetUniqueSeqNumber(cmd);
if (seqNum == 0) {
RPC_LOG_ERROR("seqNum invalid");
if (sessionObject->buffer != NULL) {
free(sessionObject->buffer);
}
return NULL;
}
*seqNumber = seqNum;
dbinder_transaction_data transData = {
.magic = DBINDER_MAGICWORD,
.version = VERSION_NUM,
.cmd = cmd,
.code = code,
.flags = option,
.seqNumber = *seqNumber,
.buffer = NULL
};
if (ProcessNormalData(data, handle, status, &transData) != ERR_NONE) {
RPC_LOG_ERROR("ProcessNormalData failed");
if (transData.buffer != NULL) {
free(transData.buffer);
return NULL;
}
}
if (MoveTransData2Buffer(sessionObject, &transData) != ERR_NONE) {
RPC_LOG_ERROR("move transaction data to buffer failed");
free(transData.buffer);
return NULL;
}
free(transData.buffer);
return sessionObject;
}
static int32_t OnSendMessage(HandleSessionList *sessionOfPeer)
{
if (sessionOfPeer == NULL || sessionOfPeer->buffer == NULL) {
RPC_LOG_ERROR("sessionOfPeer or buffer is null");
return ERR_FAILED;
}
RpcSkeleton *rpcSkeleton = GetCurrentRpcSkeleton();
if (rpcSkeleton == NULL) {
RPC_LOG_ERROR("RpcSkeleton is null");
return ERR_FAILED;
}
int32_t ret = rpcSkeleton->rpcTrans->Send((int)sessionOfPeer->sessionId,
(void *)sessionOfPeer->buffer, (unsigned int)sessionOfPeer->len);
free(sessionOfPeer->buffer);
return ret;
}
static ThreadMessageInfo *MakeThreadMessageInfo(uint64_t seqNumber, uint32_t handle)
{
ThreadMessageInfo *messageInfo = (ThreadMessageInfo *)malloc(sizeof(ThreadMessageInfo));
if (messageInfo == NULL) {
RPC_LOG_ERROR("messageInfo malloc failed");
return NULL;
}
messageInfo->threadId = pthread_self();
messageInfo->seqNumber = seqNumber;
messageInfo->buffer = NULL;
messageInfo->offsets = 0;
messageInfo->socketId = handle;
return messageInfo;
}
static int32_t HandleReply(uint64_t seqNumber, IpcIo *reply, uintptr_t *buffer)
{
if (reply == NULL) {
RPC_LOG_ERROR("no need reply, free the buffer");
return ERR_FAILED;
}
ThreadMessageInfo *messageInfo = QueryThreadBySeqNumber(seqNumber);
if (messageInfo == NULL) {
RPC_LOG_ERROR("receive buffer is nullptr");
return ERR_NONE;
}
if (messageInfo->flags & TF_OP_STATUS_CODE) {
int32_t err = messageInfo->offsetsSize;
return err;
}
dbinder_transaction_data transData = {
.buffer_size = messageInfo->bufferSize,
.offsets_size = messageInfo->offsetsSize,
.offsets = messageInfo->offsets,
.buffer = messageInfo->buffer
};
ToIpcData(&transData, reply);
buffer = (uintptr_t *)messageInfo->buffer;
return ERR_NONE;
}
static int32_t WaitForReply(uint64_t seqNumber, IpcIo *reply, uint32_t handle, int userWaitTime, uintptr_t *buffer)
{
if (reply == NULL || userWaitTime == 0) {
return ERR_NONE;
}
ThreadMessageInfo *messageInfo = MakeThreadMessageInfo(seqNumber, handle);
if (messageInfo == NULL) {
RPC_LOG_ERROR("make thread message info failed, no memory");
return ERR_FAILED;
}
if (AddSendThreadInWait(seqNumber, messageInfo, userWaitTime) != ERR_NONE) {
RPC_LOG_ERROR("sender thread wait reply message time out");
EraseThreadBySeqNumber(messageInfo);
free(messageInfo);
return ERR_FAILED;
}
int32_t result = HandleReply(seqNumber, reply, buffer);
EraseThreadBySeqNumber(messageInfo);
free(messageInfo);
return result;
}
static int32_t SendOrWaitForCompletion(int userWaitTime, uint64_t seqNumber,
HandleSessionList *sessionOfPeer, IpcIo *reply, uintptr_t *buffer)
{
if (seqNumber == 0) {
RPC_LOG_ERROR("seqNumber can not be zero");
return ERR_FAILED;
}
if (sessionOfPeer == NULL) {
RPC_LOG_ERROR("current session is invalid");
return ERR_FAILED;
}
int32_t result = OnSendMessage(sessionOfPeer);
if (result != ERR_NONE) {
RPC_LOG_ERROR("fail to send to remote session with error = %d", result);
// no return, for msg send failed maybe not mine
}
return WaitForReply(seqNumber, reply, sessionOfPeer->handle, userWaitTime, buffer);
}
static int32_t GetClientFd(void)
{
ThreadContext *threadContext = GetCurrentThreadContext();
return threadContext->clientFd;
}
static int32_t SendReply(IpcIo *reply, uint32_t flags, int32_t result)
{
uint64_t seqNumber = 0;
HandleSessionList *sessionObject = WriteTransaction(BC_REPLY, flags, 0, GetClientFd(),
0, reply, &seqNumber, result);
if (seqNumber == 0) {
RPC_LOG_ERROR("seqNumber can not be zero");
return ERR_FAILED;
}
SendOrWaitForCompletion(0, seqNumber, sessionObject, reply, NULL);
return ERR_NONE;
}
static void ProcessTransaction(const dbinder_transaction_data *tr, uint32_t listenFd)
{
if (tr == NULL || tr->cookie == 0) {
return;
}
IpcIo data;
IpcIo reply;
uint8_t replyAlloc[RPC_IPC_LENGTH];
IpcIoInit(&reply, replyAlloc, RPC_IPC_LENGTH, 0);
MessageOption option = tr->flags;
uint64_t senderSeqNumber = tr->seqNumber;
ToIpcData(tr, &data);
ThreadContext *threadContext = GetCurrentThreadContext();
const pid_t oldPid = threadContext->callerPid;
const pid_t oldUid = threadContext->callerUid;
char oldDeviceId[DEVICEID_LENGTH];
if (memcpy_s(oldDeviceId, DEVICEID_LENGTH, threadContext->callerDeviceID, DEVICEID_LENGTH) != EOK) {
RPC_LOG_ERROR("oldDeviceId memcpy failed");
return;
}
StubObject *stubObject = QueryStubByIndex(tr->cookie);
if (stubObject == NULL) {
RPC_LOG_ERROR("stubIndex is invalid");
return;
}
int32_t result = stubObject->func(tr->code, &data, &reply, option);
if (result != ERR_NONE) {
RPC_LOG_ERROR("stub is invalid, has not OnReceive or Request");
}
if (!(option & TF_OP_ASYNC)) {
threadContext->clientFd = listenFd;
threadContext->seqNumber = senderSeqNumber;
SendReply(&reply, 0, result);
threadContext->clientFd = 0;
threadContext->seqNumber = 0;
}
threadContext->callerPid = oldPid;
threadContext->callerUid = oldUid;
if (memcpy_s(threadContext->callerDeviceID, DEVICEID_LENGTH, oldDeviceId, DEVICEID_LENGTH) != EOK) {
RPC_LOG_ERROR("threadContext callerDeviceID memcpy failed");
}
}
static void ProcessReply(const dbinder_transaction_data *tr, uint32_t listenFd)
{
ThreadMessageInfo *messageInfo = QueryThreadBySeqNumber(tr->seqNumber);
if (messageInfo == NULL) {
RPC_LOG_ERROR("no thread waiting reply message of this seqNumber");
/* messageInfo is null, no thread need to wakeup */
return;
}
size_t bufferSize = tr->sizeOfSelf - sizeof(dbinder_transaction_data);
messageInfo->buffer = (void *)malloc(bufferSize);
if (messageInfo->buffer == NULL) {
RPC_LOG_ERROR("some thread is waiting for reply message, but no memory");
/* wake up sender thread */
WakeUpThreadBySeqNumber(tr->seqNumber, listenFd);
return;
}
if (memcpy_s(messageInfo->buffer, bufferSize, tr->buffer, bufferSize) != EOK) {
RPC_LOG_ERROR("messageInfo buffer memset failed");
free(messageInfo->buffer);
WakeUpThreadBySeqNumber(tr->seqNumber, listenFd);
return;
}
messageInfo->flags = tr->flags;
messageInfo->bufferSize = tr->buffer_size;
messageInfo->offsetsSize = tr->offsets_size;
messageInfo->offsets = tr->offsets;
messageInfo->socketId = listenFd;
/* wake up sender thread */
WakeUpThreadBySeqNumber(tr->seqNumber, listenFd);
}
static void OnTransaction(ThreadProcessInfo *processInfo)
{
if (processInfo == NULL) {
return;
}
dbinder_transaction_data *tr = (dbinder_transaction_data *)processInfo->buffer;
tr->buffer = (char *)(processInfo->buffer + sizeof(dbinder_transaction_data));
if (tr->cmd == BC_TRANSACTION) {
ProcessTransaction(tr, processInfo->listenFd);
} else if (tr->cmd == BC_REPLY) {
ProcessReply(tr, processInfo->listenFd);
}
}
static ThreadProcessInfo *MakeThreadProcessInfo(uint32_t handle, const char *inBuffer, uint32_t size)
{
if (inBuffer == NULL || size < sizeof(dbinder_transaction_data)) {
RPC_LOG_ERROR("buffer is null or size invalid");
return NULL;
}
ThreadProcessInfo *processInfo = (ThreadProcessInfo *)malloc(sizeof(ThreadProcessInfo));
if (processInfo == NULL) {
return NULL;
}
processInfo->buffer = (char *)malloc(size);
if (processInfo->buffer == NULL) {
free(processInfo);
return NULL;
}
if (memcpy_s(processInfo->buffer, size, inBuffer, size) != EOK) {
free(processInfo->buffer);
free(processInfo);
return NULL;
}
processInfo->listenFd = handle;
processInfo->packageSize = size;
return processInfo;
}
static int32_t CreateProcessThread(void)
{
IpcSkeleton *current = GetCurrentSkeleton();
if (current == NULL) {
RPC_LOG_ERROR("current ipcskeleton is nullptr");
return ERR_FAILED;
}
if (current->threadPool->idleSocketThreadNum > 0) {
SpawnThread(SPAWN_PASSIVE, IF_PROT_DATABUS);
RPC_LOG_INFO("create Process thread success");
return ERR_NONE;
}
return ERR_FAILED;
}
static void StartProcessLoop(uint32_t handle, const void *buffer, uint32_t size)
{
ThreadProcessInfo *processInfo = MakeThreadProcessInfo(handle, buffer, size);
if (processInfo == NULL) {
RPC_LOG_ERROR("MakeThreadProcessInfo failed");
return;
}
IdleDataThread *idleDataThread = GetIdleDataThread();
if (idleDataThread == NULL) {
if (CreateProcessThread() != ERR_NONE) {
RPC_LOG_ERROR("create IO thread failed");
}
do {
/* no IO thread in idle state, wait a monent */
usleep(GET_IDLE_THREAD_WAIT_TIME);
idleDataThread = GetIdleDataThread();
} while (idleDataThread == NULL);
}
pthread_t threadId = idleDataThread->threadId;
processInfo->threadId = threadId;
AddDataInfoToThread(processInfo);
WakeUpDataThread(threadId);
}
int32_t OnReceiveNewConnection(int sessionId)
{
uint32_t handle = sessionId;
IpcSkeleton *current = GetCurrentSkeleton();
if (current == NULL) {
RPC_LOG_ERROR("current ipcskeleton is nullptr");
return ERR_FAILED;
}
HandleSessionList *stubSession = (HandleSessionList *)malloc(sizeof(HandleSessionList));
if (stubSession == NULL) {
RPC_LOG_ERROR("stubSession malloc failed");
return ERR_FAILED;
}
stubSession->handle = handle;
stubSession->sessionId = sessionId;
if (AttachStubSession(stubSession) != ERR_NONE) {
RPC_LOG_ERROR("AttachStubSession failed");
free(stubSession);
return ERR_FAILED;
}
return ERR_NONE;
}
void OnDatabusSessionClosed(int sessionId)
{
if (sessionId < 0) {
return;
}
uint32_t handle = sessionId;
HandleSessionList *handleSession = QueryStubSession(handle);
if (handleSession != NULL) {
DetachStubSession(handleSession);
free(handleSession);
RPC_LOG_INFO("OnDatabusSessionClosed called on rpc stub");
return;
}
handleSession = QueryProxySessionBySessionId(sessionId);
if (handleSession == NULL) {
RPC_LOG_INFO("OnDatabusSessionClosed query session is null");
return;
}
DetachProxySession(handleSession);
HandleToIndexList *handeleIndex = QueryHandleToIndex(handleSession->handle);
if (handeleIndex == NULL) {
RPC_LOG_INFO("OnDatabusSessionClosed query stub index is null");
return;
}
DetachHandleToIndex(handeleIndex);
IpcSkeleton *ipcSkeleton = GetCurrentSkeleton();
if (ipcSkeleton == NULL) {
RPC_LOG_ERROR("GetCurrentSkeleton return null");
return;
}
DeathCallback *node = NULL;
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &ipcSkeleton->objects, DeathCallback, list)
{
if (node->handle == handleSession->handle) {
RPC_LOG_INFO("OnDatabusSessionClosed SendObituary handle %d", node->handle);
SendObituary(node);
DeleteDeathCallback(node);
break;
}
}
}
static uint32_t HasCompletePackage(const char *data, uint32_t readCursor, unsigned int len)
{
const dbinder_transaction_data *tr = (const dbinder_transaction_data *)(data + readCursor);
if ((tr->magic == DBINDER_MAGICWORD) &&
(tr->sizeOfSelf <= SOCKET_MAX_BUFF_SIZE + sizeof(dbinder_transaction_data)) &&
(readCursor + tr->sizeOfSelf <= len)) {
return (uint32_t)tr->sizeOfSelf;
}
return 0;
}
void OnMessageAvailable(int sessionId, const void *data, unsigned int len)
{
if (sessionId < 0 || data == NULL || len < sizeof(dbinder_transaction_data)) {
RPC_LOG_ERROR("session has wrong inputs");
return;
}
uint32_t handle = sessionId;
uint32_t readSize = 0;
while (readSize + sizeof(dbinder_transaction_data) < len) {
uint32_t packageSize = HasCompletePackage(data, readSize, len);
if (packageSize > 0) {
StartProcessLoop(handle, data, packageSize);
readSize += packageSize;
} else {
// If the current is abnormal, the subsequent is no longer processed.
break;
}
};
}
void UpdateClientSession(int32_t handle, HandleSessionList *sessionObject, const char *sessionName,
const char *serviceName, const char *deviceId)
{
if (handle < 0 || sessionObject == NULL || sessionName == NULL || serviceName == NULL || deviceId == NULL) {
return;
}
RpcSkeleton *rpcSkeleton = GetCurrentRpcSkeleton();
if (rpcSkeleton == NULL) {
return;
}
int sessionId = rpcSkeleton->rpcTrans->Connect(serviceName, deviceId, NULL);
if (sessionId < 0) {
RPC_LOG_ERROR("UpdateClientSession OpenSessionSync failed");
return;
}
sessionObject->handle = handle;
sessionObject->sessionId = sessionId;
if (AttachProxySession(sessionObject) != ERR_NONE) {
RPC_LOG_ERROR("UpdateClientSession AttachProxySession failed");
}
}
int32_t CreateTransServer(const char *sessionName)
{
if (sessionName == NULL) {
return ERR_FAILED;
}
RpcSkeleton *rpcSkeleton = GetCurrentRpcSkeleton();
if (rpcSkeleton == NULL) {
return ERR_FAILED;
}
if (rpcSkeleton->isServerCreated == 0) {
return ERR_NONE;
}
pthread_mutex_lock(&rpcSkeleton->lock);
if (rpcSkeleton->isServerCreated == -1) {
if (rpcSkeleton->rpcTrans->StartListen(sessionName, GetRpcTransCallback()) != ERR_NONE) {
RPC_LOG_ERROR("CreateTransServer failed");
pthread_mutex_unlock(&rpcSkeleton->lock);
return ERR_FAILED;
}
rpcSkeleton->isServerCreated = 0;
pthread_mutex_unlock(&rpcSkeleton->lock);
return SpawnThread(SPAWN_ACTIVE, IF_PROT_DATABUS);
}
pthread_mutex_unlock(&rpcSkeleton->lock);
return ERR_NONE;
}
static int32_t RpcAcquireHandle(int32_t handle)
{
return ERR_NONE;
}
static int32_t RpcReleaseHandle(int32_t handle)
{
return ERR_NONE;
}
static int32_t RpcInvokerSendRequest(SvcIdentity target, uint32_t code, IpcIo *data, IpcIo *reply,
MessageOption option, uintptr_t *buffer)
{
RPC_LOG_INFO("RPCInvokerSendRequest called");
int32_t result = ERR_NONE;
uint64_t seqNumber = 0;
int userWaitTime = DEFAULT_SEND_WAIT_TIME;
HandleSessionList *sessinoObject = WriteTransaction(BC_TRANSACTION, option, target.handle,
0, code, data, &seqNumber, 0);
if (sessinoObject == NULL) {
return ERR_FAILED;
}
if (option & TF_OP_ASYNC) {
result = SendOrWaitForCompletion(userWaitTime, seqNumber, sessinoObject, NULL, buffer);
} else {
result = SendOrWaitForCompletion(userWaitTime, seqNumber, sessinoObject, reply, buffer);
}
return result;
}
static int32_t RpcFreeBuffer(void *ptr)
{
if (ptr != NULL) {
free(ptr);
}
return ERR_NONE;
}
static int32_t RpcSetMaxWorkThread(int32_t maxThreadNum)
{
return ERR_NONE;
}
static void RpcJoinThread(bool initiative)
{
pthread_t threadId = pthread_self();
ThreadContext *threadContext = GetCurrentThreadContext();
if (threadContext == NULL) {
return;
}
threadContext->stopWorkThread = false;
while (threadContext->stopWorkThread == false) {
AddDataThreadInWait(threadId);
ThreadProcessInfo *processInfo = PopDataInfoFromThread(threadId);
if (processInfo != NULL) {
OnTransaction(processInfo);
free(processInfo->buffer);
free(processInfo);
}
};
}
void RpcStopWorkThread(void)
{
IpcSkeleton *current = GetCurrentSkeleton();
if (current == NULL) {
return;
}
ThreadContext *threadContext = GetCurrentThreadContext();
if (threadContext == NULL) {
return;
}
threadContext->stopWorkThread = true;
}
int32_t RpcSetRegistryObject(void)
{
return ERR_NONE;
}
static int32_t RpcAddDeathRecipient(int32_t handle, void *cookie)
{
return ERR_NONE;
}
static int32_t RpcRemoveDeathRecipient(int32_t handle, void *cookie)
{
return ERR_NONE;
}
RemoteInvoker *GetRpcInvoker(void)
{
if (g_rpcInvoker == NULL) {
g_rpcInvoker = (RemoteInvoker *)malloc(sizeof(RemoteInvoker));
if (g_rpcInvoker != NULL) {
g_rpcInvoker->AcquireHandle = RpcAcquireHandle;
g_rpcInvoker->ReleaseHandle = RpcReleaseHandle;
g_rpcInvoker->SendRequest = RpcInvokerSendRequest;
g_rpcInvoker->FreeBuffer = RpcFreeBuffer;
g_rpcInvoker->SetMaxWorkThread = RpcSetMaxWorkThread;
g_rpcInvoker->JoinThread = RpcJoinThread;
g_rpcInvoker->ExitCurrentThread = RpcStopWorkThread;
g_rpcInvoker->SetRegistryObject = RpcSetRegistryObject;
g_rpcInvoker->AddDeathRecipient = RpcAddDeathRecipient;
g_rpcInvoker->RemoveDeathRecipient = RpcRemoveDeathRecipient;
}
}
return g_rpcInvoker;
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rpc_process_skeleton.h"
#include <stdlib.h>
#include <sys/time.h>
#include <errno.h>
#include "ipc_proxy_inner.h"
#include "ipc_stub_inner.h"
#include "dbinder_types.h"
#include "rpc_trans_callback.h"
#include "rpc_types.h"
#include "rpc_errno.h"
#include "rpc_log.h"
#define USECTONSEC 1000
static RpcSkeleton g_rpcSkeleton = {
.lock = PTHREAD_MUTEX_INITIALIZER,
.isServerCreated = -1
};
static pthread_mutex_t g_rpcSkeletonMutex = PTHREAD_MUTEX_INITIALIZER;
// rpc data cache
static StubObjectList g_stubObjectList = {.mutex = PTHREAD_MUTEX_INITIALIZER};
static ThreadProcessInfoList g_processInfoList = {.mutex = PTHREAD_MUTEX_INITIALIZER};
static SocketThreadLockInfoList g_socketLockInfoList = {.mutex = PTHREAD_MUTEX_INITIALIZER};
static IdleDataThreadsList g_idleDataThreadsList = {.mutex = PTHREAD_MUTEX_INITIALIZER};
static HandleSessionList g_stubSessionList;
static pthread_mutex_t g_stubSessionMutex = PTHREAD_MUTEX_INITIALIZER;
static HandleSessionList g_proxySessionList;
static pthread_mutex_t g_proxySessionMutex = PTHREAD_MUTEX_INITIALIZER;
static HandleToIndexList g_handleToIndexList;
static pthread_mutex_t g_handleToIndexMutex = PTHREAD_MUTEX_INITIALIZER;
static ThreadMessageInfo g_seqNumberToThread;
static pthread_mutex_t g_seqNumberToThreadMutex = PTHREAD_MUTEX_INITIALIZER;
int32_t RpcProcessSkeleton(void)
{
pthread_mutex_lock(&g_rpcSkeletonMutex);
UtilsListInit(&g_stubObjectList.stubObjects);
UtilsListInit(&g_processInfoList.processInfo);
UtilsListInit(&g_socketLockInfoList.socketLockInfo);
UtilsListInit(&g_idleDataThreadsList.idleDataThread);
UtilsListInit(&g_stubSessionList.list);
UtilsListInit(&g_proxySessionList.list);
UtilsListInit(&g_handleToIndexList.list);
UtilsListInit(&g_seqNumberToThread.list);
g_rpcSkeleton.seqNumber = 0;
g_rpcSkeleton.rpcTrans = GetRpcTrans();
pthread_mutex_unlock(&g_rpcSkeletonMutex);
return ERR_NONE;
}
RpcSkeleton *GetCurrentRpcSkeleton(void)
{
return &g_rpcSkeleton;
}
int32_t AddStubByIndex(StubObject *stubObject)
{
pthread_mutex_lock(&g_stubObjectList.mutex);
UtilsListAdd(&g_stubObjectList.stubObjects, &stubObject->list);
pthread_mutex_unlock(&g_stubObjectList.mutex);
return ERR_NONE;
}
StubObject *QueryStubByIndex(uint64_t stubIndex)
{
StubObject *node = NULL;
pthread_mutex_lock(&g_stubObjectList.mutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_stubObjectList.stubObjects, StubObject, list)
{
if (node->stubIndex == stubIndex) {
pthread_mutex_unlock(&g_stubObjectList.mutex);
return node;
}
}
pthread_mutex_unlock(&g_stubObjectList.mutex);
return NULL;
}
static int32_t AttachThreadLockInfo(SocketThreadLockInfo *threadLockInfo)
{
pthread_mutex_lock(&g_socketLockInfoList.mutex);
UtilsListAdd(&g_socketLockInfoList.socketLockInfo, &threadLockInfo->list);
pthread_mutex_unlock(&g_socketLockInfoList.mutex);
return ERR_NONE;
}
static SocketThreadLockInfo *QueryThreadLockInfo(pthread_t threadId)
{
SocketThreadLockInfo *node = NULL;
pthread_mutex_lock(&g_socketLockInfoList.mutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_socketLockInfoList.socketLockInfo, SocketThreadLockInfo, list)
{
if (pthread_equal(node->threadId, threadId) != 0) {
pthread_mutex_unlock(&g_socketLockInfoList.mutex);
return node;
}
}
pthread_mutex_unlock(&g_socketLockInfoList.mutex);
return NULL;
}
static int32_t AddDataThreadToIdle(IdleDataThread *idleDataThread)
{
pthread_mutex_lock(&g_idleDataThreadsList.mutex);
UtilsListAdd(&g_idleDataThreadsList.idleDataThread, &idleDataThread->list);
pthread_mutex_unlock(&g_idleDataThreadsList.mutex);
return ERR_NONE;
}
static void DeleteDataThreadFromIdle(IdleDataThread *idleDataThread)
{
pthread_mutex_lock(&g_idleDataThreadsList.mutex);
UtilsListDelete(&idleDataThread->list);
pthread_mutex_unlock(&g_idleDataThreadsList.mutex);
}
void AddDataThreadInWait(pthread_t threadId)
{
SocketThreadLockInfo *threadLockInfo = QueryThreadLockInfo(threadId);
if (threadLockInfo == NULL) {
threadLockInfo = (SocketThreadLockInfo *)malloc(sizeof(SocketThreadLockInfo));
if (threadLockInfo == NULL) {
RPC_LOG_ERROR("SocketThreadLockInfo malloc failed");
return;
}
threadLockInfo->threadId = threadId;
if (pthread_mutex_init(&threadLockInfo->mutex, NULL) != 0) {
RPC_LOG_ERROR("SocketThreadLockInfo mutex init failed");
free(threadLockInfo);
return;
}
if (pthread_cond_init(&threadLockInfo->condition, NULL) != 0) {
RPC_LOG_ERROR("SocketThreadLockInfo cond init failed");
free(threadLockInfo);
return;
}
if (AttachThreadLockInfo(threadLockInfo) != ERR_NONE) {
free(threadLockInfo);
return;
}
}
pthread_mutex_lock(&threadLockInfo->mutex);
IdleDataThread idleDataThread = {.threadId = threadId};
if (AddDataThreadToIdle(&idleDataThread) != ERR_NONE) {
RPC_LOG_ERROR("AddDataThreadToIdle failed");
pthread_mutex_unlock(&threadLockInfo->mutex);
return;
}
pthread_cond_wait(&threadLockInfo->condition, &threadLockInfo->mutex);
DeleteDataThreadFromIdle(&idleDataThread);
pthread_mutex_unlock(&threadLockInfo->mutex);
}
void WakeUpDataThread(pthread_t threadId)
{
SocketThreadLockInfo *threadLockInfo = QueryThreadLockInfo(threadId);
if (threadLockInfo != NULL) {
pthread_mutex_lock(&threadLockInfo->mutex);
pthread_cond_signal(&threadLockInfo->condition);
pthread_mutex_unlock(&threadLockInfo->mutex);
}
}
IdleDataThread *GetIdleDataThread(void)
{
IdleDataThread *node = NULL;
pthread_mutex_lock(&g_idleDataThreadsList.mutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_idleDataThreadsList.idleDataThread, IdleDataThread, list)
{
pthread_mutex_unlock(&g_idleDataThreadsList.mutex);
return node;
}
pthread_mutex_unlock(&g_idleDataThreadsList.mutex);
return NULL;
}
void AddDataInfoToThread(ThreadProcessInfo *processInfo)
{
pthread_mutex_lock(&g_processInfoList.mutex);
UtilsListAdd(&g_processInfoList.processInfo, &processInfo->list);
pthread_mutex_unlock(&g_processInfoList.mutex);
}
ThreadProcessInfo *PopDataInfoFromThread(pthread_t threadId)
{
ThreadProcessInfo *node = NULL;
pthread_mutex_lock(&g_processInfoList.mutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_processInfoList.processInfo, ThreadProcessInfo, list)
{
if (pthread_equal(node->threadId, threadId) != 0) {
UtilsListDelete(&node->list);
pthread_mutex_unlock(&g_processInfoList.mutex);
return node;
}
}
pthread_mutex_unlock(&g_processInfoList.mutex);
return NULL;
}
uint32_t ConvertChannelID2Int(int64_t databusChannelId)
{
if (databusChannelId < 0) {
return 0;
}
uint32_t channelType = (uint32_t)((databusChannelId >> 8) & 0X00000000FF000000ULL);
uint32_t channelID = (uint32_t)(databusChannelId & 0X0000000000FFFFFFULL);
return (channelType | channelID);
}
int32_t AttachStubSession(HandleSessionList *handleSession)
{
pthread_mutex_lock(&g_stubSessionMutex);
UtilsListAdd(&g_stubSessionList.list, &handleSession->list);
pthread_mutex_unlock(&g_stubSessionMutex);
return ERR_NONE;
}
void DetachStubSession(HandleSessionList *handleSession)
{
pthread_mutex_lock(&g_stubSessionMutex);
UtilsListDelete(&handleSession->list);
pthread_mutex_unlock(&g_stubSessionMutex);
}
HandleSessionList *QueryStubSession(uint32_t handle)
{
HandleSessionList *node = NULL;
pthread_mutex_lock(&g_stubSessionMutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_stubSessionList.list, HandleSessionList, list)
{
if (node->handle == handle) {
pthread_mutex_unlock(&g_stubSessionMutex);
return node;
}
}
pthread_mutex_unlock(&g_stubSessionMutex);
return NULL;
}
int32_t AttachProxySession(HandleSessionList *handleSession)
{
pthread_mutex_lock(&g_proxySessionMutex);
UtilsListAdd(&g_proxySessionList.list, &handleSession->list);
pthread_mutex_unlock(&g_proxySessionMutex);
return ERR_NONE;
}
void DetachProxySession(HandleSessionList *handleSession)
{
pthread_mutex_lock(&g_proxySessionMutex);
UtilsListDelete(&handleSession->list);
pthread_mutex_unlock(&g_proxySessionMutex);
}
HandleSessionList *QueryProxySession(uint32_t handle)
{
HandleSessionList *node = NULL;
pthread_mutex_lock(&g_proxySessionMutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_proxySessionList.list, HandleSessionList, list)
{
if (node->handle == handle) {
pthread_mutex_unlock(&g_proxySessionMutex);
return node;
}
}
pthread_mutex_unlock(&g_proxySessionMutex);
return NULL;
}
HandleSessionList *QueryProxySessionBySessionId(uint32_t sessionId)
{
HandleSessionList *node = NULL;
pthread_mutex_lock(&g_proxySessionMutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_proxySessionList.list, HandleSessionList, list)
{
if (node->sessionId == sessionId) {
pthread_mutex_unlock(&g_proxySessionMutex);
return node;
}
}
pthread_mutex_unlock(&g_proxySessionMutex);
return NULL;
}
uint64_t ProcessGetSeqNumber()
{
pthread_mutex_lock(&g_rpcSkeleton.lock);
++g_rpcSkeleton.seqNumber; // can be overflow, and seqNumber do not use 0
if (g_rpcSkeleton.seqNumber == 0) {
++g_rpcSkeleton.seqNumber;
}
pthread_mutex_unlock(&g_rpcSkeleton.lock);
return g_rpcSkeleton.seqNumber;
}
int32_t AttachHandleToIndex(HandleToIndexList *handleToIndex)
{
pthread_mutex_lock(&g_handleToIndexMutex);
UtilsListAdd(&g_handleToIndexList.list, &handleToIndex->list);
pthread_mutex_unlock(&g_handleToIndexMutex);
return ERR_NONE;
}
void DetachHandleToIndex(HandleToIndexList *handleToIndex)
{
pthread_mutex_lock(&g_handleToIndexMutex);
UtilsListDelete(&handleToIndex->list);
pthread_mutex_unlock(&g_handleToIndexMutex);
}
HandleToIndexList *QueryHandleToIndex(uint32_t handle)
{
HandleToIndexList *node = NULL;
pthread_mutex_lock(&g_handleToIndexMutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_handleToIndexList.list, HandleToIndexList, list)
{
if (node->handle == handle) {
pthread_mutex_unlock(&g_handleToIndexMutex);
return node;
}
}
pthread_mutex_unlock(&g_handleToIndexMutex);
return NULL;
}
static int32_t AddThreadBySeqNumber(ThreadMessageInfo *messageInfo)
{
pthread_mutex_lock(&g_seqNumberToThreadMutex);
UtilsListAdd(&g_seqNumberToThread.list, &messageInfo->list);
pthread_mutex_unlock(&g_seqNumberToThreadMutex);
return ERR_NONE;
}
int32_t AddSendThreadInWait(uint64_t seqNumber, ThreadMessageInfo *messageInfo, int userWaitTime)
{
if (AddThreadBySeqNumber(messageInfo) != ERR_NONE) {
RPC_LOG_ERROR("add seqNumber = %llu failed", seqNumber);
free(messageInfo);
return ERR_FAILED;
}
SocketThreadLockInfo *threadLockInfo = QueryThreadLockInfo(messageInfo->threadId);
if (threadLockInfo == NULL) {
threadLockInfo = (SocketThreadLockInfo *)malloc(sizeof(SocketThreadLockInfo));
if (threadLockInfo == NULL) {
RPC_LOG_ERROR("threadLockInfo malloc failed");
return ERR_FAILED;
}
pthread_mutex_init(&threadLockInfo->mutex, NULL);
pthread_cond_init(&threadLockInfo->condition, NULL);
threadLockInfo->threadId = messageInfo->threadId;
int32_t ret = AttachThreadLockInfo(threadLockInfo);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("AttachThreadLockInfo fail");
free(threadLockInfo);
return ERR_FAILED;
}
}
pthread_mutex_lock(&threadLockInfo->mutex);
if (userWaitTime < 0) {
pthread_cond_wait(&threadLockInfo->condition, &threadLockInfo->mutex);
} else {
struct timespec waitTime;
struct timeval now;
if (gettimeofday(&now, NULL) != 0) {
RPC_LOG_ERROR("gettimeofday failed");
pthread_mutex_unlock(&threadLockInfo->mutex);
return ERR_FAILED;
}
waitTime.tv_sec = now.tv_sec + DEFAULT_SEND_WAIT_TIME;
waitTime.tv_nsec = now.tv_usec * USECTONSEC;
int ret = pthread_cond_timedwait(&threadLockInfo->condition, &threadLockInfo->mutex, &waitTime);
pthread_mutex_unlock(&threadLockInfo->mutex);
if (ret == ETIMEDOUT) {
RPC_LOG_ERROR("send thread wait for reply timeout");
return ERR_FAILED;
}
}
return ERR_NONE;
}
void EraseThreadBySeqNumber(ThreadMessageInfo *messageInfo)
{
pthread_mutex_lock(&g_seqNumberToThreadMutex);
UtilsListDelete(&messageInfo->list);
pthread_mutex_unlock(&g_seqNumberToThreadMutex);
}
ThreadMessageInfo *QueryThreadBySeqNumber(uint64_t seqNumber)
{
ThreadMessageInfo *node = NULL;
pthread_mutex_lock(&g_seqNumberToThreadMutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_seqNumberToThread.list, ThreadMessageInfo, list)
{
if (node->seqNumber == seqNumber) {
pthread_mutex_unlock(&g_seqNumberToThreadMutex);
return node;
}
}
pthread_mutex_unlock(&g_seqNumberToThreadMutex);
return NULL;
}
void WakeUpThreadBySeqNumber(uint64_t seqNumber, uint32_t handle)
{
ThreadMessageInfo *messageInfo = QueryThreadBySeqNumber(seqNumber);
if (messageInfo == NULL) {
RPC_LOG_ERROR("error! messageInfo is nullptr");
return;
}
if (handle != messageInfo->socketId) {
RPC_LOG_ERROR("error! handle is not equal messageInfo, handle = %d, messageFd = %u", handle,
messageInfo->socketId);
return;
}
if (pthread_equal(messageInfo->threadId, pthread_self()) == 0) {
SocketThreadLockInfo *threadLockInfo = QueryThreadLockInfo(messageInfo->threadId);
if (threadLockInfo != NULL) {
/* wake up this IO thread to process socket stream
* Wake up the client processing thread
*/
pthread_mutex_lock(&threadLockInfo->mutex);
pthread_cond_signal(&threadLockInfo->condition);
pthread_mutex_unlock(&threadLockInfo->mutex);
}
}
}
int32_t RpcOnRemoteRequestInner(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option,
IpcObjectStub *objectStub)
{
int32_t result = ERR_FAILED;
switch (code) {
case INVOKE_LISTEN_THREAD: {
result = InvokerListenThreadStub(code, data, reply, option, objectStub->func);
break;
}
case GET_UIDPID_INFO: {
result = GetPidAndUidInfoStub(code, data, reply, option);
break;
}
case GRANT_DATABUS_NAME: {
result = GrantDataBusNameStub(code, data, reply, option);
break;
}
default:
result = ERR_NOT_RPC;
break;
}
return result;
}
void UpdateProtoIfNeed(int32_t handle)
{
RPC_LOG_INFO("rpc manager update proto, handle %d", handle);
UpdateProto(handle);
}
uint64_t GetNewStubIndex(void)
{
pthread_mutex_lock(&g_rpcSkeleton.lock);
uint64_t stubIndex = ++g_rpcSkeleton.stubIndex;
pthread_mutex_unlock(&g_rpcSkeleton.lock);
return stubIndex;
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rpc_process_skeleton.h"
#include "dbinder_invoker.h"
#include "rpc_errno.h"
int32_t RpcProcessSkeleton(void)
{
return ERR_NONE;
}
RpcSkeleton *GetCurrentRpcSkeleton(void)
{
return NULL;
}
int32_t RpcOnRemoteRequestInner(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option,
IpcObjectStub *objectStub)
{
return ERR_NOT_RPC;
}
void UpdateProtoIfNeed(int32_t handle)
{
return;
}
RemoteInvoker *GetRpcInvoker(void)
{
return NULL;
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rpc_trans_callback.h"
#include "rpc_log.h"
#include "rpc_errno.h"
#include "dbinder_invoker.h"
static int32_t OnConnected(int32_t sessionId, int32_t result)
{
if (sessionId < 0 || result != 0) {
RPC_LOG_ERROR("fail to open session because of wrong channel ID");
return ERR_FAILED;
}
RPC_LOG_INFO("rpc OnConnected callback, receive sessionId: %d", sessionId);
return OnReceiveNewConnection(sessionId);
}
static int32_t OnDisconnected(int32_t sessionId)
{
RPC_LOG_INFO("rpc OnDisconnected callback, receive sessionId: %d", sessionId);
OnDatabusSessionClosed(sessionId);
return ERR_NONE;
}
static int32_t OnRecieved(int32_t sessionId, const void *data, uint32_t len)
{
RPC_LOG_INFO("rpc OnRecieved callback, receive sessionId: %d", sessionId);
OnMessageAvailable(sessionId, data, len);
return ERR_NONE;
}
static TransCallback g_sessionListener = {
.OnConnected = OnConnected,
.OnDisconnected = OnDisconnected,
.OnRecieved = OnRecieved
};
TransCallback *GetRpcTransCallback(void)
{
RPC_LOG_INFO("GetTransCallback rpc");
return &g_sessionListener;
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_RPC_TRANS_H
#define OHOS_RPC_TRANS_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int32_t (*OnConnected)(int32_t sessionId, int32_t result);
int32_t (*OnDisconnected)(int32_t sessionId);
int32_t (*OnRecieved)(int32_t sessionId, const void *data, uint32_t len);
} TransCallback;
typedef struct {
int32_t (*StartListen)(const char *SaSessionName, void *cb);
int32_t (*StopListen)(const char *SaSessionName);
int32_t (*Connect)(const char *SaSessionName, const char *peerDeviceId, void *args);
int32_t (*Disconnect)(int32_t sessionId);
int32_t (*Send)(int32_t sessionId, const void *data, uint32_t len);
} TransInterface;
TransInterface *GetRpcTrans(void);
char *GetLocalDeviceID(void);
#ifdef __cplusplus
}
#endif
#endif // OHOS_RPC_TRANS_H
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rpc_trans.h"
#include <stddef.h>
#if defined(RPC_SOCKET_TRANS)
#include "rpc_socket_trans.h"
#endif
TransInterface *GetRpcTrans(void)
{
#if defined(RPC_SOCKET_TRANS)
return GetSocketTrans();
#endif
return NULL;
}
char *GetLocalDeviceID(void)
{
#if defined(RPC_SOCKET_TRANS)
return GetSocketLocalDeviceID();
#endif
return NULL;
}
\ No newline at end of file
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/lite/config/component/lite_component.gni")
lite_component("rpc_test") {
features = []
if (ohos_kernel_type == "linux") {
features += [
"client:rpc_client",
"server:rpc_server",
"samgr:rpc_samgr",
]
}
}
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/lite/config/component/lite_component.gni")
SUBSYSTEM_DIR = "//foundation/communication/ipc"
IPC_CORE_ROOT = "${SUBSYSTEM_DIR}/ipc/native/c"
executable("rpc_client") {
sources = [ "$SUBSYSTEM_DIR/ipc/test/rpc/client/rpc_client.c" ]
include_dirs = [
"//third_party/bounds_checking_function/include",
"//utils/native/lite/include",
"$IPC_CORE_ROOT/manager/include",
"$IPC_CORE_ROOT/rpc/trans_adapter/include",
"$IPC_CORE_ROOT/rpc/ipc_adapter/include",
"$IPC_CORE_ROOT/rpc/include",
"$IPC_CORE_ROOT/ipc/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/c/dbinder/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/c/ipc/include",
"$SUBSYSTEM_DIR/services/dbinder/c/include",
"//base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
]
ldflags = [ "-lstdc++" ]
deps = [
"${SUBSYSTEM_DIR}/interfaces/innerkits/c/dbinder:dbinder",
"${SUBSYSTEM_DIR}/interfaces/innerkits/c/ipc:rpc_manager",
]
configs -= [ "//build/lite/config:clang_opt" ]
}
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "rpc_log.h"
#include "rpc_errno.h"
#include "rpc_trans.h"
#include "dbinder_service.h"
#include "ipc_skeleton.h"
#include "ipc_process_skeleton.h"
#include "rpc_process_skeleton.h"
#include "serializer.h"
#define IPC_LENGTH 64
#define NUMBER_A 12
#define NUMBER_B 17
enum {
OP_ADD = 1,
OP_SUB = 2,
OP_MULTI = 3,
OP_ADD_SERVICE = 4,
OP_DBINDER_CONNECT = 5,
OP_DBINDER_RECEIVED = 6,
};
enum {
GET_REMOTE_SYSTEM_ABILITY_TRANSACTION = 3,
ADD_REMOTE_SYSTEM_ABILITY_TRANSACTION = 4,
};
static const int32_t g_saID = 16;
static void ServerDead1(void)
{
RPC_LOG_INFO("#### rpc server dead callback11 called");
}
static void RpcClientTestOne(SvcIdentity sid, MessageOption option)
{
IpcIo data2;
uint8_t tmpData2[IPC_LENGTH];
IpcIoInit(&data2, tmpData2, IPC_LENGTH, 0);
WriteInt32(&data2, NUMBER_A);
WriteInt32(&data2, NUMBER_B);
IpcIo reply2;
uintptr_t ptr2 = 0;
int32_t ret = SendRequest(sid, OP_ADD, &data2, &reply2, option, &ptr2);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("SendRequest OP_ADD failed, error = %d", ret);
FreeBuffer((void *)ptr2);
return;
}
int32_t sum;
ReadInt32(&reply2, &sum);
RPC_LOG_INFO("%d + %d = %d", NUMBER_A, NUMBER_B, sum);
FreeBuffer((void *)ptr2);
}
static void RpcClientTestTwo(SvcIdentity sid, MessageOption option)
{
IpcIo data3;
uint8_t tmpData3[IPC_LENGTH];
IpcIoInit(&data3, tmpData3, IPC_LENGTH, 0);
WriteInt32(&data3, NUMBER_A);
WriteInt32(&data3, NUMBER_B);
IpcIo reply3;
uintptr_t ptr3 = 0;
int32_t ret = SendRequest(sid, OP_MULTI, &data3, &reply3, option, &ptr3);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("SendRequest OP_MULTI failed, error = %d", ret);
FreeBuffer((void *)ptr3);
return;
}
int32_t mutil;
ReadInt32(&reply3, &mutil);
RPC_LOG_INFO("%d * %d = %d", NUMBER_A, NUMBER_B, mutil);
FreeBuffer((void *)ptr3);
}
int main(int argc, char *argv[])
{
RPC_LOG_INFO("Enter System Ability Client .... ");
if (argc == 1) {
RPC_LOG_INFO("input deviceid please");
return -1;
}
RPC_LOG_INFO("argv 1 is %s", argv[1]);
if (strcmp(argv[1], "deviceId") == 0) {
RPC_LOG_INFO("local deviceId is %s", GetLocalDeviceID());
return 0;
}
const char *deviceId = argv[1];
IpcIo data1;
uint8_t tmpData1[IPC_LENGTH];
IpcIoInit(&data1, tmpData1, IPC_LENGTH, 0);
WriteInt32(&data1, g_saID);
WriteString(&data1, deviceId);
IpcIo reply1;
MessageOption option = TF_OP_SYNC;
SvcIdentity target = {
.handle = 0
};
RPC_LOG_INFO("get remote system ability from samgr.");
uintptr_t ptr = 0;
int32_t ret = SendRequest(target, GET_REMOTE_SYSTEM_ABILITY_TRANSACTION, &data1, &reply1, option, &ptr);
SvcIdentity sid;
ReadRemoteObject(&reply1, &sid);
RPC_LOG_INFO("call server add func server handle = %d.", sid.handle);
FreeBuffer((void *)ptr);
uint32_t cbId1 = 0;
ret = AddDeathRecipient(sid, ServerDead1, NULL, &cbId1);
RPC_LOG_INFO("add death callback cbid1 = %d", ret);
RpcClientTestOne(sid, option);
RpcClientTestTwo(sid, option);
JoinWorkThread();
return 0;
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_RPC_RPC_MINI_SAMGR_H
#define OHOS_RPC_RPC_MINI_SAMGR_H
#include "serializer.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void RpcStartSamgr(void);
int32_t AddSystemAbility(int32_t saId, SvcIdentity *sid);
SvcIdentity *GetSystemAbilityById(int32_t systemAbility);
int32_t AddRemoteSystemAbility(int32_t saId, SvcIdentity *sid);
int32_t GetRemoteSystemAbility(int32_t saId, const char* deviceId, SvcIdentity *sid);
#ifdef __cplusplus
}
#endif
#endif // OHOS_RPC_RPC_MINI_SAMGR_H
\ No newline at end of file
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/lite/config/component/lite_component.gni")
SUBSYSTEM_DIR = "//foundation/communication/ipc"
IPC_CORE_ROOT = "${SUBSYSTEM_DIR}/ipc/native/c"
executable("rpc_samgr") {
sources = [ "$SUBSYSTEM_DIR/ipc/test/rpc/samgr/rpc_samgr.c" ]
include_dirs = [
"//third_party/bounds_checking_function/include",
"//utils/native/lite/include",
"$IPC_CORE_ROOT/manager/include",
"$IPC_CORE_ROOT/ipc/include",
"//foundation/communication/ipc/services/dbinder/c/include",
"//base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
"$SUBSYSTEM_DIR/interfaces/innerkits/c/dbinder/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/c/ipc/include",
"$SUBSYSTEM_DIR/services/dbinder/c/include",
]
ldflags = [
"-lstdc++",
"-lpthread",
]
deps = [
"${SUBSYSTEM_DIR}/interfaces/innerkits/c/dbinder:dbinder",
"${SUBSYSTEM_DIR}/interfaces/innerkits/c/ipc:rpc_manager",
]
configs -= [ "//build/lite/config:clang_opt" ]
}
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rpc_mini_samgr.h"
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "rpc_log.h"
#include "rpc_errno.h"
#include "ipc_skeleton.h"
#include "serializer.h"
#include "utils_list.h"
#include "securec.h"
#include "dbinder_service.h"
typedef struct {
UTILS_DL_LIST list;
int32_t saId;
SvcIdentity *sid;
} SvcInfo;
static UTILS_DL_LIST *g_saList = NULL;
static pthread_mutex_t g_handleMutex = PTHREAD_MUTEX_INITIALIZER;
static int32_t g_handle = 0;
int32_t AddSystemAbility(int32_t saId, SvcIdentity *sid)
{
RPC_LOG_INFO("AddSystemAbility called.... handle = %d", sid->handle);
RPC_LOG_INFO("AddSystemAbility called.... cookie = %u, said = %d", sid->cookie, saId);
if (g_saList == NULL) {
return ERR_FAILED;
}
SvcInfo* node = (SvcInfo *)calloc(1, sizeof(SvcInfo));
if (node == NULL) {
RPC_LOG_ERROR("AddSystemAbility node calloc failed");
return ERR_FAILED;
}
node->saId = saId;
node->sid = (SvcIdentity *)calloc(1, sizeof(SvcIdentity));
if (memcpy_s(node->sid, sizeof(SvcIdentity), sid, sizeof(SvcIdentity)) != EOK) {
RPC_LOG_INFO("AddSystemAbility memcpy failed");
free(node->sid);
free(node);
return ERR_FAILED;
}
pthread_mutex_lock(&g_handleMutex);
node->sid->handle = ++g_handle;
pthread_mutex_unlock(&g_handleMutex);
UtilsListAdd(g_saList, &node->list);
return ERR_NONE;
}
SvcIdentity *GetSystemAbilityById(int32_t systemAbility)
{
SvcInfo* node = NULL;
SvcInfo* next = NULL;
UTILS_DL_LIST_FOR_EACH_ENTRY_SAFE(node, next, g_saList, SvcInfo, list)
{
RPC_LOG_INFO("GetSystemAbilityById %d", node->saId);
if (node->saId == systemAbility) {
return node->sid;
}
}
return NULL;
}
int32_t AddRemoteSystemAbility(int32_t saId, SvcIdentity *sid)
{
if (AddSystemAbility(saId, sid) == ERR_FAILED) {
RPC_LOG_ERROR("AddSystemAbility failed");
return ERR_FAILED;
}
const char *name = "16";
if (RegisterRemoteProxy(name, strlen(name), saId) != ERR_NONE) {
RPC_LOG_ERROR("RegisterRemoteProxy failed");
return ERR_FAILED;
}
return ERR_NONE;
}
int32_t GetRemoteSystemAbility(int32_t saId, const char* deviceId, SvcIdentity *sid)
{
RPC_LOG_INFO("GetRemoteSystemAbility start");
const char *name = "16";
uint32_t idLen = (uint32_t)strlen(deviceId);
int32_t ret = MakeRemoteBinder(name, 2, deviceId, idLen, (uintptr_t)saId, 0, (void *)sid);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("MakeRemoteBinder failed");
}
return ret;
}
void RpcStartSamgr(void)
{
RPC_LOG_INFO("RpcStartSamgr start");
g_saList = (UTILS_DL_LIST *)calloc(1, sizeof(UTILS_DL_LIST));
UtilsListInit(g_saList);
StartDBinderService();
RPC_LOG_INFO("StartDBinderService finished");
return;
}
\ No newline at end of file
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include <string.h>
#include "rpc_log.h"
#include "rpc_errno.h"
#include "ipc_skeleton.h"
#include "serializer.h"
#include "utils_list.h"
#include "dbinder_service.h"
typedef struct {
UTILS_DL_LIST list;
int32_t saId;
SvcIdentity *sid;
} SvcInfo;
static UTILS_DL_LIST *g_saList = NULL;
enum {
ADD_SYSTEM_ABILITY_TRANSACTION = 2,
GET_REMOTE_SYSTEM_ABILITY_TRANSACTION = 3,
ADD_REMOTE_SYSTEM_ABILITY_TRANSACTION = 4,
};
int32_t AddSystemAbility(int32_t saId, SvcIdentity *sid)
{
RPC_LOG_INFO("AddSystemAbility called.... handle = %d", sid->handle);
RPC_LOG_INFO("AddSystemAbility called.... cookie = %u", sid->cookie);
if (g_saList == NULL) {
return ERR_FAILED;
}
SvcInfo* node = (SvcInfo *)calloc(1, sizeof(SvcInfo));
if (node == NULL) {
RPC_LOG_ERROR("AddSystemAbility node calloc failed");
return ERR_FAILED;
}
node->saId = saId;
node->sid = sid;
UtilsListAdd(g_saList, &node->list);
return ERR_NONE;
}
int32_t GetSystemAbility(int32_t saId, const char* deviceId, SvcIdentity *sid)
{
SvcInfo* node = NULL;
SvcInfo* next = NULL;
UTILS_DL_LIST_FOR_EACH_ENTRY_SAFE(node, next, g_saList, SvcInfo, list)
{
if (node->saId == saId) {
sid->handle = node->sid->handle;
sid->token = node->sid->token;
sid->cookie = node->sid->cookie;
RPC_LOG_INFO("find sa, said = %d, handle = %d, cookie = %u", saId, sid->handle, sid->cookie);
return ERR_NONE;
}
}
return ERR_FAILED;
}
int32_t AddRemoteSystemAbility(int32_t saId, SvcIdentity *sid)
{
if (AddSystemAbility(saId, sid) == ERR_FAILED) {
RPC_LOG_ERROR("AddSystemAbility failed");
return ERR_FAILED;
}
const char *name = "16";
if (RegisterRemoteProxy(name, strlen(name), saId) != ERR_NONE) {
RPC_LOG_ERROR("RegisterRemoteProxy failed");
return ERR_FAILED;
}
return ERR_NONE;
}
int32_t GetRemoteSystemAbility(IpcIo *data, SvcIdentity *sid)
{
int32_t saId;
ReadInt32(data, &saId);
size_t len;
const char *deviceId = (const char *)ReadString(data, &len);
const char *name = "16";
uint32_t idLen = (uint32_t)strlen(deviceId);
RPC_LOG_INFO("GetRemoteSystemAbility start");
int32_t ret = MakeRemoteBinder(name, 2, deviceId, idLen, (uintptr_t)saId, 0, (void *)sid);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("MakeRemoteBinder failed");
}
RPC_LOG_INFO("GetRemoteSystemAbility handle=%d, cookie=%u", sid->handle, sid->cookie);
return ret;
}
int32_t RemoteRequest(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option)
{
int32_t result = ERR_NONE;
RPC_LOG_INFO("OnRemoteRequest called.... code = %d", code);
switch (code) {
case GET_SYSTEM_ABILITY_TRANSACTION: {
int32_t saId;
ReadInt32(data, &saId);
SvcIdentity sid;
result = GetSystemAbility(saId, "", &sid);
WriteRemoteObject(reply, &sid);
break;
}
case ADD_SYSTEM_ABILITY_TRANSACTION: {
int32_t saId;
ReadInt32(data, &saId);
SvcIdentity *sid = (SvcIdentity *)malloc(sizeof(SvcIdentity));
if (sid == NULL) {
result = ERR_FAILED;
break;
}
ReadRemoteObject(data, sid);
result = AddSystemAbility(saId, sid);
break;
}
case GET_REMOTE_SYSTEM_ABILITY_TRANSACTION: {
SvcIdentity sid;
result = GetRemoteSystemAbility(data, &sid);
WriteRemoteObject(reply, &sid);
break;
}
case ADD_REMOTE_SYSTEM_ABILITY_TRANSACTION: {
int32_t saId;
ReadInt32(data, &saId);
SvcIdentity *sid = (SvcIdentity *)malloc(sizeof(SvcIdentity));
if (sid == NULL) {
result = ERR_FAILED;
break;
}
ReadRemoteObject(data, sid);
result = AddRemoteSystemAbility(saId, sid);
break;
}
default:
RPC_LOG_ERROR("unknown code %d", code);
break;
}
return result;
}
int main(int argc, char *argv[])
{
RPC_LOG_INFO("Enter System Ability Manager .... ");
g_saList = (UTILS_DL_LIST *)calloc(1, sizeof(UTILS_DL_LIST));
UtilsListInit(g_saList);
IpcObjectStub objectStub = {
.func = RemoteRequest,
.isRemote = false
};
SvcIdentity target = {
.handle = 0,
.cookie = (uintptr_t)&objectStub
};
if (SetContextObject(target) != ERR_NONE) {
RPC_LOG_ERROR("SAMGR register samgr failed");
return -1;
}
StartDBinderService();
RPC_LOG_INFO("StartDBinderService finished");
JoinWorkThread();
return -1;
}
\ No newline at end of file
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/lite/config/component/lite_component.gni")
SUBSYSTEM_DIR = "//foundation/communication/ipc"
IPC_CORE_ROOT = "${SUBSYSTEM_DIR}/ipc/native/c"
executable("rpc_server") {
sources = [ "$SUBSYSTEM_DIR/ipc/test/rpc/server/rpc_server.c" ]
include_dirs = [
"//third_party/bounds_checking_function/include",
"//utils/native/lite/include",
"$IPC_CORE_ROOT/ipc/include",
"$IPC_CORE_ROOT/manager/include",
"$IPC_CORE_ROOT/rpc/include",
"$IPC_CORE_ROOT/rpc/ipc_adapter/include",
"$IPC_CORE_ROOT/rpc/trans_adapter/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/c/dbinder/include",
"$SUBSYSTEM_DIR/interfaces/innerkits/c/ipc/include",
"$SUBSYSTEM_DIR/services/dbinder/c/include",
"//base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
]
ldflags = [ "-lstdc++" ]
deps = [
"${SUBSYSTEM_DIR}/interfaces/innerkits/c/dbinder:dbinder",
"${SUBSYSTEM_DIR}/interfaces/innerkits/c/ipc:rpc_manager",
]
configs -= [ "//build/lite/config:clang_opt" ]
}
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include <securec.h>
#include "rpc_log.h"
#include "rpc_errno.h"
#include "ipc_skeleton.h"
#include "serializer.h"
#include "dbinder_invoker.h"
#include "dbinder_types.h"
enum {
OP_ADD = 1,
OP_SUB = 2,
OP_MULTI = 3,
OP_ADD_SERVICE = 4,
};
enum {
ADD_SYSTEM_ABILITY_TRANSACTION = 2,
GET_REMOTE_SYSTEM_ABILITY_TRANSACTION = 3,
ADD_REMOTE_SYSTEM_ABILITY_TRANSACTION = 4,
};
static const int32_t g_saID = 16;
static const uint32_t IPC_LENGTH = 128;
int32_t RemoteRequestOne(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option)
{
int32_t result = ERR_NONE;
RPC_LOG_INFO("server OnRemoteRequestOne called....");
switch (code) {
case OP_ADD: {
int32_t a;
ReadInt32(data, &a);
int32_t b;
ReadInt32(data, &b);
RPC_LOG_INFO("RemoteRequestOne add called a = %d, b = %d", a, b);
WriteInt32(reply, a + b);
break;
}
case OP_SUB: {
int32_t a;
ReadInt32(data, &a);
int32_t b;
ReadInt32(data, &b);
RPC_LOG_INFO("RemoteRequestOne sub called a = %d, b = %d", a, b);
WriteInt32(reply, a - b);
break;
}
case OP_MULTI: {
int32_t a;
ReadInt32(data, &a);
int32_t b;
ReadInt32(data, &b);
RPC_LOG_INFO("RemoteRequestOne mulit called a = %d, b = %d", a, b);
WriteInt32(reply, a * b);
break;
}
default:
RPC_LOG_ERROR("unknown code %d", code);
break;
}
return result;
}
int main(int argc, char *argv[])
{
RPC_LOG_INFO("Enter System Ability Server .... ");
IpcObjectStub objectStubOne = {
.func = RemoteRequestOne,
.isRemote = false
};
SvcIdentity svcOne = {
.handle = -1,
.token = (uintptr_t)&objectStubOne,
.cookie = (uintptr_t)&objectStubOne
};
IpcIo data;
uint8_t tmpData1[IPC_LENGTH];
IpcIoInit(&data, tmpData1, IPC_LENGTH, 1);
WriteInt32(&data, g_saID);
WriteRemoteObject(&data, &svcOne);
IpcIo reply;
MessageOption option = TF_OP_SYNC;
SvcIdentity target = {
.handle = 0
};
RPC_LOG_INFO("====== add ability one to samgr ======");
uintptr_t ptr = 0;
SendRequest(target, ADD_REMOTE_SYSTEM_ABILITY_TRANSACTION, &data, &reply, option, &ptr);
int32_t ret;
ReadInt32(&reply, &ret);
RPC_LOG_INFO("send request one ret = %d .... ", ret);
FreeBuffer((void *)ptr);
JoinWorkThread();
return -1;
}
\ No newline at end of file
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_RPC_SOCKET_TRANS_H
#define OHOS_RPC_SOCKET_TRANS_H
#include <stdint.h>
#include "utils_list.h"
#include "rpc_trans.h"
#ifdef __cplusplus
extern "C" {
#endif
#define DEFAULT_BACKLOG 4
#define DEFAULT_PACKET_SIZE 1024
#define DEFAULT_HASH_OFFSET 3
static char const *SOCKET_SERVER_ADDR = "0.0.0.0";
static char const *DEFAULT_NET_INTERFACE = "eth0";
static const uint16_t DEFAULT_HASH_SEED = 5381;
static const uint16_t DEFAULT_PORT_MIN = 10000;
TransInterface *GetSocketTrans(void);
char *GetSocketLocalDeviceID(void);
#ifdef __cplusplus
}
#endif
#endif // OHOS_RPC_SOCKET_TRANS_H
\ No newline at end of file
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rpc_socket_trans.h"
#include <string.h>
#include <stddef.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include "lwip/def.h"
#include "lwip/inet.h"
#include "lwip/netif.h"
#include "lwip/netifapi.h"
#include "utils_list.h"
#include "securec.h"
#include "rpc_errno.h"
#include "rpc_log.h"
#define DEVICEID_LENGTH 64
#define SERVICENAME_LENGTH 200
#define DEFAULT_LOCAL_DEVICEID "192.168.1.74"
#define DEFAULT_THREAD_STACK_SIZE 8192
typedef struct {
UTILS_DL_LIST list;
char *saSessionName;
char *deviceId;
TransCallback cb;
} SocketNode;
typedef struct {
UTILS_DL_LIST list;
pthread_mutex_t mutex;
} SocketNodeList;
static SocketNodeList g_socketNodeList = {.mutex = PTHREAD_MUTEX_INITIALIZER};
static int32_t g_init = -1;
static int32_t g_serverCreated = -1;
static TransCallback g_callback;
static char *g_localDeviceId = NULL;
static uint16_t Hash(const char *name)
{
if (name == NULL) {
return 0;
}
RPC_LOG_INFO("Hash called %s", name);
sleep(1);
uint16_t hash = DEFAULT_HASH_SEED;
uint16_t c;
while (c = *name++)
hash = ((hash << DEFAULT_HASH_OFFSET) + hash) + c;
return hash % DEFAULT_PORT_MIN + DEFAULT_PORT_MIN;
}
static int32_t BindLocalIP(int fd, const char *localIP, uint16_t port, struct sockaddr_in *addr)
{
if (memset_s(addr, sizeof(struct sockaddr_in), 0, sizeof(*addr)) != EOK) {
RPC_LOG_ERROR("sockaddr_in memset failed");
return ERR_FAILED;
}
addr->sin_family = AF_INET;
int rc = inet_pton(AF_INET, localIP, &addr->sin_addr);
if (rc <= 0) {
RPC_LOG_ERROR("inet_pton rc=%d", rc);
return ERR_FAILED;
}
addr->sin_port = lwip_htons(port);
errno = 0;
rc = bind(fd, (struct sockaddr *)addr, sizeof(*addr));
if (rc < 0) {
RPC_LOG_ERROR("bind fd=%d,rc=%d", fd, rc);
return ERR_FAILED;
}
return ERR_NONE;
}
static void TcpShutDown(int fd)
{
if (fd >= 0) {
shutdown(fd, SHUT_RDWR);
close(fd);
}
}
static void *HandleAccept(void *args)
{
if (args == NULL) {
return NULL;
}
int32_t clientFd = *(int32_t *)args;
int32_t ret;
if (g_callback.OnConnected != NULL) {
ret = g_callback.OnConnected(clientFd, 0);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("g_callback OnConnected failed");
return NULL;
}
}
char buf[DEFAULT_PACKET_SIZE];
if (g_callback.OnRecieved != NULL) {
for (;;) {
ssize_t readLen = read(clientFd, buf, DEFAULT_PACKET_SIZE);
if (readLen == 0) {
RPC_LOG_INFO("client socket close");
g_callback.OnDisconnected(clientFd);
TcpShutDown(clientFd);
return NULL;
}
if (readLen < 0) {
RPC_LOG_ERROR("socket read error=%d", readLen);
TcpShutDown(clientFd);
return NULL;
}
ret = g_callback.OnRecieved(clientFd, (void *)buf, (uint32_t)readLen);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("g_callback OnRecieved failed");
return NULL;
}
}
}
return NULL;
}
static void *OpenTcpServerSocket(void *args)
{
printf("OpenTcpServerSocket %d\n", strlen((char *)args));
sleep(1);
if (args == NULL) {
return NULL;
}
char *ip = (char *)SOCKET_SERVER_ADDR;
uint16_t port = Hash((char *)args);
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
RPC_LOG_ERROR("fd=%d", fd);
return NULL;
}
struct sockaddr_in addr;
int32_t ret = BindLocalIP(fd, ip, port, &addr);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("BindLocalIP ret=%d", ret);
TcpShutDown(fd);
return NULL;
}
if (listen(fd, DEFAULT_BACKLOG) != 0) {
RPC_LOG_ERROR("listen failed");
TcpShutDown(fd);
return NULL;
}
g_serverCreated = 0;
for (;;) {
socklen_t len = sizeof(addr);
int32_t clientFd = accept(fd, (struct sockaddr *)&addr, &len);
RPC_LOG_INFO("accept get fd %d", clientFd);
pthread_t threadId;
pthread_attr_t threadAttr;
ret = pthread_attr_init(&threadAttr);
if (ret != 0) {
RPC_LOG_ERROR("pthread_attr_init failed %d", ret);
return ERR_FAILED;
}
if (pthread_attr_setstacksize(&threadAttr, DEFAULT_THREAD_STACK_SIZE) != 0) {
RPC_LOG_ERROR("pthread_attr_setstacksize failed");
return ERR_FAILED;
}
ret = pthread_create(&threadId, &threadAttr, HandleAccept, (void *)&clientFd);
if (ret != 0) {
RPC_LOG_ERROR("pthread_create failed %d", ret);
return ERR_FAILED;
}
pthread_detach(threadId);
}
return NULL;
}
static int32_t StartListen(const char *SaSessionName, void *cb)
{
printf("StartListen called %s, %d\n", SaSessionName, strlen(SaSessionName));
if (SaSessionName == NULL) {
RPC_LOG_ERROR("SaSessionName is null");
return ERR_FAILED;
}
if (memcpy_s(&g_callback, sizeof(TransCallback), cb, sizeof(TransCallback)) != EOK) {
RPC_LOG_ERROR("g_callback memcpy_s failed");
return ERR_FAILED;
}
pthread_t threadId;
pthread_attr_t threadAttr;
int ret = pthread_attr_init(&threadAttr);
if (ret != 0) {
RPC_LOG_ERROR("pthread_attr_init failed %d", ret);
return ERR_FAILED;
}
if (pthread_attr_setstacksize(&threadAttr, DEFAULT_THREAD_STACK_SIZE) != 0) {
RPC_LOG_ERROR("pthread_attr_setstacksize failed");
return ERR_FAILED;
}
ret = pthread_create(&threadId, &threadAttr, OpenTcpServerSocket, (void *)SaSessionName);
if (ret != 0) {
RPC_LOG_ERROR("pthread_create failed %d", ret);
return ERR_FAILED;
}
pthread_detach(threadId);
return ERR_NONE;
}
static int32_t StopListen(const char *SaSessionName)
{
return ERR_NONE;
}
static void *HandleSendReply(void *args)
{
if (args == NULL) {
RPC_LOG_ERROR("HandleSendReply args is null");
return NULL;
}
int32_t fd = *(int32_t *)args;
free(args);
char buf[DEFAULT_PACKET_SIZE];
if (g_callback.OnRecieved != NULL) {
for (;;) {
ssize_t readLen = read(fd, buf, DEFAULT_PACKET_SIZE);
if (readLen == 0) {
RPC_LOG_INFO("HandleSendReply received len %d", readLen);
g_callback.OnDisconnected(fd);
TcpShutDown(fd);
return NULL;
}
if (readLen < 0) {
RPC_LOG_ERROR("HandleSendReply received len %d", readLen);
TcpShutDown(fd);
return NULL;
}
g_callback.OnRecieved(fd, buf, readLen);
}
}
return NULL;
}
static int32_t Connect(const char *SaSessionName, const char *peerDeviceId, void *args)
{
if (SaSessionName == NULL) {
RPC_LOG_INFO("SaSessionName is null");
return ERR_FAILED;
}
uint16_t port = Hash(SaSessionName);
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
RPC_LOG_ERROR("%s:%d:fd=%d", __func__, __LINE__, fd);
return ERR_FAILED;
}
struct sockaddr_in addr;
if (memset_s(&addr, sizeof(addr), 0, sizeof(addr)) != EOK) {
RPC_LOG_ERROR("memset failed");
}
addr.sin_family = AF_INET;
inet_pton(AF_INET, peerDeviceId, &addr.sin_addr);
addr.sin_port = lwip_htons(port);
errno = 0;
int rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
if ((rc == -1) && (errno != EINPROGRESS)) {
RPC_LOG_ERROR("fd=%d,connect rc=%d, errno=%d", fd, rc, errno);
TcpShutDown(fd);
return ERR_FAILED;
}
int32_t *sessionId = (int32_t *)malloc(sizeof(int32_t));
if (sessionId == NULL) {
return ERR_FAILED;
}
*sessionId = fd;
pthread_t threadId;
pthread_attr_t threadAttr;
int ret = pthread_attr_init(&threadAttr);
if (ret != 0) {
RPC_LOG_ERROR("pthread_attr_init failed %d", ret);
return ERR_FAILED;
}
if (pthread_attr_setstacksize(&threadAttr, DEFAULT_THREAD_STACK_SIZE) != 0) {
RPC_LOG_ERROR("pthread_attr_setstacksize failed");
return ERR_FAILED;
}
ret = pthread_create(&threadId, &threadAttr, HandleSendReply, (void *)sessionId);
if (ret != 0) {
RPC_LOG_ERROR("pthread_create failed %d", ret);
return ERR_FAILED;
}
pthread_detach(threadId);
return fd;
}
static int32_t Disconnect(int32_t sessionId)
{
return ERR_NONE;
}
static int32_t Send(int32_t sessionId, const void *data, uint32_t len)
{
if (sessionId < 0 || data == NULL || len <= 0) {
RPC_LOG_ERROR("send invail params");
return ERR_FAILED;
}
ssize_t ret = write(sessionId, data, len);
if (ret < 0) {
RPC_LOG_ERROR("send error=%d", ret);
return ERR_FAILED;
}
return ERR_NONE;
}
static TransInterface g_socketTrans = {
.StartListen = StartListen,
.StopListen = StopListen,
.Connect = Connect,
.Disconnect = Disconnect,
.Send = Send
};
TransInterface *GetSocketTrans(void)
{
if (g_init == -1) {
pthread_mutex_lock(&g_socketNodeList.mutex);
UtilsListInit(&g_socketNodeList.list);
g_init = 0;
printf("g_socketTrans %x\n", g_socketTrans.StartListen);
pthread_mutex_unlock(&g_socketNodeList.mutex);
}
return &g_socketTrans;
}
char *GetSocketLocalDeviceID(void)
{
extern struct netif if_wifi;
uint32_t ip = ((ip4_addr_t *)&if_wifi.ip_addr)->addr;
char *localDeviceId = inet_ntoa(ip);
if (localDeviceId == NULL) {
RPC_LOG_ERROR("GetSocketLocalDeviceID inet_ntoa return null");
return NULL;
}
RPC_LOG_INFO("GetSocketLocalDeviceID %s\n", localDeviceId);
return localDeviceId;
}
\ No newline at end of file
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rpc_socket_trans.h"
#include <string.h>
#include <stddef.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include "utils_list.h"
#include "securec.h"
#include "rpc_errno.h"
#include "rpc_log.h"
#define DEVICEID_LENGTH 64
#define SERVICENAME_LENGTH 200
typedef struct {
UTILS_DL_LIST list;
char *saSessionName;
char *deviceId;
TransCallback cb;
} SocketNode;
typedef struct {
UTILS_DL_LIST list;
pthread_mutex_t mutex;
} SocketNodeList;
static SocketNodeList g_socketNodeList = {.mutex = PTHREAD_MUTEX_INITIALIZER};
static int32_t g_init = -1;
static int32_t g_serverCreated = -1;
static TransCallback g_callback;
static char *g_localDeviceId = NULL;
static uint16_t Hash(const char *name)
{
if (name == NULL) {
return 0;
}
uint16_t hash = DEFAULT_HASH_SEED;
uint16_t c;
while (c = *name++)
hash = ((hash << DEFAULT_HASH_OFFSET) + hash) + c;
return hash % DEFAULT_PORT_MIN + DEFAULT_PORT_MIN;
}
static int32_t BindLocalIP(int fd, const char *localIP, uint16_t port, struct sockaddr_in *addr)
{
if (memset_s(addr, sizeof(struct sockaddr_in), 0, sizeof(*addr)) != EOK) {
RPC_LOG_ERROR("sockaddr_in memset failed");
return ERR_FAILED;
}
addr->sin_family = AF_INET;
int rc = inet_pton(AF_INET, localIP, &addr->sin_addr);
if (rc <= 0) {
RPC_LOG_ERROR("inet_pton rc=%d", rc);
return ERR_FAILED;
}
addr->sin_port = htons(port);
errno = 0;
rc = bind(fd, (struct sockaddr *)addr, sizeof(*addr));
if (rc < 0) {
RPC_LOG_ERROR("bind fd=%d,rc=%d", fd, rc);
return ERR_FAILED;
}
return ERR_NONE;
}
static void TcpShutDown(int fd)
{
if (fd >= 0) {
shutdown(fd, SHUT_RDWR);
close(fd);
}
}
static void HandleAccept(void *args)
{
if (args == NULL) {
return;
}
int32_t clientFd = *(int32_t *)args;
int32_t ret;
if (g_callback.OnConnected != NULL) {
ret = g_callback.OnConnected(clientFd, 0);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("g_callback OnConnected failed");
return;
}
}
char buf[DEFAULT_PACKET_SIZE];
if (g_callback.OnRecieved != NULL) {
for (;;) {
ssize_t readLen = read(clientFd, buf, DEFAULT_PACKET_SIZE);
if (readLen == 0) {
RPC_LOG_INFO("client socket close");
g_callback.OnDisconnected(clientFd);
TcpShutDown(clientFd);
return;
}
if (readLen < 0) {
RPC_LOG_ERROR("socket read error=%d", readLen);
TcpShutDown(clientFd);
return;
}
ret = g_callback.OnRecieved(clientFd, (void *)buf, (uint32_t)readLen);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("g_callback OnRecieved failed");
return;
}
}
}
}
static void OpenTcpServerSocket(void *args)
{
if (args == NULL) {
return;
}
char *ip = (char *)SOCKET_SERVER_ADDR;
uint16_t port = Hash((char *)args);
errno = 0;
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
RPC_LOG_ERROR("fd=%d", fd);
return;
}
struct sockaddr_in addr;
int32_t ret = BindLocalIP(fd, ip, port, &addr);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("BindLocalIP ret=%d", ret);
TcpShutDown(fd);
return;
}
if (listen(fd, DEFAULT_BACKLOG) != 0) {
RPC_LOG_ERROR("listen failed");
TcpShutDown(fd);
return;
}
g_serverCreated = 0;
for (;;) {
socklen_t len = sizeof(addr);
int32_t clientFd = accept(fd, (struct sockaddr *)&addr, &len);
pthread_t threadId;
pthread_create(&threadId, NULL, HandleAccept, (void *)&clientFd);
pthread_detach(threadId);
}
}
static int32_t StartListen(const char *SaSessionName, void *cb)
{
if (g_serverCreated == 0) {
return ERR_NONE;
}
RPC_LOG_INFO("StartListen called");
if (SaSessionName == NULL) {
RPC_LOG_ERROR("SaSessionName is null");
return ERR_FAILED;
}
if (memcpy_s(&g_callback, sizeof(TransCallback), cb, sizeof(TransCallback)) != EOK) {
RPC_LOG_ERROR("g_callback memcpy_s failed");
return ERR_FAILED;
}
pthread_t threadId;
pthread_create(&threadId, NULL, OpenTcpServerSocket, (void *)SaSessionName);
pthread_detach(threadId);
return ERR_NONE;
}
static int32_t StopListen(const char *SaSessionName)
{
return ERR_NONE;
}
static void HandleSendReply(void *args)
{
if (args == NULL) {
RPC_LOG_ERROR("HandleSendReply args is null");
return;
}
int32_t fd = *(int32_t *)args;
free(args);
char buf[DEFAULT_PACKET_SIZE];
if (g_callback.OnRecieved != NULL) {
for (;;) {
ssize_t readLen = read(fd, buf, DEFAULT_PACKET_SIZE);
if (readLen == 0) {
RPC_LOG_INFO("HandleSendReply received len %d", readLen);
g_callback.OnDisconnected(fd);
TcpShutDown(fd);
return;
}
if (readLen < 0) {
RPC_LOG_ERROR("HandleSendReply received len %d", readLen);
TcpShutDown(fd);
return;
}
g_callback.OnRecieved(fd, buf, readLen);
}
}
}
static int32_t Connect(const char *SaSessionName, const char *peerDeviceId, void *args)
{
if (SaSessionName == NULL) {
RPC_LOG_INFO("SaSessionName is null");
return ERR_FAILED;
}
uint16_t port = Hash(SaSessionName);
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
RPC_LOG_ERROR("%s:%d:fd=%d", __func__, __LINE__, fd);
return ERR_FAILED;
}
struct sockaddr_in addr;
if (memset_s(&addr, sizeof(addr), 0, sizeof(addr)) != EOK) {
RPC_LOG_ERROR("memset failed");
}
addr.sin_family = AF_INET;
inet_pton(AF_INET, peerDeviceId, &addr.sin_addr);
addr.sin_port = htons(port);
errno = 0;
int rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
if ((rc == -1) && (errno != EINPROGRESS)) {
RPC_LOG_ERROR("fd=%d,connect rc=%d, errno=%d", fd, rc, errno);
TcpShutDown(fd);
return ERR_FAILED;
}
int32_t *sessionId = (int32_t *)malloc(sizeof(int32_t));
if (sessionId == NULL) {
return ERR_FAILED;
}
*sessionId = fd;
pthread_t threadId;
pthread_create(&threadId, NULL, HandleSendReply, (void *)sessionId);
pthread_detach(threadId);
return fd;
}
static int32_t Disconnect(int32_t sessionId)
{
return ERR_NONE;
}
static int32_t Send(int32_t sessionId, const void *data, uint32_t len)
{
if (sessionId < 0 || data == NULL || len <= 0) {
RPC_LOG_ERROR("send invail params");
return ERR_FAILED;
}
ssize_t ret = write(sessionId, data, len);
if (ret < 0) {
RPC_LOG_ERROR("send error=%d", ret);
return ERR_FAILED;
}
return ERR_NONE;
}
static TransInterface g_socketTrans = {
.StartListen = StartListen,
.StopListen = StopListen,
.Connect = Connect,
.Disconnect = Disconnect,
.Send = Send
};
TransInterface *GetSocketTrans(void)
{
if (g_init == -1) {
pthread_mutex_lock(&g_socketNodeList.mutex);
UtilsListInit(&g_socketNodeList.list);
g_init = 0;
pthread_mutex_unlock(&g_socketNodeList.mutex);
}
return &g_socketTrans;
}
char *GetSocketLocalDeviceID(void)
{
if (g_localDeviceId != NULL) {
return g_localDeviceId;
}
struct ifaddrs *ifaddr;
struct ifaddrs *ifa;
int family;
if (getifaddrs(&ifaddr) == -1) {
RPC_LOG_ERROR("getifaddrs failed");
freeifaddrs(ifaddr);
return NULL;
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr != NULL) {
family = ifa->ifa_addr->sa_family;
if (family != AF_INET || strcmp(ifa->ifa_name, DEFAULT_NET_INTERFACE) != 0) {
continue;
}
char *localDeviceId = inet_ntoa(((struct sockaddr_in*)ifa->ifa_addr)->sin_addr);
if (localDeviceId == NULL) {
RPC_LOG_ERROR("GetSocketLocalDeviceID inet_ntoa get null");
break;
}
size_t deviceIdLen = strlen(localDeviceId);
if (deviceIdLen == 0 || deviceIdLen > DEVICEID_LENGTH) {
RPC_LOG_ERROR("deviceIdLen invalid");
break;
}
g_localDeviceId = (char *)malloc(deviceIdLen + 1);
if (g_localDeviceId == NULL) {
RPC_LOG_ERROR("g_localDeviceId malloc failed");
break;
}
if (strcpy_s(g_localDeviceId, deviceIdLen + 1, localDeviceId) != EOK) {
RPC_LOG_ERROR("g_localDeviceId strcpy failed");
} else {
RPC_LOG_INFO("GetSocketLocalDeviceID %s", g_localDeviceId);
}
break;
}
}
freeifaddrs(ifaddr);
return g_localDeviceId;
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_RPC_DBINDER_STUB_H
#define OHOS_RPC_DBINDER_STUB_H
#include <stdint.h>
#include <stdlib.h>
#include "dbinder_types.h"
#include "serializer.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
UTILS_DL_LIST list;
char serviceName[SERVICENAME_LENGTH + 1];
char deviceID[DEVICEID_LENGTH + 1];
uintptr_t binderObject;
SvcIdentity svc;
} DBinderServiceStub;
int32_t GetDBinderStub(const char *serviceName, const char *deviceID,
uintptr_t binderObject, DBinderServiceStub *dBinderServiceStub);
#ifdef __cplusplus
}
#endif
#endif // OHOS_RPC_DBINDER_STUB_H
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_RPC_DBINDER_RTANS_CALLBACK_H
#define OHOS_RPC_DBINDER_RTANS_CALLBACK_H
#include <stdint.h>
#include <stdlib.h>
#include "rpc_trans.h"
#include "dbinder_service.h"
#ifdef __cplusplus
extern "C" {
#endif
TransCallback *GetDBinderTransCallback(void);
#ifdef __cplusplus
}
#endif
#endif // OHOS_RPC_DBINDER_RTANS_CALLBACK_H
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_RPC_DBINDER_TYPES_H
#define OHOS_RPC_DBINDER_TYPES_H
#include <stdint.h>
#include "utils_list.h"
#include "serializer.h"
#ifdef __cplusplus
extern "C" {
#endif
#define DEVICEID_LENGTH 64
#define SERVICENAME_LENGTH 200
#define VERSION_NUM 1
#define SESSION_NAME_LEGNTH 8
#define RPC_IPC_LENGTH 128
#define RPC_IPC_LENGTH_LONG 256
#define GET_SYSTEM_ABILITY_TRANSACTION 1
#define ID_DIGITS 10
#define DEFAULT_SEND_WAIT_TIME 4
enum DBinderCode {
MESSAGE_AS_INVOKER = 1,
MESSAGE_AS_REPLY = 2,
MESSAGE_AS_OBITUARY = 3,
};
enum AfType {
IPV4_TYPE = 1,
IPV6_TYPE = 2,
DATABBUS_TYPE = 3,
};
enum {
DATABUS_TYPE
};
struct DeviceIdInfo {
uint16_t afType;
uint16_t reserved;
char fromDeviceId[DEVICEID_LENGTH + 1];
char toDeviceId[DEVICEID_LENGTH + 1];
};
struct DHandleEntryHead {
uint32_t len;
uint32_t version;
};
typedef struct {
UTILS_DL_LIST list;
uint32_t type;
uint16_t toPort;
uint16_t fromPort;
uint64_t stubIndex;
uint32_t socketFd;
char serviceName[SERVICENAME_LENGTH + 1];
struct DeviceIdInfo deviceIdInfo;
uintptr_t stub;
} SessionInfo;
typedef struct {
UTILS_DL_LIST list;
uintptr_t binderObject;
SvcIdentity *proxy;
char *sessionName;
uint32_t cbId;
} ProxyObject;
typedef struct {
uint32_t sizeOfSelf;
uint32_t magic;
uint32_t version;
int cmd;
uint32_t code;
uint32_t flags;
uint64_t cookie;
uint64_t seqNumber;
size_t buffer_size;
size_t offsets_size;
uintptr_t offsets;
char *buffer;
} dbinder_transaction_data;
#ifdef __cplusplus
}
#endif
#endif // OHOS_RPC_DBINDER_TYPES_H
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_RPC_DBINDER_IPC_ADAPTER_H
#define OHOS_RPC_DBINDER_IPC_ADAPTER_H
#include <stdint.h>
#include <stdbool.h>
#include "dbinder_stub.h"
#include "dbinder_types.h"
#ifdef __cplusplus
extern "C" {
#endif
bool IsSameStub(DBinderServiceStub *stub, const char *serviceName,
const char *deviceID, uintptr_t binderObject);
int32_t GetDBinderHandle(uintptr_t stubAddr);
int32_t UpdateSessionIfNeed(uintptr_t stubAddr);
ProxyObject *RpcGetSystemAbility(int32_t systemAbility);
#ifdef __cplusplus
}
#endif
#endif // OHOS_RPC_DBINDER_IPC_ADAPTER_H
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dbinder_ipc_adapter.h"
#include "securec.h"
#include "ipc_proxy_inner.h"
#include "rpc_errno.h"
#include "rpc_log.h"
#include "rpc_mini_samgr.h" // samgr refactory needed in mini system
bool IsSameStub(DBinderServiceStub *stub, const char *serviceName,
const char *deviceID, uintptr_t binderObject)
{
return false;
}
int32_t GetDBinderHandle(uintptr_t stubAddr)
{
return (int32_t)stubAddr;
}
int32_t UpdateSessionIfNeed(uintptr_t stubAddr)
{
UpdateProto((int32_t)stubAddr);
return ERR_NONE;
}
ProxyObject *RpcGetSystemAbility(int32_t systemAbility)
{
SvcIdentity *target = GetSystemAbilityById(systemAbility);
if (target == NULL) {
RPC_LOG_ERROR("GetSystemAbilityById return null");
return NULL;
}
ProxyObject *proxyObject = (ProxyObject *)calloc(1, sizeof(ProxyObject));
if (proxyObject == NULL) {
return NULL;
}
proxyObject->proxy = (SvcIdentity *)malloc(sizeof(SvcIdentity));
if (proxyObject->proxy == NULL) {
free(proxyObject);
return NULL;
}
if (memcpy_s(proxyObject->proxy, sizeof(SvcIdentity), target, sizeof(SvcIdentity)) != EOK) {
free(proxyObject->proxy);
free(proxyObject);
return NULL;
}
return proxyObject;
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dbinder_ipc_adapter.h"
#include <pthread.h>
#include <string.h>
#include "securec.h"
#include "ipc_skeleton.h"
#include "rpc_log.h"
#include "rpc_errno.h"
#define IPC_STUB_HANDLE (-1)
bool IsSameStub(DBinderServiceStub *stub, const char *serviceName,
const char *deviceID, uintptr_t binderObject)
{
if (stub == NULL) {
return false;
}
return (strcmp(stub->serviceName, serviceName) == 0 && strcmp(stub->deviceID, deviceID) == 0
&& stub->binderObject == binderObject);
}
int32_t GetDBinderHandle(uintptr_t stubAddr)
{
return IPC_STUB_HANDLE;
}
int32_t UpdateSessionIfNeed(uintptr_t stubAddr)
{
return ERR_NONE;
}
ProxyObject *RpcGetSystemAbility(int32_t systemAbility)
{
IpcIo data;
uint8_t tmpData[RPC_IPC_LENGTH];
IpcIoInit(&data, tmpData, RPC_IPC_LENGTH, 0);
RPC_LOG_INFO("GetSystemAbility systemAbility %d", systemAbility);
WriteInt32(&data, systemAbility);
IpcIo reply;
MessageOption option = TF_OP_SYNC;
RPC_LOG_INFO("get system ability from samgr");
uintptr_t ptr;
int32_t ret = SendRequest(*GetContextObject(), GET_SYSTEM_ABILITY_TRANSACTION, &data, &reply, option, &ptr);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("GetSystemAbility failed");
FreeBuffer((void *)ptr);
return NULL;
}
SvcIdentity svc;
ReadRemoteObject(&reply, &svc);
ProxyObject *proxyObject = (ProxyObject *)malloc(sizeof(ProxyObject));
if (proxyObject == NULL) {
FreeBuffer((void *)ptr);
return NULL;
}
proxyObject->proxy = (SvcIdentity *)malloc(sizeof(SvcIdentity));
if (proxyObject->proxy == NULL) {
free(proxyObject);
FreeBuffer((void *)ptr);
return NULL;
}
if (memcpy_s(proxyObject->proxy, sizeof(SvcIdentity), &svc, sizeof(SvcIdentity)) != EOK) {
free(proxyObject->proxy);
free(proxyObject);
FreeBuffer((void *)ptr);
return NULL;
}
FreeBuffer((void *)ptr);
return proxyObject;
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dbinder_service.h"
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <pthread.h>
#include "utils_list.h"
#include "securec.h"
#include "rpc_trans.h"
#include "dbinder_trans_callback.h"
#include "dbinder_ipc_adapter.h"
#include "serializer.h"
#include "dbinder_stub.h"
#include "ipc_skeleton.h"
#include "ipc_proxy_inner.h"
#include "rpc_log.h"
#include "rpc_errno.h"
typedef struct {
UTILS_DL_LIST list;
char *serviceName;
uintptr_t binder;
} RemoteBinderObjects;
typedef struct {
UTILS_DL_LIST remoteBinderObjects;
pthread_mutex_t mutex;
} RemoteBinderObjectsList;
typedef struct {
UTILS_DL_LIST dBinderStubs;
pthread_mutex_t mutex;
} DBinderStubRegistedList;
typedef struct {
UTILS_DL_LIST list;
pthread_mutex_t mutex;
pthread_cond_t condition;
uint32_t seqNumber;
} ThreadLockInfo;
typedef struct {
UTILS_DL_LIST threadLocks;
pthread_mutex_t mutex;
} ThreadLockInfoList;
typedef struct {
UTILS_DL_LIST sessionInfos;
pthread_mutex_t mutex;
} SessionInfoList;
typedef struct {
UTILS_DL_LIST proxyObject;
pthread_mutex_t mutex;
} ProxyObjectList;
static RemoteBinderObjectsList g_binderList = {.mutex = PTHREAD_MUTEX_INITIALIZER};
static DBinderStubRegistedList g_stubRegistedList = {.mutex = PTHREAD_MUTEX_INITIALIZER};
static ThreadLockInfoList g_threadLockInfoList = {.mutex = PTHREAD_MUTEX_INITIALIZER};
static SessionInfoList g_sessionInfoList = {.mutex = PTHREAD_MUTEX_INITIALIZER};
static ProxyObjectList g_proxyObjectList = {.mutex = PTHREAD_MUTEX_INITIALIZER};
static TransInterface *g_trans = NULL;
static char const *DBINDER_SESSION_NAME = "DBinderService";
static const uint32_t RETRY_TIMES = 2;
static const int32_t FIRST_SYS_ABILITY_ID = 0x00000001;
static const int32_t LAST_SYS_ABILITY_ID = 0x00ffffff;
static int32_t InitDBinder(void)
{
UtilsListInit(&g_binderList.remoteBinderObjects);
UtilsListInit(&g_stubRegistedList.dBinderStubs);
UtilsListInit(&g_threadLockInfoList.threadLocks);
UtilsListInit(&g_sessionInfoList.sessionInfos);
UtilsListInit(&g_proxyObjectList.proxyObject);
return ERR_NONE;
}
static char *GetRegisterService(uintptr_t binderObject)
{
RemoteBinderObjects *node = NULL;
pthread_mutex_lock(&g_binderList.mutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_binderList.remoteBinderObjects, RemoteBinderObjects, list)
{
if (node->binder == binderObject) {
pthread_mutex_unlock(&g_binderList.mutex);
return node->serviceName;
}
}
pthread_mutex_unlock(&g_binderList.mutex);
return NULL;
}
static void AddRegisterService(RemoteBinderObjects *binderObject)
{
pthread_mutex_lock(&g_binderList.mutex);
UtilsListAdd(&g_binderList.remoteBinderObjects, &binderObject->list);
pthread_mutex_unlock(&g_binderList.mutex);
}
static int32_t CheckBinderParams(const void *serviceName, uint32_t nameLen, const char *deviceID,
uint32_t idLen, void *remoteObject)
{
if (serviceName == NULL || deviceID == NULL || remoteObject == NULL) {
RPC_LOG_ERROR("MakeRemoteBinder null poiter");
return ERR_FAILED;
}
if (strlen((char *)serviceName) != nameLen || strlen(deviceID) != idLen) {
RPC_LOG_ERROR("MakeRemoteBinder length invalid");
return ERR_FAILED;
}
return ERR_NONE;
}
static DBinderServiceStub *QueryDBinderStub(const char *serviceName, const char *deviceID,
uintptr_t binderObject)
{
pthread_mutex_lock(&g_stubRegistedList.mutex);
DBinderServiceStub *node = NULL;
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_stubRegistedList.dBinderStubs, DBinderServiceStub, list)
{
if (IsSameStub(node, serviceName, deviceID, binderObject)) {
RPC_LOG_INFO("find dBinderStub in g_stubRegistedList");
pthread_mutex_unlock(&g_stubRegistedList.mutex);
return node;
}
}
pthread_mutex_unlock(&g_stubRegistedList.mutex);
return NULL;
}
static void AddDBinderStub(DBinderServiceStub *stub)
{
pthread_mutex_lock(&g_stubRegistedList.mutex);
UtilsListAdd(&g_stubRegistedList.dBinderStubs, &stub->list);
pthread_mutex_unlock(&g_stubRegistedList.mutex);
}
static DBinderServiceStub *FindOrNewDBinderStub(const char *serviceName, uint32_t nameLen,
const char *deviceID, uint32_t idLen, uintptr_t binderObject)
{
if (serviceName == NULL || deviceID == NULL) {
RPC_LOG_ERROR("FindOrNewDBinderStub get null input params");
return NULL;
}
DBinderServiceStub *node = QueryDBinderStub(serviceName, deviceID, binderObject);
if (node != NULL) {
RPC_LOG_INFO("DBinderStub cached already");
return node;
}
node = (DBinderServiceStub *)malloc(sizeof(DBinderServiceStub));
if (node == NULL) {
RPC_LOG_ERROR("dBinderServiceStub malloc failed");
return NULL;
}
if (GetDBinderStub(serviceName, deviceID, binderObject, node) != ERR_NONE) {
RPC_LOG_ERROR("GetDBinderStub failed");
free(node);
return NULL;
}
AddDBinderStub(node);
return node;
}
static int32_t SendDataToRemote(const char *deviceId, const DHandleEntryTxRx *msg)
{
if (deviceId == NULL || msg == NULL) {
return ERR_FAILED;
}
int32_t sessionId = 0;
sessionId = g_trans->Connect(DBINDER_SESSION_NAME, deviceId, NULL);
if (sessionId < 0) {
RPC_LOG_ERROR("SendDataToRemote connect failed");
return ERR_FAILED;
}
if (g_trans->Send(sessionId, (void *)msg, msg->head.len) != ERR_NONE) {
RPC_LOG_ERROR("SendDataToRemote send failed");
return ERR_FAILED;
}
return ERR_NONE;
}
static int32_t SendEntryToRemote(DBinderServiceStub *stub, const uint32_t seqNumber)
{
char *toDeviceID = stub->deviceID;
if (toDeviceID == NULL) {
RPC_LOG_ERROR("toDeviceID invalid");
return ERR_FAILED;
}
uint32_t toDeviceIDLength = (uint32_t)strlen(toDeviceID);
char *localDeviceID = GetLocalDeviceID();
if (localDeviceID == NULL) {
RPC_LOG_ERROR("GetLocalDeviceID failed");
return ERR_FAILED;
}
uint32_t localDeviceIDLength = (uint32_t)strlen(localDeviceID);
if (toDeviceIDLength > DEVICEID_LENGTH || localDeviceIDLength > DEVICEID_LENGTH) {
RPC_LOG_ERROR("deviceID invalid");
return ERR_FAILED;
}
DHandleEntryTxRx message = {
.head.len = sizeof(DHandleEntryTxRx),
.head.version = VERSION_NUM,
.transType = DATABUS_TYPE,
.dBinderCode = MESSAGE_AS_INVOKER,
.fromPort = 0,
.toPort = 0,
.stubIndex = atoi(stub->serviceName),
.seqNumber = seqNumber,
.binderObject = stub->binderObject,
.deviceIdInfo.afType = DATABBUS_TYPE,
.stub = (uintptr_t)(stub->svc.cookie),
.pid = (uint32_t)GetCallingPid(),
.uid = (uint32_t)GetCallingUid()
};
if (memcpy_s(message.deviceIdInfo.fromDeviceId, DEVICEID_LENGTH, localDeviceID, localDeviceIDLength) != EOK ||
memcpy_s(message.deviceIdInfo.toDeviceId, DEVICEID_LENGTH, toDeviceID, toDeviceIDLength) != EOK) {
RPC_LOG_ERROR("deviceIdInfo memory copy failed");
return ERR_FAILED;
}
message.deviceIdInfo.fromDeviceId[localDeviceIDLength] = '\0';
message.deviceIdInfo.toDeviceId[toDeviceIDLength] = '\0';
if (SendDataToRemote(toDeviceID, &message) != ERR_NONE) {
RPC_LOG_ERROR("SendDataToRemote failed");
return ERR_FAILED;
}
return ERR_NONE;
}
static int32_t AttachThreadLockInfo(ThreadLockInfo *threadLockInfo)
{
pthread_mutex_lock(&g_threadLockInfoList.mutex);
UtilsListAdd(&g_threadLockInfoList.threadLocks, &threadLockInfo->list);
pthread_mutex_unlock(&g_threadLockInfoList.mutex);
return ERR_NONE;
}
static void DetachThreadLockInfo(ThreadLockInfo *threadLockInfo)
{
pthread_mutex_lock(&g_threadLockInfoList.mutex);
UtilsListDelete(&threadLockInfo->list);
pthread_mutex_unlock(&g_threadLockInfoList.mutex);
}
static int32_t InvokerRemoteDBinder(DBinderServiceStub *dBinderServiceStub, uint32_t seqNumber)
{
if (dBinderServiceStub == NULL) {
RPC_LOG_ERROR("InvokerRemoteDBinder dBinderServiceStub is NULL");
return ERR_FAILED;
}
int32_t ret = ERR_FAILED;
ThreadLockInfo *threadLockInfo = (ThreadLockInfo *)malloc(sizeof(ThreadLockInfo));
if (threadLockInfo == NULL) {
RPC_LOG_ERROR("threadLockInfo malloc failed");
return ERR_FAILED;
}
if (pthread_mutex_init(&threadLockInfo->mutex, NULL) != 0) {
RPC_LOG_ERROR("threadLockInfo mutex init failed");
free(threadLockInfo);
return ERR_FAILED;
}
if (pthread_cond_init(&threadLockInfo->condition, NULL) != 0) {
RPC_LOG_ERROR("threadLockInfo condition init failed");
pthread_mutex_destroy(&threadLockInfo->mutex);
free(threadLockInfo);
return ERR_FAILED;
}
threadLockInfo->seqNumber = seqNumber;
ret = AttachThreadLockInfo(threadLockInfo);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("AttachThreadLockInfo failed");
pthread_mutex_destroy(&threadLockInfo->mutex);
pthread_cond_destroy(&threadLockInfo->condition);
free(threadLockInfo);
return ret;
}
pthread_mutex_lock(&threadLockInfo->mutex);
ret = SendEntryToRemote(dBinderServiceStub, seqNumber);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("send entry to remote dbinderService failed");
} else {
pthread_cond_wait(&threadLockInfo->condition, &threadLockInfo->mutex);
RPC_LOG_INFO("InvokerRemoteDBinder wakeup!");
}
if (QuerySessionObject((uintptr_t)(dBinderServiceStub->svc.cookie)) == NULL) {
RPC_LOG_ERROR("QuerySessionObject is null");
ret = ERR_FAILED;
}
if (UpdateSessionIfNeed(dBinderServiceStub->svc.cookie) != ERR_NONE) {
RPC_LOG_ERROR("UpdateSessionIfNeed failed");
ret = ERR_FAILED;
}
pthread_mutex_unlock(&threadLockInfo->mutex);
DetachThreadLockInfo(threadLockInfo);
free(threadLockInfo);
return ret;
}
static uint32_t GetSeqNumber(void)
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static uint32_t seqNumber = 0;
pthread_mutex_lock(&mutex);
seqNumber++;
pthread_mutex_unlock(&mutex);
return seqNumber;
}
static int32_t AttachSessionObject(SessionInfo *sessionInfo)
{
pthread_mutex_lock(&g_sessionInfoList.mutex);
UtilsListAdd(&g_sessionInfoList.sessionInfos, &sessionInfo->list);
pthread_mutex_unlock(&g_sessionInfoList.mutex);
return ERR_NONE;
}
static void DetachSessionObject(SessionInfo *sessionInfo)
{
pthread_mutex_lock(&g_sessionInfoList.mutex);
UtilsListDelete(&sessionInfo->list);
pthread_mutex_unlock(&g_sessionInfoList.mutex);
}
SessionInfo *QuerySessionObject(uintptr_t stub)
{
SessionInfo *node = NULL;
pthread_mutex_lock(&g_sessionInfoList.mutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_sessionInfoList.sessionInfos, SessionInfo, list)
{
if (node->stub == stub) {
pthread_mutex_unlock(&g_sessionInfoList.mutex);
return node;
}
}
pthread_mutex_unlock(&g_sessionInfoList.mutex);
return NULL;
}
static void DeleteDBinderStub(DBinderServiceStub *stub)
{
if (stub == NULL) {
RPC_LOG_ERROR("DeleteDBinderStub get null stub");
return;
}
pthread_mutex_lock(&g_stubRegistedList.mutex);
UtilsListDelete(&stub->list);
pthread_mutex_unlock(&g_stubRegistedList.mutex);
}
static ProxyObject *QueryProxyObject(uintptr_t binderObject)
{
ProxyObject *node = NULL;
pthread_mutex_lock(&g_proxyObjectList.mutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_proxyObjectList.proxyObject, ProxyObject, list)
{
if (node->binderObject == binderObject) {
pthread_mutex_unlock(&g_proxyObjectList.mutex);
return node;
}
}
pthread_mutex_unlock(&g_proxyObjectList.mutex);
return NULL;
}
static int32_t AttachProxyObject(ProxyObject *proxy)
{
pthread_mutex_lock(&g_proxyObjectList.mutex);
UtilsListAdd(&g_proxyObjectList.proxyObject, &proxy->list);
pthread_mutex_unlock(&g_proxyObjectList.mutex);
return ERR_NONE;
}
void DetachProxyObject(ProxyObject *proxy)
{
pthread_mutex_lock(&g_proxyObjectList.mutex);
UtilsListDelete(&proxy->list);
pthread_mutex_unlock(&g_proxyObjectList.mutex);
}
static void DbinderSaDeathRecipient(void *args)
{
if (args == NULL) {
RPC_LOG_ERROR("DbinderSaDeathRecipient args is null");
return;
}
ProxyObject *proxyObject = (ProxyObject *)args;
RPC_LOG_INFO("DbinderSaDeathRecipient cbiId %d", proxyObject->cbId);
DetachProxyObject(proxyObject);
}
static ProxyObject *FindOrNewProxy(uintptr_t binderObject, int32_t systemAbilityId)
{
ProxyObject *proxyObject = QueryProxyObject(binderObject);
if (proxyObject != NULL) {
RPC_LOG_INFO("FindOrNewProxy found cached proxy");
return proxyObject;
}
char *serviceName = GetRegisterService(binderObject);
if (serviceName == NULL && (systemAbilityId < FIRST_SYS_ABILITY_ID || systemAbilityId > LAST_SYS_ABILITY_ID)) {
RPC_LOG_ERROR("service is not registered in this device, saId:%d", systemAbilityId);
return NULL;
}
int32_t digitalName = systemAbilityId;
if (serviceName != NULL) {
digitalName = atoi(serviceName);
}
proxyObject = RpcGetSystemAbility(digitalName);
if (proxyObject == NULL) {
RPC_LOG_ERROR("RpcGetSystemAbility failed, saId: %d", systemAbilityId);
return NULL;
}
proxyObject->binderObject = binderObject;
int32_t ret = AddDeathRecipient(*proxyObject->proxy, DbinderSaDeathRecipient,
(void *)proxyObject, &proxyObject->cbId);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("FindOrNewProxy AddDeathRecipient failed, error %d", ret);
free(proxyObject->proxy);
free(proxyObject);
return NULL;
}
if (AttachProxyObject(proxyObject) != ERR_NONE) {
RPC_LOG_ERROR("FindOrNewProxy AttachProxyObject failed");
RemoveDeathRecipient(*proxyObject->proxy, proxyObject->cbId);
free(proxyObject->proxy);
free(proxyObject);
return NULL;
}
return proxyObject;
}
static int32_t GetDatabusNameByProxy(ProxyObject *proxy)
{
if (proxy == NULL) {
RPC_LOG_ERROR("GetDatabusNameByProxy proxy is null");
return ERR_FAILED;
}
if (proxy->sessionName != NULL && strlen(proxy->sessionName) > 0) {
RPC_LOG_ERROR("GetDatabusNameByProxy proxy got sessionName already");
return ERR_NONE;
}
if (GetPidAndUidInfo(proxy) != ERR_NONE) {
RPC_LOG_ERROR("GetDatabusNameByProxy GetPidAndUidInfo failed");
return ERR_FAILED;
}
return ERR_NONE;
}
static int32_t OnRemoteInvokerDataBusMessage(ProxyObject *proxy, DHandleEntryTxRx *replyMessage,
const char *remoteDeviceID, uint32_t pid, uint32_t uid)
{
if (remoteDeviceID == NULL || strlen(remoteDeviceID) > DEVICEID_LENGTH) {
RPC_LOG_ERROR("remote deviceID invalid");
return ERR_FAILED;
}
if (GetDatabusNameByProxy(proxy) != ERR_NONE) {
RPC_LOG_ERROR("GetDatabusNameByProxy failed");
return ERR_FAILED;
}
IpcIo reply;
uintptr_t ptr;
int32_t ret = InvokerListenThread(proxy, GetLocalDeviceID(), remoteDeviceID, pid, uid, &reply, &ptr);
if (ret != ERR_NONE) {
RPC_LOG_ERROR("INVOKE_LISTEN_THREAD failed");
FreeBuffer((void *)ptr);
return ERR_FAILED;
}
uint64_t stubIndex;
if (!ReadUint64(&reply, &stubIndex)) {
FreeBuffer((void *)ptr);
return ERR_FAILED;
}
size_t sessionLen;
char *serverSessionName = (char *)ReadString(&reply, &sessionLen);
if (stubIndex == 0 || serverSessionName == NULL || strlen(serverSessionName) > SERVICENAME_LENGTH) {
RPC_LOG_ERROR("INVOKE_LISTEN_THREAD reply stubIndex or sessionName invalid");
FreeBuffer((void *)ptr);
return ERR_FAILED;
}
replyMessage->dBinderCode = MESSAGE_AS_REPLY;
replyMessage->stubIndex = stubIndex;
replyMessage->serviceNameLength = (uint16_t)sessionLen;
if (memcpy_s(replyMessage->serviceName, SERVICENAME_LENGTH, serverSessionName, sessionLen) != 0) {
RPC_LOG_ERROR("replyMessage serviceName memcpy failed");
FreeBuffer((void *)ptr);
return ERR_FAILED;
}
replyMessage->serviceName[replyMessage->serviceNameLength] = '\0';
FreeBuffer((void *)ptr);
return ERR_NONE;
}
static int32_t OnRemoteInvokerMessage(const DHandleEntryTxRx *message)
{
ProxyObject *saProxy = FindOrNewProxy(message->binderObject, (int32_t)message->stubIndex);
if (saProxy == NULL) {
RPC_LOG_ERROR("OnRemoteInvokerMessage get SA Proxy failed");
return ERR_FAILED;
}
DHandleEntryTxRx replyMessage;
if (memcpy_s(&replyMessage, sizeof(DHandleEntryTxRx), message, sizeof(DHandleEntryTxRx)) != EOK) {
RPC_LOG_ERROR("OnRemoteInvokerMessage replyMessage memcpy failed");
return ERR_FAILED;
}
char *fromDeviceID = replyMessage.deviceIdInfo.fromDeviceId;
switch (replyMessage.transType) {
case DATABUS_TYPE: {
if (OnRemoteInvokerDataBusMessage(saProxy, &replyMessage, fromDeviceID,
message->pid, message->uid) != ERR_NONE) {
RPC_LOG_ERROR("OnRemoteInvokerMessage Invoker Databus Message fail");
return ERR_FAILED;
}
break;
}
default: {
RPC_LOG_ERROR("OnRemoteInvokerMessage msg transType invalid");
return ERR_FAILED;
}
}
if (SendDataToRemote(fromDeviceID, &replyMessage) != ERR_NONE) {
RPC_LOG_ERROR("fail to send data from server DBS to client DBS");
return ERR_FAILED;
}
return ERR_NONE;
}
static ThreadLockInfo *QueryThreadLockInfo(uint32_t seqNumber)
{
ThreadLockInfo *node = NULL;
pthread_mutex_lock(&g_threadLockInfoList.mutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_threadLockInfoList.threadLocks, ThreadLockInfo, list)
{
if (node->seqNumber == seqNumber) {
pthread_mutex_unlock(&g_threadLockInfoList.mutex);
return node;
}
}
pthread_mutex_unlock(&g_threadLockInfoList.mutex);
return NULL;
}
static void WakeupThreadByStub(uint32_t seqNumber)
{
ThreadLockInfo *threadLockInfo = QueryThreadLockInfo(seqNumber);
if (threadLockInfo == NULL) {
RPC_LOG_ERROR("threadLockInfo is not exist");
return;
}
pthread_mutex_lock(&threadLockInfo->mutex);
pthread_cond_signal(&threadLockInfo->condition);
pthread_mutex_unlock(&threadLockInfo->mutex);
}
static bool HasDBinderStub(uintptr_t binderObject)
{
DBinderServiceStub *node;
pthread_mutex_lock(&g_stubRegistedList.mutex);
UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_stubRegistedList.dBinderStubs, DBinderServiceStub, list)
{
if (node->binderObject == binderObject) {
pthread_mutex_unlock(&g_stubRegistedList.mutex);
return true;
}
}
pthread_mutex_unlock(&g_stubRegistedList.mutex);
return false;
}
static void MakeSessionByReplyMessage(const DHandleEntryTxRx *replyMessage)
{
if (replyMessage == NULL) {
RPC_LOG_ERROR("replyMessage is null");
return;
}
if (!HasDBinderStub(replyMessage->binderObject)) {
RPC_LOG_ERROR("invalid stub object");
return;
}
if (QuerySessionObject(replyMessage->stub) != NULL) {
RPC_LOG_ERROR("invoker remote session already, do nothing");
return;
}
SessionInfo *session = (SessionInfo *)malloc(sizeof(SessionInfo));
if (session == NULL) {
RPC_LOG_ERROR("session malloc failed");
return;
}
if (memcpy_s(&session->deviceIdInfo, sizeof(struct DeviceIdInfo),
&replyMessage->deviceIdInfo, sizeof(struct DeviceIdInfo)) != 0) {
RPC_LOG_ERROR("deviceIdInfo memory copy failed");
free(session);
return;
}
if (strcpy_s(session->serviceName, SERVICENAME_LENGTH + 1, replyMessage->serviceName) != EOK) {
RPC_LOG_ERROR("session serviceName copy failed");
free(session);
return;
}
session->serviceName[replyMessage->serviceNameLength] = '\0';
session->socketFd = 0;
session->stubIndex = replyMessage->stubIndex;
session->toPort = replyMessage->toPort;
session->fromPort = replyMessage->fromPort;
session->type = replyMessage->transType;
session->stub = replyMessage->stub;
if (session->stubIndex == 0) {
RPC_LOG_ERROR("stubIndex invalid");
free(session);
return;
}
if (AttachSessionObject(session) != 0) {
RPC_LOG_ERROR("AttachSessionObject failed");
return;
}
}
static int32_t OnRemoteReplyMessage(const DHandleEntryTxRx *replyMessage)
{
MakeSessionByReplyMessage(replyMessage);
WakeupThreadByStub(replyMessage->seqNumber);
return ERR_NONE;
}
int32_t StartDBinderService(void)
{
static bool isDBinderCreated = false;
int32_t ret = ERR_NONE;
if (isDBinderCreated) {
return ret;
}
g_trans = GetRpcTrans();
if (g_trans == NULL) {
RPC_LOG_ERROR("GetRpcTrans failed");
return ERR_FAILED;
}
ret = g_trans->StartListen(DBINDER_SESSION_NAME, (void *)GetDBinderTransCallback());
if (ret != ERR_NONE) {
RPC_LOG_ERROR("StartListen failed");
return ret;
}
ret = InitDBinder();
if (ret != ERR_NONE) {
RPC_LOG_ERROR("InitDBinder failed");
}
isDBinderCreated = true;
return ret;
}
int32_t RegisterRemoteProxy(const void *name, uint32_t len, int32_t systemAbility)
{
RPC_LOG_INFO("register remote proxy, service name = %s", (char*)name);
if (name == NULL || systemAbility < 0) {
RPC_LOG_ERROR("RegisterRemoteProxy name is null or systemAbility invalid");
return ERR_FAILED;
}
const char *serviceName = (char *)name;
RemoteBinderObjects *binderObject = (RemoteBinderObjects *)malloc(sizeof(RemoteBinderObjects));
if (binderObject == NULL) {
RPC_LOG_ERROR("binder object malloc failed");
return ERR_FAILED;
}
uintptr_t binder = (uintptr_t)systemAbility;
binderObject->binder = binder;
if (len == 0 || len > SERVICENAME_LENGTH || len != strlen(serviceName)) {
RPC_LOG_ERROR("RegisterRemoteProxy name length invalid");
free(binderObject);
return ERR_FAILED;
}
binderObject->serviceName = (char *)malloc(len + 1);
if (binderObject->serviceName == NULL) {
RPC_LOG_ERROR("RegisterRemoteProxy binderObject->serviceName malloc failed");
free(binderObject);
return ERR_FAILED;
}
if (strcpy_s(binderObject->serviceName, len + 1, serviceName) != EOK) {
RPC_LOG_ERROR("RegisterRemoteProxy binderObject->serviceName copy failed");
free(binderObject->serviceName);
free(binderObject);
return ERR_FAILED;
}
AddRegisterService(binderObject);
return ERR_NONE;
}
int32_t MakeRemoteBinder(const void *serviceName, uint32_t nameLen, const char *deviceID, uint32_t idLen,
uintptr_t binderObject, uint64_t pid, void *remoteObject)
{
RPC_LOG_INFO("MakeRemoteBinder start");
if (CheckBinderParams(serviceName, nameLen, deviceID, idLen, remoteObject) != ERR_NONE) {
RPC_LOG_ERROR("MakeRemoteBinder failed");
return ERR_FAILED;
}
const char *name = (const char *)serviceName;
DBinderServiceStub *dBinderServiceStub = FindOrNewDBinderStub(name, nameLen, deviceID, idLen, binderObject);
if (dBinderServiceStub == NULL) {
RPC_LOG_ERROR("FindOrNewDBinderStub return null");
return ERR_FAILED;
}
uint32_t retryTimes = 0;
int32_t ret = ERR_FAILED;
do {
ret = InvokerRemoteDBinder(dBinderServiceStub, GetSeqNumber());
retryTimes++;
} while (ret != ERR_NONE && (retryTimes < RETRY_TIMES));
if (ret != ERR_NONE) {
RPC_LOG_ERROR("fail to invoke service, service name = %s", serviceName);
SessionInfo *sessionObject = QuerySessionObject((uintptr_t)(dBinderServiceStub->svc.cookie));
if (sessionObject != NULL) {
DetachSessionObject(sessionObject);
free(sessionObject);
}
DeleteDBinderStub(dBinderServiceStub);
free((void *)dBinderServiceStub->svc.cookie);
free(dBinderServiceStub);
} else {
if (memcpy_s(remoteObject, sizeof(SvcIdentity), &dBinderServiceStub->svc, sizeof(SvcIdentity)) != 0) {
RPC_LOG_ERROR("svc memory copy failed");
ret = ERR_FAILED;
}
}
return ret;
}
int32_t OnRemoteMessageTask(const DHandleEntryTxRx *message)
{
if (message == NULL) {
RPC_LOG_ERROR("OnRemoteMessageTask message is NULL");
return ERR_FAILED;
}
int32_t ret = ERR_NONE;
switch (message->dBinderCode) {
case MESSAGE_AS_INVOKER: {
ret = OnRemoteInvokerMessage(message);
break;
}
case MESSAGE_AS_REPLY: {
ret = OnRemoteReplyMessage(message);
break;
}
default: {
RPC_LOG_ERROR("OnRemoteMessageTask dbindercode=%d valid", message->dBinderCode);
ret = ERR_FAILED;
break;
}
}
return ret;
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dbinder_stub.h"
#include <stdbool.h>
#include <pthread.h>
#include "rpc_log.h"
#include "rpc_errno.h"
#include "securec.h"
#include "ipc_thread_pool.h"
#include "ipc_skeleton.h"
#include "ipc_process_skeleton.h"
#include "dbinder_service.h"
#include "dbinder_ipc_adapter.h"
static int32_t GetDigits(int32_t number)
{
int32_t n = 0;
while (number > 0) {
n++;
number /= ID_DIGITS;
}
if (n == 0) {
n++;
}
return n;
}
static char *CreateDatabusName(void)
{
int32_t pid = (int32_t)GetCallingPid();
int32_t pidLen = GetDigits(pid);
int32_t uid = (int32_t)GetCallingUid();
int32_t uidLen = GetDigits(uid);
uint32_t sessionNameLen = SESSION_NAME_LEGNTH + pidLen + uidLen;
char *sessionName = (char *)malloc(sessionNameLen + 1);
if (sessionName == NULL) {
RPC_LOG_ERROR("sessionName mallo failed");
return NULL;
}
if (sprintf_s(sessionName, sessionNameLen + 1, "DBinder%d_%d", uid, pid) == -1) {
RPC_LOG_ERROR("sessionName sprintf failed");
free(sessionName);
return NULL;
}
return sessionName;
}
static int32_t ProcessProto(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption *option)
{
int32_t result = ERR_NONE;
ThreadContext *threadContext = GetCurrentThreadContext();
if (threadContext == NULL) {
RPC_LOG_ERROR("ProcessProto threadContext is null");
return ERR_FAILED;
}
SessionInfo *session = QuerySessionObject((uintptr_t)threadContext->objectStub);
if (session == NULL) {
RPC_LOG_ERROR("client find session is null");
return ERR_FAILED;
}
const char *localBusName = CreateDatabusName();
if (localBusName == NULL) {
RPC_LOG_ERROR("ProcessProto CreateDatabusName failed");
return ERR_FAILED;
}
switch (session->type) {
case DATABUS_TYPE: {
WriteUint32(reply, IF_PROT_DATABUS);
WriteUint64(reply, session->stubIndex);
WriteString(reply, session->serviceName);
WriteString(reply, session->deviceIdInfo.toDeviceId);
WriteString(reply, session->deviceIdInfo.fromDeviceId);
WriteString(reply, localBusName);
free((void *)localBusName);
break;
}
default: {
result = ERR_FAILED;
break;
}
}
return result;
}
static int32_t DBinderRemoteRequest(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption *option)
{
int32_t ret = 0;
switch (code) {
case GET_PROTO_INFO: {
ret = ProcessProto(code, data, reply, option);
break;
}
default: {
RPC_LOG_ERROR("unknown dbinder code %{public}d", code);
ret = -1;
break;
}
}
return ret;
}
int32_t GetDBinderStub(const char *serviceName, const char *deviceID,
uintptr_t binderObject, DBinderServiceStub *dBinderServiceStub)
{
if (strcpy_s(dBinderServiceStub->serviceName, SERVICENAME_LENGTH, serviceName) != EOK
|| strcpy_s(dBinderServiceStub->deviceID, DEVICEID_LENGTH, deviceID) != EOK) {
RPC_LOG_ERROR("dBinderServiceStub string copy failed");
return ERR_FAILED;
}
IpcObjectStub *objectStub = (IpcObjectStub *)malloc(sizeof(IpcObjectStub));
if (objectStub == NULL) {
RPC_LOG_ERROR("objectStub malloc failed");
return ERR_FAILED;
}
objectStub->func = (OnRemoteRequest)DBinderRemoteRequest;
objectStub->isRemote = true;
dBinderServiceStub->binderObject = binderObject;
dBinderServiceStub->svc.handle = GetDBinderHandle((uintptr_t)objectStub);
dBinderServiceStub->svc.token = (uintptr_t)objectStub;
dBinderServiceStub->svc.cookie = (uintptr_t)objectStub;
return ERR_NONE;
}
\ No newline at end of file
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rpc_trans.h"
#include <stdbool.h>
#include "dbinder_service.h"
#include "rpc_log.h"
#include "rpc_errno.h"
static int32_t OnConnected(int32_t sessionId, int32_t result)
{
RPC_LOG_ERROR("dbinder OnConnected callback, receive sessionId: %d", sessionId);
return ERR_NONE;
}
static int32_t OnDisconnected(int32_t sessionId)
{
RPC_LOG_ERROR("dbinder OnDisconnected callback, receive sessionId: %d", sessionId);
return ERR_NONE;
}
static int32_t OnRecieved(int32_t sessionId, const void *data, uint32_t len)
{
RPC_LOG_INFO("dbinder OnRecieved callback, receive sessionId: %d", sessionId);
if (data == NULL) {
RPC_LOG_ERROR("OnRecieved failed, data is null");
return ERR_FAILED;
}
if (len != sizeof(DHandleEntryTxRx)) {
RPC_LOG_ERROR("OnRecieved received data length %d, excepted length %d", len, sizeof(DHandleEntryTxRx));
return ERR_FAILED;
}
DHandleEntryTxRx *handleEntry = (DHandleEntryTxRx *)data;
if (OnRemoteMessageTask(handleEntry) != ERR_NONE) {
RPC_LOG_ERROR("OnRemoteMessageTask failed");
return ERR_FAILED;
}
return ERR_NONE;
}
static TransCallback g_sessionListener = {
.OnConnected = OnConnected,
.OnDisconnected = OnDisconnected,
.OnRecieved = OnRecieved
};
TransCallback *GetDBinderTransCallback(void)
{
RPC_LOG_INFO("GetTransCallback dbinder");
return &g_sessionListener;
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册