1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "bus_center_client_stub.h"
17 #include "comm_log.h"
18 #include "iproxy_client.h"
19 #include "ipc_skeleton.h"
20 #include "softbus_adapter_mem.h"
21 #include "softbus_adapter_thread.h"
22 #include "softbus_adapter_timer.h"
23 #include "softbus_client_context_manager.h"
24 #include "softbus_client_event_manager.h"
25 #include "softbus_client_frame_manager.h"
26 #include "softbus_client_stub_interface.h"
27 #include "softbus_errcode.h"
28 #include "softbus_server_ipc_interface_code.h"
29 #include "softbus_server_proxy.h"
30 #include "trans_client_stub.h"
31 
32 #define INVALID_CB_ID 0xFF
33 
34 static int RegisterServerDeathCb(void);
35 static unsigned int g_deathCbId = INVALID_CB_ID;
36 static SvcIdentity g_svcIdentity = {0};
37 
38 struct SoftBusIpcClientCmd {
39     enum SoftBusFuncId code;
40     int32_t (*func)(IpcIo *data, IpcIo *reply);
41 };
42 
43 static struct SoftBusIpcClientCmd g_softBusIpcClientCmdTbl[] = {
44     { CLIENT_ON_JOIN_RESULT, ClientOnJoinLNNResult },
45     { CLIENT_ON_JOIN_METANODE_RESULT, ClientOnJoinMetaNodeResult },
46     { CLIENT_ON_LEAVE_RESULT, ClientOnLeaveLNNResult },
47     { CLIENT_ON_LEAVE_METANODE_RESULT, ClientOnLeaveMetaNodeResult },
48     { CLIENT_ON_NODE_ONLINE_STATE_CHANGED, ClientOnNodeOnlineStateChanged },
49     { CLIENT_ON_NODE_BASIC_INFO_CHANGED, ClientOnNodeBasicInfoChanged },
50     { CLIENT_ON_TIME_SYNC_RESULT, ClientOnTimeSyncResult },
51     { CLIENT_ON_PUBLISH_LNN_RESULT, ClientOnPublishLNNResult },
52     { CLIENT_ON_REFRESH_LNN_RESULT, ClientOnRefreshLNNResult },
53     { CLIENT_ON_REFRESH_DEVICE_FOUND, ClientOnRefreshDeviceFound },
54     { CLIENT_ON_CHANNEL_OPENED, ClientOnChannelOpened },
55     { CLIENT_ON_CHANNEL_OPENFAILED, ClientOnChannelOpenfailed },
56     { CLIENT_ON_CHANNEL_CLOSED, ClientOnChannelClosed },
57     { CLIENT_ON_CHANNEL_MSGRECEIVED, ClientOnChannelMsgreceived },
58     { CLIENT_SET_CHANNEL_INFO, ClientSetChannelInfo },
59     { CLIENT_ON_CHANNEL_BIND, ClientOnChannelBind },
60 };
61 
ClientIpcInterfaceMsgHandle(uint32_t code,IpcIo * data,IpcIo * reply,MessageOption option)62 static int ClientIpcInterfaceMsgHandle(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option)
63 {
64     if (data == NULL) {
65         COMM_LOGE(COMM_SDK, "invalid param");
66         return SOFTBUS_ERR;
67     }
68 
69     COMM_LOGI(COMM_SDK, "receive ipc transact code. code=%{public}u", code);
70     unsigned int num = sizeof(g_softBusIpcClientCmdTbl) / sizeof(struct SoftBusIpcClientCmd);
71     for (unsigned int i = 0; i < num; i++) {
72         if (code == g_softBusIpcClientCmdTbl[i].code) {
73             return g_softBusIpcClientCmdTbl[i].func(data, reply);
74         }
75     }
76     COMM_LOGE(COMM_SDK, "not support code. code=%{public}u", code);
77     return SOFTBUS_ERR;
78 }
79 
InnerRegisterService(void)80 static int InnerRegisterService(void)
81 {
82     char *clientName[SOFTBUS_PKGNAME_MAX_NUM] = {0};
83     uint32_t clientNameNum = GetSoftBusClientNameList(clientName, SOFTBUS_PKGNAME_MAX_NUM);
84     if (clientNameNum == 0) {
85         COMM_LOGE(COMM_SDK, "get client name failed");
86         return SOFTBUS_ERR;
87     }
88 
89     struct CommonScvId svcId = {0};
90     if (GetClientIdentity(&svcId.handle, &svcId.token, &svcId.cookie) != SOFTBUS_OK) {
91         COMM_LOGE(COMM_SDK, "get client identity failed");
92         for (uint32_t i = 0; i < clientNameNum; i++) {
93             SoftBusFree(clientName[i]);
94         }
95         return SOFTBUS_ERR;
96     }
97     for (uint32_t i = 0; i < clientNameNum; i++) {
98         while (RegisterService(clientName[i], &svcId) != SOFTBUS_OK) {
99             SoftBusSleepMs(WAIT_SERVER_READY_INTERVAL);
100         }
101         SoftBusFree(clientName[i]);
102     }
103 
104     COMM_LOGD(COMM_SDK, "InnerRegisterService success");
105     return SOFTBUS_OK;
106 }
107 
UnregisterServerDeathCb(void)108 static void UnregisterServerDeathCb(void)
109 {
110     RemoveDeathRecipient(g_svcIdentity, g_deathCbId);
111     g_deathCbId = INVALID_CB_ID;
112     g_svcIdentity.handle = 0;
113     g_svcIdentity.token = 0;
114     g_svcIdentity.cookie = 0;
115 }
116 
DeathProcTask(void * arg)117 static void *DeathProcTask(void *arg)
118 {
119     (void)arg;
120     CLIENT_NotifyObserver(EVENT_SERVER_DEATH, NULL, 0);
121 
122     if (InnerRegisterService() != SOFTBUS_OK) {
123         COMM_LOGE(COMM_SDK, "register service failed");
124         return NULL;
125     }
126 
127     COMM_LOGI(COMM_SDK, "\n<< !!! SERVICE (%{public}s) RECOVER !!! >>\n", SOFTBUS_SERVICE);
128     CLIENT_NotifyObserver(EVENT_SERVER_RECOVERY, NULL, 0);
129     UnregisterServerDeathCb();
130 
131     if (RegisterServerDeathCb() != SOFTBUS_OK) {
132         COMM_LOGE(COMM_SDK, "reg server death cb failed");
133         return NULL;
134     }
135 
136     return NULL;
137 }
138 
StartDeathProcTask(void)139 static int StartDeathProcTask(void)
140 {
141     int ret;
142     SoftBusThreadAttr threadAttr;
143     SoftBusThread tid;
144     ret = SoftBusThreadAttrInit(&threadAttr);
145     if (ret != 0) {
146         COMM_LOGE(COMM_SDK, "Thread attr init failed, ret=%{public}d", ret);
147         return SOFTBUS_ERR;
148     }
149 
150     threadAttr.detachState = SOFTBUS_THREAD_DETACH;
151     threadAttr.policy = SOFTBUS_SCHED_RR;
152     threadAttr.taskName = "OS_deathTsk";
153     ret = SoftBusThreadCreate(&tid, &threadAttr, DeathProcTask, NULL);
154     if (ret != 0) {
155         COMM_LOGE(COMM_SDK, "create DeathProcTask failed, ret=%{public}d", ret);
156         return SOFTBUS_ERR;
157     }
158 
159     return ret;
160 }
161 
DeathCallback(void)162 static void DeathCallback(void)
163 {
164     COMM_LOGW(COMM_SDK, "\n<< ATTENTION !!! >> SERVICE (%{public}s) DEAD !!!\n", SOFTBUS_SERVICE);
165 
166     if (StartDeathProcTask() != SOFTBUS_OK) {
167         COMM_LOGE(COMM_SDK, "start death proc task failed");
168     }
169     COMM_LOGI(COMM_SDK, "client start check softbus server...");
170 }
171 
RegisterServerDeathCb(void)172 static int RegisterServerDeathCb(void)
173 {
174     g_svcIdentity = SAMGR_GetRemoteIdentity(SOFTBUS_SERVICE, NULL);
175     g_deathCbId = INVALID_CB_ID;
176     if (AddDeathRecipient(g_svcIdentity, DeathCallback, NULL, &g_deathCbId) != EC_SUCCESS) {
177         COMM_LOGE(COMM_SDK, "reg death callback failed");
178         return SOFTBUS_ERR;
179     }
180     return SOFTBUS_OK;
181 }
182 
ClientStubInit(void)183 int ClientStubInit(void)
184 {
185     if (ServerProxyInit() != SOFTBUS_OK) {
186         COMM_LOGE(COMM_SDK, "server proxy init failed.");
187         return SOFTBUS_ERR;
188     }
189 
190     static IpcObjectStub objectStub = {
191         .func = ClientIpcInterfaceMsgHandle,
192         .args = NULL,
193         .isRemote = false
194     };
195     SvcIdentity clientIdentity = {
196         .handle = IPC_INVALID_HANDLE,
197         .token = SERVICE_TYPE_ANONYMOUS,
198         .cookie = (uintptr_t)&objectStub
199     };
200 
201     int ret = ClientContextInit();
202     if (ret != SOFTBUS_OK) {
203         COMM_LOGE(COMM_SDK, "client context init failed.");
204         return SOFTBUS_ERR;
205     }
206     SetClientIdentity(clientIdentity.handle, clientIdentity.token, clientIdentity.cookie);
207     if (RegisterServerDeathCb() != SOFTBUS_OK) {
208         ClientContextDeinit();
209         COMM_LOGE(COMM_SDK, "reg server death cb failed");
210         return SOFTBUS_ERR;
211     }
212 
213     return SOFTBUS_OK;
214 }
215 
ClientRegisterService(const char * pkgName)216 int ClientRegisterService(const char *pkgName)
217 {
218     struct CommonScvId svcId = {0};
219     if (GetClientIdentity(&svcId.handle, &svcId.token, &svcId.cookie) != SOFTBUS_OK) {
220         COMM_LOGE(COMM_SDK, "get client identity failed");
221         return SOFTBUS_ERR;
222     }
223 
224     while (RegisterService(pkgName, &svcId) != SOFTBUS_OK) {
225         SoftBusSleepMs(WAIT_SERVER_READY_INTERVAL);
226     }
227 
228     COMM_LOGI(COMM_SDK, "ClientRegisterService success");
229     return SOFTBUS_OK;
230 }
231