1 /*
2 * Copyright (C) 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 #include "distributed_socket.h"
16
17 #include <thread>
18 #include "socket.h"
19 #include "session.h"
20 #include "distributed_server.h"
21 #include "distributed_client.h"
22 #include "distributed_const_define.h"
23
24 namespace OHOS {
25 namespace Notification {
26
27 static const int32_t BIND_SERVICE_MAX_RETRY_TIMES = 1;
28 static const int32_t BIND_SERVICE_SLEEP_TIMES_MS = 10000; // 0.1s
29 static const uint32_t SOCKET_NAME_MAX_LEN = 256;
30 static const int32_t QOS_NUM = 5;
31
OnServerBind(int32_t socket,PeerSocketInfo info)32 static void OnServerBind(int32_t socket, PeerSocketInfo info)
33 {
34 ANS_LOGI("Socket fd is %{public}d.", socket);
35 if (socket <= 0) {
36 ANS_LOGE("Socket fd invalid.");
37 return;
38 }
39 DistributedServer::GetInstance().OnBind(socket, info);
40 }
41
OnServerShutdown(int32_t socket,ShutdownReason reason)42 static void OnServerShutdown(int32_t socket, ShutdownReason reason)
43 {
44 ANS_LOGI("Socket fd %{public}d shutdown because %{public}d.", socket, (int32_t)(reason));
45 if (socket <= 0) {
46 ANS_LOGE("Socket fd invalid.");
47 return;
48 }
49 DistributedServer::GetInstance().OnShutdown(socket, reason);
50 }
51
OnServerBytes(int32_t socket,const void * data,uint32_t dataLen)52 static void OnServerBytes(int32_t socket, const void *data, uint32_t dataLen)
53 {
54 ANS_LOGI("Socket byte fd %{public}d, recv len %{public}d.", socket, dataLen);
55 if ((socket <= 0) || (data == nullptr) || (dataLen == 0)) {
56 ANS_LOGW("Socket byte invalid data.");
57 return;
58 }
59 DistributedServer::GetInstance().OnBytes(socket, data, dataLen);
60 }
61
OnServerMessage(int32_t socket,const void * data,uint32_t dataLen)62 static void OnServerMessage(int32_t socket, const void *data, uint32_t dataLen)
63 {
64 ANS_LOGI("Socket byte fd %{public}d, recv len %{public}d.", socket, dataLen);
65 if ((socket <= 0) || (data == nullptr) || (dataLen == 0)) {
66 ANS_LOGW("Socket byte invalid data.");
67 return;
68 }
69 DistributedServer::GetInstance().OnMessage(socket, data, dataLen);
70 }
71
OnClientBytes(int32_t socket,const void * data,uint32_t dataLen)72 static void OnClientBytes(int32_t socket, const void *data, uint32_t dataLen)
73 {
74 ANS_LOGI("Socket message fd %{public}d, recv len %{public}d.", socket, dataLen);
75 if ((socket <= 0) || (data == nullptr) || (dataLen == 0)) {
76 ANS_LOGW("Socket message invalid data.");
77 }
78 DistributedServer::GetInstance().OnMessage(socket, data, dataLen);
79 }
80
OnClientShutdown(int32_t socket,ShutdownReason reason)81 static void OnClientShutdown(int32_t socket, ShutdownReason reason)
82 {
83 ANS_LOGI("Socket fd %{public}d shutdown because %{public}d.", socket, (int32_t)(reason));
84 if (socket <= 0) {
85 ANS_LOGE("Socket fd invalid.");
86 return;
87 }
88 DistributedClient::GetInstance().OnShutdown(socket, reason);
89 }
90
OnQos(int32_t socket,QoSEvent eventId,const QosTV * qos,uint32_t qosCount)91 static void OnQos(int32_t socket, QoSEvent eventId, const QosTV *qos, uint32_t qosCount)
92 {
93 ANS_LOGI("OnQos %{public}d %{public}d %{public}d", socket, (int32_t)eventId, (int32_t)(qosCount));
94 for (uint32_t idx = 0; idx < qosCount; idx++) {
95 ANS_LOGI("QosTV: type: %{public}d, value: %{public}d", (int32_t)qos[idx].qos, qos[idx].value);
96 }
97 }
98
CloseSocket(int32_t socketId)99 void CloseSocket(int32_t socketId)
100 {
101 ANS_LOGI("Close socket id %{public}d", socketId);
102 ::Shutdown(socketId);
103 }
104
CheckAndCopyStr(char * dest,uint32_t destLen,const std::string & src)105 bool CheckAndCopyStr(char* dest, uint32_t destLen, const std::string& src)
106 {
107 if (destLen < src.length() + 1) {
108 return false;
109 }
110 if (strcpy_s(dest, destLen, src.c_str()) != EOK) {
111 return false;
112 }
113 return true;
114 }
115
ServiceListen(const std::string & name,const std::string & pkgName,TransDataType dataType,int32_t & socketId)116 int32_t ServiceListen(const std::string& name, const std::string& pkgName, TransDataType dataType, int32_t& socketId)
117 {
118 char nameStr[SOCKET_NAME_MAX_LEN + 1];
119 if (!CheckAndCopyStr(nameStr, SOCKET_NAME_MAX_LEN, name)) {
120 return DISRTIBUED_ERR;
121 }
122
123 char pkgNameStr[SOCKET_NAME_MAX_LEN + 1];
124 if (!CheckAndCopyStr(pkgNameStr, SOCKET_NAME_MAX_LEN, pkgName)) {
125 return DISRTIBUED_ERR;
126 }
127
128 SocketInfo info = { .name = nameStr, .pkgName = pkgNameStr, .dataType = dataType };
129 socketId = ::Socket(info); // create service socket id
130 if (socketId <= 0) {
131 ANS_LOGW("Create socket faild, %{public}s %{public}s %{public}d.", nameStr, pkgNameStr, socketId);
132 return DISRTIBUED_SOCKET_CREATE_ERR;
133 }
134
135 QosTV serverQos[] = {
136 { .qos = QOS_TYPE_MIN_BW, .value = 64*1024 },
137 { .qos = QOS_TYPE_MAX_LATENCY, .value = 10000 },
138 { .qos = QOS_TYPE_MIN_LATENCY, .value = 2000 },
139 };
140 ISocketListener listener;
141 listener.OnBind = OnServerBind; // only service may receive OnBind
142 listener.OnQos = OnQos; // only service may receive OnBind
143 listener.OnShutdown = OnServerShutdown;
144 listener.OnBytes = OnServerBytes;
145 listener.OnMessage = OnServerMessage;
146 int32_t ret = ::Listen(socketId, serverQos, 3, &listener);
147 if (ret != ERR_OK) {
148 ::Shutdown(socketId);
149 ANS_LOGW("Create listener failed, ret is %{public}d.", ret);
150 return ret;
151 }
152 ANS_LOGI("Service listen %{public}s %{public}d %{public}d.", name.c_str(), dataType, socketId);
153 return ERR_OK;
154 }
155
ClientBind(const std::string & name,const std::string & pkgName,const std::string & peerNetWorkId,TransDataType dataType,int32_t & socketId)156 int32_t ClientBind(const std::string& name, const std::string& pkgName,
157 const std::string& peerNetWorkId, TransDataType dataType, int32_t& socketId)
158 {
159 char nameStr[SOCKET_NAME_MAX_LEN + 1];
160 char peerNetWorkIdStr[SOCKET_NAME_MAX_LEN + 1];
161 if (!CheckAndCopyStr(nameStr, SOCKET_NAME_MAX_LEN, name) ||
162 !CheckAndCopyStr(peerNetWorkIdStr, SOCKET_NAME_MAX_LEN, peerNetWorkId)) {
163 return DISRTIBUED_ERR;
164 }
165 char pkgNameStr[SOCKET_NAME_MAX_LEN + 1];
166 char peerNameStr[SOCKET_NAME_MAX_LEN + 1];
167 if (!CheckAndCopyStr(pkgNameStr, SOCKET_NAME_MAX_LEN, pkgName) ||
168 !CheckAndCopyStr(peerNameStr, SOCKET_NAME_MAX_LEN, name)) {
169 return DISRTIBUED_ERR;
170 }
171 SocketInfo info = { .name = nameStr, .peerName = peerNameStr, .peerNetworkId = peerNetWorkIdStr,
172 .pkgName = pkgNameStr, .dataType = dataType };
173 socketId = ::Socket(info); // create client socket id
174 if (socketId <= 0) {
175 ANS_LOGW("Create client socket faild, ret is %{public}d.", socketId);
176 return DISRTIBUED_SOCKET_CREATE_ERR;
177 }
178
179 QosTV clientQos[] = {
180 { .qos = QOS_TYPE_MIN_BW, .value = 64*1024 }, { .qos = QOS_TYPE_MAX_LATENCY, .value = 10000 },
181 { .qos = QOS_TYPE_MIN_LATENCY, .value = 2000 }, { .qos = QOS_TYPE_TRANS_CONTINUOUS, .value = 1 },
182 { .qos = QOS_TYPE_MAX_IDLE_TIMEOUT, .value = 600000 },
183 };
184 ISocketListener listener;
185 listener.OnQos = OnQos;
186 listener.OnShutdown = OnClientShutdown;
187 listener.OnBytes = OnClientBytes;
188
189 // retry 10 times or bind success
190 int32_t result = 0;
191 int32_t retryTimes = 0;
192 auto sleepTime = std::chrono::milliseconds(BIND_SERVICE_SLEEP_TIMES_MS);
193 bool bindSuccess = false;
194 while (retryTimes < BIND_SERVICE_MAX_RETRY_TIMES) {
195 result = ::Bind(socketId, clientQos, QOS_NUM, &listener);
196 if (result != 0) {
197 ANS_LOGE("Bind Server failed, ret is %{public}d.", result);
198 retryTimes++;
199 continue;
200 }
201 bindSuccess = true;
202 break;
203 }
204
205 if (!bindSuccess) {
206 ::Shutdown(socketId); // close client.
207 return result;
208 }
209 return ERR_OK;
210 }
211
ClientSendMsg(int32_t socketId,const void * data,int32_t length,TransDataType type)212 int32_t ClientSendMsg(int32_t socketId, const void* data, int32_t length, TransDataType type)
213 {
214 int32_t result = 0;
215 if (type == TransDataType::DATA_TYPE_BYTES) {
216 result = ::SendBytes(socketId, data, length);
217 } else if (type == TransDataType::DATA_TYPE_MESSAGE) {
218 result = ::SendMessage(socketId, data, length);
219 }
220 ANS_LOGI("socket Send %{public}d %{public}d %{public}d %{public}d", socketId, length, type, result);
221 return result;
222 }
223
224 }
225 }
226