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 }
95
CloseSocket(int32_t socketId)96 void CloseSocket(int32_t socketId)
97 {
98 ANS_LOGI("Close socket id %{public}d", socketId);
99 ::Shutdown(socketId);
100 }
101
CheckAndCopyStr(char * dest,uint32_t destLen,const std::string & src)102 bool CheckAndCopyStr(char* dest, uint32_t destLen, const std::string& src)
103 {
104 if (destLen < src.length() + 1) {
105 return false;
106 }
107 if (strcpy_s(dest, destLen, src.c_str()) != EOK) {
108 return false;
109 }
110 return true;
111 }
112
ServiceListen(const std::string & name,const std::string & pkgName,TransDataType dataType,int32_t & socketId)113 int32_t ServiceListen(const std::string& name, const std::string& pkgName, TransDataType dataType, int32_t& socketId)
114 {
115 char nameStr[SOCKET_NAME_MAX_LEN + 1];
116 if (!CheckAndCopyStr(nameStr, SOCKET_NAME_MAX_LEN, name)) {
117 return DISRTIBUED_ERR;
118 }
119
120 char pkgNameStr[SOCKET_NAME_MAX_LEN + 1];
121 if (!CheckAndCopyStr(pkgNameStr, SOCKET_NAME_MAX_LEN, pkgName)) {
122 return DISRTIBUED_ERR;
123 }
124
125 SocketInfo info = { .name = nameStr, .pkgName = pkgNameStr, .dataType = dataType };
126 socketId = ::Socket(info); // create service socket id
127 if (socketId <= 0) {
128 ANS_LOGW("Create socket faild, %{public}s %{public}s %{public}d.", nameStr, pkgNameStr, socketId);
129 return DISRTIBUED_SOCKET_CREATE_ERR;
130 }
131
132 QosTV serverQos[] = {
133 { .qos = QOS_TYPE_MIN_BW, .value = 64*1024 },
134 { .qos = QOS_TYPE_MAX_LATENCY, .value = 10000 },
135 { .qos = QOS_TYPE_MIN_LATENCY, .value = 2000 },
136 };
137 ISocketListener listener;
138 listener.OnBind = OnServerBind; // only service may receive OnBind
139 listener.OnQos = OnQos; // only service may receive OnBind
140 listener.OnShutdown = OnServerShutdown;
141 listener.OnBytes = OnServerBytes;
142 listener.OnMessage = OnServerMessage;
143 int32_t ret = ::Listen(socketId, serverQos, 3, &listener);
144 if (ret != ERR_OK) {
145 ::Shutdown(socketId);
146 ANS_LOGW("Create listener failed, ret is %{public}d.", ret);
147 return ret;
148 }
149 ANS_LOGI("Service listen %{public}s %{public}d %{public}d.", name.c_str(), dataType, socketId);
150 return ERR_OK;
151 }
152
ClientBind(const std::string & name,const std::string & pkgName,const std::string & peerNetWorkId,TransDataType dataType,int32_t & socketId)153 int32_t ClientBind(const std::string& name, const std::string& pkgName,
154 const std::string& peerNetWorkId, TransDataType dataType, int32_t& socketId)
155 {
156 char nameStr[SOCKET_NAME_MAX_LEN + 1];
157 char peerNetWorkIdStr[SOCKET_NAME_MAX_LEN + 1];
158 if (!CheckAndCopyStr(nameStr, SOCKET_NAME_MAX_LEN, name) ||
159 !CheckAndCopyStr(peerNetWorkIdStr, SOCKET_NAME_MAX_LEN, peerNetWorkId)) {
160 return DISRTIBUED_ERR;
161 }
162 char pkgNameStr[SOCKET_NAME_MAX_LEN + 1];
163 char peerNameStr[SOCKET_NAME_MAX_LEN + 1];
164 if (!CheckAndCopyStr(pkgNameStr, SOCKET_NAME_MAX_LEN, pkgName) ||
165 !CheckAndCopyStr(peerNameStr, SOCKET_NAME_MAX_LEN, name)) {
166 return DISRTIBUED_ERR;
167 }
168 SocketInfo info = { .name = nameStr, .peerName = peerNameStr, .peerNetworkId = peerNetWorkIdStr,
169 .pkgName = pkgNameStr, .dataType = dataType };
170 socketId = ::Socket(info); // create client socket id
171 if (socketId <= 0) {
172 ANS_LOGW("Create client socket faild, ret is %{public}d.", socketId);
173 return DISRTIBUED_SOCKET_CREATE_ERR;
174 }
175
176 QosTV clientQos[] = {
177 { .qos = QOS_TYPE_MIN_BW, .value = 64*1024 }, { .qos = QOS_TYPE_MAX_LATENCY, .value = 10000 },
178 { .qos = QOS_TYPE_MIN_LATENCY, .value = 2000 }, { .qos = QOS_TYPE_TRANS_CONTINUOUS, .value = 1 },
179 { .qos = QOS_TYPE_MAX_IDLE_TIMEOUT, .value = 600000 },
180 };
181 ISocketListener listener;
182 listener.OnQos = OnQos;
183 listener.OnShutdown = OnClientShutdown;
184 listener.OnBytes = OnClientBytes;
185
186 // retry 10 times or bind success
187 int32_t result = 0;
188 int32_t retryTimes = 0;
189 auto sleepTime = std::chrono::milliseconds(BIND_SERVICE_SLEEP_TIMES_MS);
190 bool bindSuccess = false;
191 while (retryTimes < BIND_SERVICE_MAX_RETRY_TIMES) {
192 result = ::Bind(socketId, clientQos, QOS_NUM, &listener);
193 if (result != 0) {
194 ANS_LOGE("Bind Server failed, ret is %{public}d.", result);
195 retryTimes++;
196 continue;
197 }
198 bindSuccess = true;
199 break;
200 }
201
202 if (!bindSuccess) {
203 ::Shutdown(socketId); // close client.
204 return result;
205 }
206 return ERR_OK;
207 }
208
ClientSendBytes(int32_t socketId,const void * data,uint32_t length)209 int32_t ClientSendBytes(int32_t socketId, const void* data, uint32_t length)
210 {
211 int32_t result = ::SendBytes(socketId, data, length);
212 ANS_LOGI("Socket send byte %{public}d %{public}d %{public}d ", socketId, length, result);
213 return result;
214 }
215
ClientSendMessage(int32_t socketId,const void * data,uint32_t length)216 int32_t ClientSendMessage(int32_t socketId, const void* data, uint32_t length)
217 {
218 int32_t result = ::SendMessage(socketId, data, length);
219 ANS_LOGI("Socket send message %{public}d %{public}d %{public}d ", socketId, length, result);
220 return result;
221 }
222
223 }
224 }
225