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_client.h"
16
17 #include "socket.h"
18 #include "session.h"
19 #include "distributed_socket.h"
20 #include "distributed_server.h"
21 namespace OHOS {
22 namespace Notification {
23
24 namespace {
25 constexpr const int32_t PUBLISH_ERROR_EVENT_CODE = 0;
26 constexpr const int32_t BRANCH1_ID = 1;
27 constexpr const int32_t BRANCH2_ID = 2;
28 constexpr const int32_t BRANCH4_ID = 4;
29 }
30
GetInstance()31 DistributedClient& DistributedClient::GetInstance()
32 {
33 static DistributedClient distributedClient;
34 return distributedClient;
35 }
36
ReleaseClient()37 void DistributedClient::ReleaseClient()
38 {
39 std::lock_guard<std::mutex> lock(clientLock_);
40 ANS_LOGI("Release client socket %{public}d.", (int32_t)(socketsId_.size()));
41 for (auto& socketItem : socketsId_) {
42 CloseSocket(socketItem.second);
43 }
44 socketsId_.clear();
45 }
46
OnShutdown(int32_t socket,ShutdownReason reason)47 void DistributedClient::OnShutdown(int32_t socket, ShutdownReason reason)
48 {
49 std::lock_guard<std::mutex> lock(clientLock_);
50 for (auto& socketItem : socketsId_) {
51 if (socketItem.second == socket) {
52 socketItem.second = -1;
53 std::string message = "socketID: " + std::to_string(socket) + " ; ShutdownReason: " +
54 ShutdownReasonToString(reason);
55 DistributedService::GetInstance().SendHaReport(0, BRANCH4_ID, message, PUBLISH_ERROR_EVENT_CODE);
56 }
57 }
58 }
59
AddDevice(DistributedDeviceInfo peerDevice)60 void DistributedClient::AddDevice(DistributedDeviceInfo peerDevice)
61 {
62 std::lock_guard<std::mutex> lock(clientLock_);
63 ANS_LOGI("Distributed client AddDevice %{public}s %{public}s", StringAnonymous(peerDevice.deviceId_).c_str(),
64 StringAnonymous(peerDevice.networkId_).c_str());
65 networksId_[peerDevice.deviceId_] = peerDevice.networkId_;
66 }
67
ReleaseDevice(const std::string & deviceId,uint16_t deviceType)68 void DistributedClient::ReleaseDevice(const std::string &deviceId, uint16_t deviceType)
69 {
70 std::string messageKey = deviceId + '_' + std::to_string(TransDataType::DATA_TYPE_MESSAGE);
71 std::string byteKey = deviceId + '_' + std::to_string(TransDataType::DATA_TYPE_BYTES);
72 std::lock_guard<std::mutex> lock(clientLock_);
73 auto socket = socketsId_.find(messageKey);
74 if (socket != socketsId_.end()) {
75 CloseSocket(socket->second);
76 socketsId_.erase(socket);
77 }
78 socket = socketsId_.find(byteKey);
79 if (socket != socketsId_.end()) {
80 CloseSocket(socket->second);
81 socketsId_.erase(socket);
82 }
83 networksId_.erase(deviceId);
84 }
85
RefreshDevice(const std::string & deviceId,uint16_t deviceType,const std::string & networkId)86 void DistributedClient::RefreshDevice(const std::string &deviceId, uint16_t deviceType,
87 const std::string &networkId)
88 {
89 ReleaseDevice(deviceId, deviceType);
90 std::lock_guard<std::mutex> lock(clientLock_);
91 networksId_[deviceId] = networkId;
92 ANS_LOGI("Distributed refresh device %{public}s %{public}s", StringAnonymous(deviceId).c_str(),
93 StringAnonymous(networkId).c_str());
94 }
95
GetSocketId(const std::string & deviceId,uint16_t deviceType,TransDataType dataType,int32_t & socketId)96 int32_t DistributedClient::GetSocketId(const std::string &deviceId, uint16_t deviceType, TransDataType dataType,
97 int32_t& socketId)
98 {
99 std::string key = deviceId + '_' + std::to_string(dataType);
100 {
101 std::lock_guard<std::mutex> lock(clientLock_);
102 auto socketItem = socketsId_.find(key);
103 if (socketItem != socketsId_.end() && socketItem->second != -1) {
104 socketId = socketItem->second;
105 return ERR_OK;
106 }
107 }
108
109 std::string networkId;
110 auto networkIdItem = networksId_.find(deviceId);
111 if (networkIdItem != networksId_.end()) {
112 networkId = networkIdItem->second;
113 }
114 std::string name = (dataType == TransDataType::DATA_TYPE_MESSAGE) ? ANS_SOCKET_CMD : ANS_SOCKET_MSG;
115 int32_t result = ClientBind(name, ANS_SOCKET_PKG, networkId, dataType, socketId);
116 if (result != ERR_OK) {
117 ANS_LOGW("Get socketid failed %{public}s %{public}s %{public}d %{public}d", StringAnonymous(deviceId).c_str(),
118 StringAnonymous(networkId).c_str(), deviceType, dataType);
119 return result;
120 }
121 {
122 std::lock_guard<std::mutex> lock(clientLock_);
123 socketsId_[key] = socketId;
124 ANS_LOGI("Get socketid insert %{public}s %{public}d", key.c_str(), socketId);
125 }
126 return ERR_OK;
127 }
128
SendMessage(const void * data,int32_t length,TransDataType dataType,const std::string & deviceId,uint16_t deviceType)129 int32_t DistributedClient::SendMessage(const void* data, int32_t length, TransDataType dataType,
130 const std::string &deviceId, uint16_t deviceType)
131 {
132 int32_t socketId = 0;
133 DistributedServer::GetInstance().CheckServer();
134 int32_t result = GetSocketId(deviceId, deviceType, dataType, socketId);
135 if (result != ERR_OK) {
136 ANS_LOGW("Get SocketId failed %{public}s %{public}d %{public}d", StringAnonymous(deviceId).c_str(),
137 deviceType, dataType);
138 int32_t messageType = 0;
139 std::string errorReason = "Bind server failed,";
140 errorReason.append("dataType: " + std::to_string(dataType));
141 DistributedService::GetInstance().SendEventReport(messageType, result, errorReason);
142 DistributedService::GetInstance().SendHaReport(result, BRANCH1_ID, errorReason);
143 return result;
144 }
145 result = ClientSendMsg(socketId, data, length, dataType);
146 if (result != ERR_OK) {
147 int32_t messageType = 0;
148 std::string errorReason = "send message failed,";
149 errorReason.append("dataType: " + std::to_string(dataType));
150 DistributedService::GetInstance().SendEventReport(messageType, result, errorReason);
151 DistributedService::GetInstance().SendHaReport(result, BRANCH2_ID, errorReason);
152 }
153 return result;
154 }
155
ShutdownReasonToString(ShutdownReason reason)156 std::string DistributedClient::ShutdownReasonToString(ShutdownReason reason)
157 {
158 switch (reason) {
159 case ShutdownReason::SHUTDOWN_REASON_UNKNOWN:
160 return "SHUTDOWN_REASON_UNKNOWN";
161 case ShutdownReason::SHUTDOWN_REASON_PEER:
162 return "SHUTDOWN_REASON_PEER";
163 case ShutdownReason::SHUTDOWN_REASON_LNN_CHANGED:
164 return "SHUTDOWN_REASON_LNN_CHANGED";
165 case ShutdownReason::SHUTDOWN_REASON_CONN_CHANGED:
166 return "SHUTDOWN_REASON_CONN_CHANGED";
167 case ShutdownReason::SHUTDOWN_REASON_TIMEOUT:
168 return "SHUTDOWN_REASON_TIMEOUT";
169 case ShutdownReason::SHUTDOWN_REASON_SEND_FILE_ERR:
170 return "SHUTDOWN_REASON_SEND_FILE_ERR";
171 case ShutdownReason::SHUTDOWN_REASON_RECV_FILE_ERR:
172 return "SHUTDOWN_REASON_RECV_FILE_ERR";
173 case ShutdownReason::SHUTDOWN_REASON_RECV_DATA_ERR:
174 return "SHUTDOWN_REASON_RECV_DATA_ERR";
175 case ShutdownReason::SHUTDOWN_REASON_UNEXPECTED:
176 return "SHUTDOWN_REASON_UNEXPECTED";
177 default:
178 return "unknown";
179 }
180 }
181
182 }
183 }
184
185