• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #define LOG_TAG "SoftBusClient"
17 
18 #include "softbus_client.h"
19 
20 #include "communicator_context.h"
21 #include "communication/connect_manager.h"
22 #include "inner_socket.h"
23 #include "log_print.h"
24 #include "softbus_error_code.h"
25 #include "utils/anonymous.h"
26 
27 namespace OHOS::AppDistributedKv {
28 using namespace OHOS::DistributedKv;
29 using namespace OHOS::DistributedData;
30 
SoftBusClient(const PipeInfo & pipeInfo,const DeviceId & deviceId,const std::string & networkId,uint32_t type,const SessionAccessInfo & accessInfo)31 SoftBusClient::SoftBusClient(const PipeInfo& pipeInfo, const DeviceId& deviceId, const std::string& networkId,
32     uint32_t type, const SessionAccessInfo &accessInfo) : type_(type), pipe_(pipeInfo), device_(deviceId),
33     networkId_(networkId), accessInfo_(accessInfo)
34 {
35     mtu_ = DEFAULT_MTU_SIZE;
36 }
37 
~SoftBusClient()38 SoftBusClient::~SoftBusClient()
39 {
40     ZLOGI("Shutdown socket:%{public}d, deviceId:%{public}s", socket_, Anonymous::Change(device_.deviceId).c_str());
41     if (socket_ > 0) {
42         Shutdown(socket_);
43     }
44 }
45 
operator ==(int32_t socket) const46 bool SoftBusClient::operator==(int32_t socket) const
47 {
48     return socket_ == socket;
49 }
50 
operator ==(const std::string & deviceId) const51 bool SoftBusClient::operator==(const std::string &deviceId) const
52 {
53     return device_.deviceId == deviceId;
54 }
55 
GetMtuBuffer() const56 uint32_t SoftBusClient::GetMtuBuffer() const
57 {
58     ZLOGD("get mtu size socket:%{public}d mtu:%{public}d", socket_, mtu_);
59     return mtu_;
60 }
61 
GetTimeout() const62 uint32_t SoftBusClient::GetTimeout() const
63 {
64     return DEFAULT_TIMEOUT;
65 }
66 
SendData(const DataInfo & dataInfo)67 Status SoftBusClient::SendData(const DataInfo &dataInfo)
68 {
69     std::lock_guard<std::mutex> lock(mutex_);
70     auto result = CheckStatus();
71     if (result != Status::SUCCESS) {
72         return result;
73     }
74     ZLOGD("send data socket:%{public}d, data size:%{public}u.", socket_, dataInfo.length);
75     int32_t ret = SendBytes(socket_, dataInfo.data, dataInfo.length);
76     if (ret != SOFTBUS_OK) {
77         expireTime_ = std::chrono::steady_clock::now();
78         ZLOGE("send data to socket%{public}d failed, ret:%{public}d.", socket_, ret);
79         softBusError_ = ret;
80         return Status::ERROR;
81     }
82     softBusError_ = 0;
83     expireTime_ = CalcExpireTime();
84     return Status::SUCCESS;
85 }
86 
GetSoftBusError()87 int32_t SoftBusClient::GetSoftBusError()
88 {
89     std::lock_guard<std::mutex> lock(mutex_);
90     return softBusError_;
91 }
92 
OpenConnect(const ISocketListener * listener)93 Status SoftBusClient::OpenConnect(const ISocketListener *listener)
94 {
95     std::lock_guard<std::mutex> lock(mutex_);
96     auto status = CheckStatus();
97     if (status == Status::SUCCESS || status == Status::RATE_LIMIT) {
98         return status;
99     }
100     if (isOpening_.exchange(true)) {
101         return Status::RATE_LIMIT;
102     }
103     int32_t clientSocket = CreateSocket();
104     if (clientSocket <= 0) {
105         isOpening_.store(false);
106         return Status::NETWORK_ERROR;
107     }
108     auto task = [type = type_, clientSocket, listener, client = shared_from_this()]() {
109         if (client == nullptr) {
110             ZLOGE("OpenSessionByAsync client is nullptr.");
111             return;
112         }
113         ZLOGI("Bind Start, device:%{public}s socket:%{public}d type:%{public}u",
114             Anonymous::Change(client->device_.deviceId).c_str(), clientSocket, type);
115         int32_t status = client->Open(clientSocket, type, listener);
116         CommunicatorContext::GetInstance().NotifySessionReady(client->device_.deviceId, status);
117         client->isOpening_.store(false);
118     };
119     auto executorPool = CommunicatorContext::GetInstance().GetThreadPool();
120     if (executorPool == nullptr) {
121         return Status::NETWORK_ERROR;
122     }
123     executorPool->Execute(task);
124     return Status::RATE_LIMIT;
125 }
126 
CreateSocket() const127 int32_t SoftBusClient::CreateSocket() const
128 {
129     SocketInfo socketInfo;
130     std::string peerName = pipe_.pipeId;
131     socketInfo.peerName = const_cast<char *>(peerName.c_str());
132     auto networkId = GetNetworkId();
133     socketInfo.peerNetworkId = const_cast<char *>(networkId.c_str());
134     std::string clientName = pipe_.pipeId;
135     socketInfo.name = const_cast<char *>(clientName.c_str());
136     std::string pkgName = "ohos.distributeddata";
137     socketInfo.pkgName = pkgName.data();
138     socketInfo.dataType = DATA_TYPE_BYTES;
139     int32_t socket = Socket(socketInfo);
140     if (socket <= 0) {
141         ZLOGE("Create the client Socket:%{public}d failed, peerName:%{public}s", socket, socketInfo.peerName);
142         return socket;
143     }
144     if (accessInfo_.isOHType) {
145         SocketAccessInfo info;
146         info.userId = accessInfo_.userId;
147         info.localTokenId = accessInfo_.tokenId;
148         AccessExtraInfo extraInfo;
149         extraInfo.bundleName = accessInfo_.bundleName;
150         extraInfo.accountId = accessInfo_.accountId;
151         extraInfo.storeId = accessInfo_.storeId;
152         std::string extraInfoStr = Serializable::Marshall(extraInfo);
153         if (extraInfoStr.empty()) {
154             ZLOGE("Marshall access info fail");
155             return INVALID_SOCKET_ID;
156         }
157         info.extraAccessInfo = const_cast<char *>(extraInfoStr.c_str());
158         auto status = SetAccessInfo(socket, info);
159         if (status != SOFTBUS_OK) {
160             ZLOGE("SetAccessInfo fail, status:%{public}d, userId:%{public}d, bundleName:%{public}s,"
161                 "accountId:%{public}s, storeId:%{public}s", status, info.userId, extraInfo.bundleName.c_str(),
162                 Anonymous::Change(extraInfo.accountId).c_str(), Anonymous::Change(extraInfo.storeId).c_str());
163             return INVALID_SOCKET_ID;
164         }
165     }
166     return socket;
167 }
168 
CheckStatus()169 Status SoftBusClient::CheckStatus()
170 {
171     if (bindState_ == 0) {
172         return Status::SUCCESS;
173     }
174     if (isOpening_.load()) {
175         return Status::RATE_LIMIT;
176     }
177     if (bindState_ == 0) {
178         return Status::SUCCESS;
179     }
180     return Status::ERROR;
181 }
182 
Open(int32_t socket,uint32_t type,const ISocketListener * listener,bool async)183 int32_t SoftBusClient::Open(int32_t socket, uint32_t type, const ISocketListener *listener, bool async)
184 {
185     auto networkId = GetNetworkId();
186     ZLOGI("Bind start, device:%{public}s, networkId:%{public}s, session:%{public}s, socketId:%{public}d",
187         Anonymous::Change(device_.deviceId).c_str(), Anonymous::Change(networkId).c_str(),
188         pipe_.pipeId.c_str(), socket);
189     int32_t status = Bind(socket, QOS_INFOS[type % QOS_BUTT], QOS_COUNTS[type % QOS_BUTT], listener);
190     if (status != SOFTBUS_OK) {
191         ZLOGE("Bind fail, device:%{public}s, networkId:%{public}s, socketId:%{public}d, result:%{public}d",
192             Anonymous::Change(device_.deviceId).c_str(), Anonymous::Change(networkId).c_str(), socket, status);
193         Shutdown(socket);
194         return status;
195     }
196     uint32_t mtu = 0;
197     std::tie(status, mtu) = GetMtu(socket);
198     if (status != SOFTBUS_OK) {
199         ZLOGE("GetMtu failed, session:%{public}s, socket:%{public}d, status:%{public}d", pipe_.pipeId.c_str(), socket_,
200             status);
201         Shutdown(socket);
202         return status;
203     }
204     UpdateBindInfo(socket, mtu, status, async);
205     expireTime_ = CalcExpireTime();
206     ZLOGI("Bind success, device:%{public}s, networkId:%{public}s, session:%{public}s, socketId:%{public}d",
207         Anonymous::Change(device_.deviceId).c_str(), Anonymous::Change(networkId).c_str(),
208         pipe_.pipeId.c_str(), socket);
209     ConnectManager::GetInstance()->OnSessionOpen(networkId);
210     return status;
211 }
212 
GetExpireTime() const213 SoftBusClient::Time SoftBusClient::GetExpireTime() const
214 {
215     std::lock_guard<std::mutex> lock(mutex_);
216     return expireTime_;
217 }
218 
GetSocket() const219 int32_t SoftBusClient::GetSocket() const
220 {
221     return socket_;
222 }
223 
UpdateBindInfo(int32_t socket,uint32_t mtu,int32_t status,bool async)224 void SoftBusClient::UpdateBindInfo(int32_t socket, uint32_t mtu, int32_t status, bool async)
225 {
226     if (async) {
227         std::lock_guard<std::mutex> lock(mutex_);
228         socket_ = socket;
229         mtu_ = mtu;
230         bindState_ = status;
231     } else {
232         socket_ = socket;
233         mtu_ = mtu;
234         bindState_ = status;
235     }
236 }
237 
GetMtu(int32_t socket)238 std::pair<int32_t, uint32_t> SoftBusClient::GetMtu(int32_t socket)
239 {
240     uint32_t mtu = 0;
241     auto ret = GetMtuSize(socket, &mtu);
242     return { ret, mtu };
243 }
244 
GetQoSType() const245 uint32_t SoftBusClient::GetQoSType() const
246 {
247     return type_ % QOS_BUTT;
248 }
249 
CalcExpireTime() const250 SoftBusClient::Time SoftBusClient::CalcExpireTime() const
251 {
252     auto delay = type_ == QOS_BR ? BR_CLOSE_DELAY : HML_CLOSE_DELAY;
253     return std::chrono::steady_clock::now() + delay;
254 }
255 
ReuseConnect(const ISocketListener * listener)256 Status SoftBusClient::ReuseConnect(const ISocketListener *listener)
257 {
258     std::lock_guard<std::mutex> lock(mutex_);
259     auto checkStatus = CheckStatus();
260     if (checkStatus == Status::SUCCESS) {
261         expireTime_ = CalcExpireTime();
262         return Status::SUCCESS;
263     }
264     int32_t socket = CreateSocket();
265     if (socket <= 0) {
266         return Status::NETWORK_ERROR;
267     }
268     ZLOGI("Reuse Start, device:%{public}s session:%{public}s socket:%{public}d",
269         Anonymous::Change(device_.deviceId).c_str(), pipe_.pipeId.c_str(), socket);
270     int32_t status = Open(socket, QOS_REUSE, listener, false);
271     return status == SOFTBUS_OK ? Status::SUCCESS : Status::NETWORK_ERROR;
272 }
273 
GetNetworkId() const274 std::string SoftBusClient::GetNetworkId() const
275 {
276     std::lock_guard<std::mutex> lock(networkIdMutex_);
277     return networkId_;
278 }
279 
UpdateNetworkId(const std::string & networkId)280 void SoftBusClient::UpdateNetworkId(const std::string& networkId)
281 {
282     std::lock_guard<std::mutex> lock(networkIdMutex_);
283     networkId_ = networkId;
284 }
285 } // namespace OHOS::AppDistributedKv