• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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