• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #include "map_mse_mnscli.h"
17 #include <memory>
18 #include "btm.h"
19 #include "log.h"
20 #include "map_mse_params.h"
21 #include "map_mse_types.h"
22 #include "securec.h"
23 #include "stub/map_service.h"
24 
25 namespace OHOS {
26 namespace bluetooth {
27 const uint8_t MapMseMnscli::MNS_TARGET[16] = {
28     0xbb, 0x58, 0x2b, 0x41, 0x42, 0x0c, 0x11, 0xdb, 0xb0, 0xde, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
29 };
30 const std::string MapMseMnscli::HEADER_TYPE_EVENT = "x-bt/MAP-event-report";
31 const uint16_t MapMseMnscli::SERVICE_CLASS_UUID;
32 
MapMseMnscli(utility::Dispatcher & dispatcher,MnsObserver & mnsObserver)33 MapMseMnscli::MapMseMnscli(utility::Dispatcher &dispatcher, MnsObserver &mnsObserver)
34     : dispatcher_(dispatcher), mnsObserver_(mnsObserver)
35 {
36     std::lock_guard<std::recursive_mutex> lock(mnsMapMutex_);
37     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
38 
39     clientObserver_ = std::make_unique<MseClientObserver>(*this);
40     ObexClient::RegisterL2capLPsm(GOEP_L2CAP_LPSM);
41 }
42 
~MapMseMnscli()43 MapMseMnscli::~MapMseMnscli()
44 {
45     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
46 
47     obexConfigMap_.clear();
48     obexClientMap_.clear();
49     connectionIdMap_.clear();
50     remoteFeatures_.clear();
51 }
52 
DeregisterL2capLPsm(void) const53 void MapMseMnscli::DeregisterL2capLPsm(void) const
54 {
55     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
56 
57     ObexClient::DeregisterL2capLPsm(GOEP_L2CAP_LPSM);
58 }
59 
GetConnectionId(const std::string & address) const60 uint32_t MapMseMnscli::GetConnectionId(const std::string &address) const
61 {
62     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
63 
64     uint32_t connectionId = 0;
65     if (auto iter = connectionIdMap_.find(address); iter != connectionIdMap_.end()) {
66         connectionId = iter->second;
67     }
68     return connectionId;
69 }
70 
Connect(const RawAddress & remoteAddr,int masId)71 int MapMseMnscli::Connect(const RawAddress &remoteAddr, int masId)
72 {
73     std::lock_guard<std::recursive_mutex> lock(mnsMapMutex_);
74     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
75 
76     std::string address = remoteAddr.GetAddress();
77     if (masIds_.find(address) == masIds_.end()) {
78         masIds_[address] = masId + 1;
79     } else {
80         masIds_[address] = masIds_[address] + (masId + 1);
81     }
82     if (connectionIdMap_.find(address) != connectionIdMap_.end()) {
83         return Result::SUCCEED;
84     }
85     if (mnsStateMap_.find(address) != mnsStateMap_.end()) {
86         if (mnsStateMap_[address] == BTConnectState::CONNECTING) {
87             return Result::SUCCEED;
88         }
89     }
90     mnsStateMap_[address] = BTConnectState::CONNECTING;
91     if (auto iter = obexConfigMap_.find(address); iter != obexConfigMap_.end()) {
92         if (Result::SUCCEED != RegistGap(remoteAddr, iter->second.isGoepL2capPSM_, iter->second.scn_)) {
93             MSE_LOG_INFO("Gap Regist failed.");
94             return Result::FAIL;
95         }
96         auto obexMpClient = std::make_unique<ObexMpClient>(iter->second, *clientObserver_, dispatcher_);
97         if (!obexMpClient->Connect()) {
98             obexClientMap_[address] = std::move(obexMpClient);
99         } else {
100             MSE_LOG_INFO("MNS connection failed.");
101             return Result::FAIL;
102         }
103     }
104     return Result::SUCCEED;
105 }
106 
RegistGap(const RawAddress & remoteAddr,bool isL2cap,uint16_t scn) const107 int MapMseMnscli::RegistGap(const RawAddress &remoteAddr, bool isL2cap, uint16_t scn) const
108 {
109     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
110 
111     BtAddr address;
112     address.type = BT_PUBLIC_DEVICE_ADDRESS;
113     remoteAddr.ConvertToUint8(address.addr, sizeof(address.addr));
114     GapSecChannel gapChannel = {.l2capPsm = scn};
115     if (!isL2cap) {
116         gapChannel.rfcommChannel = static_cast<uint8_t>(scn);
117     }
118     GapServiceSecurityInfo serviceInfo = {
119         .direction = OUTGOING,
120         .serviceId = GAP_Service(MAP_SERVER_ID_START + MAP_MAX_COUNT),
121         .protocolId = isL2cap ? GAP_SecMultiplexingProtocol::SEC_PROTOCOL_L2CAP
122                               : GAP_SecMultiplexingProtocol::SEC_PROTOCOL_RFCOMM,
123         .channelId = gapChannel
124     };
125     if (GAPIF_RegisterServiceSecurity(&address,
126         &serviceInfo,
127         GAP_SEC_IN_AUTHENTICATION | GAP_SEC_IN_ENCRYPTION | GAP_SEC_OUT_AUTHENTICATION | GAP_SEC_OUT_ENCRYPTION)) {
128         MSE_LOG_INFO("Call GAP_RegisterServiceSecurity Error");
129         return Result::FAIL;
130     }
131     return Result::SUCCEED;
132 }
133 
UnRegistGap(const RawAddress & remoteAddr,bool isL2cap,uint16_t scn) const134 void MapMseMnscli::UnRegistGap(const RawAddress &remoteAddr, bool isL2cap, uint16_t scn) const
135 {
136     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
137 
138     BtAddr address;
139     address.type = BT_PUBLIC_DEVICE_ADDRESS;
140     remoteAddr.ConvertToUint8(address.addr, sizeof(address.addr));
141     uint8_t rfcommno = 0;
142     if (!isL2cap) {
143         rfcommno = static_cast<uint8_t>(scn);
144         BTM_RemoveRemoteRfcommScnChannelForLogging(BTM_HCI_LOG_FILTER_MODULE_MAP, rfcommno, &address);
145     } else {
146         BTM_RemoveRemoteL2capPsmForLogging(BTM_HCI_LOG_FILTER_MODULE_MAP, scn, &address);
147     }
148 
149     GapServiceSecurityInfo serviceInfo = {
150         .direction = OUTGOING,
151         .serviceId = GAP_Service(MAP_SERVER_ID_START + MAP_MAX_COUNT),
152         .protocolId = isL2cap ? GAP_SecMultiplexingProtocol::SEC_PROTOCOL_L2CAP
153                               : GAP_SecMultiplexingProtocol::SEC_PROTOCOL_RFCOMM,
154         .channelId = isL2cap ? GapSecChannel{.l2capPsm = scn} : GapSecChannel{.rfcommChannel = rfcommno}
155     };
156     if (GAPIF_DeregisterServiceSecurity(&address, &serviceInfo)) {
157         MSE_LOG_INFO("Call GAP_UnregisterServiceSecurity Error");
158     }
159 }
160 
DisConnect(const RawAddress & remoteAddr,int masId)161 void MapMseMnscli::DisConnect(const RawAddress &remoteAddr, int masId)
162 {
163     std::lock_guard<std::recursive_mutex> lock(mnsMapMutex_);
164     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
165 
166     std::string address = remoteAddr.GetAddress();
167     if (masIds_.find(address) != masIds_.end()) {
168         masIds_[address] = masIds_[address] - (masId + 1);
169         if (masIds_[address] == 0) {
170             masIds_.erase(address);
171         } else {
172             return;
173         }
174     } else {
175         return;
176     }
177 
178     if (mnsStateMap_.find(address) != mnsStateMap_.end()) {
179         if (mnsStateMap_[address] == BTConnectState::DISCONNECTING) {
180             return;
181         }
182     }
183     if (auto iter = obexClientMap_.find(address); iter != obexClientMap_.end()) {
184         mnsStateMap_[address] = BTConnectState::DISCONNECTING;
185         if (RET_NO_ERROR != iter->second->Disconnect()) {
186             mnsStateMap_[address] = BTConnectState::DISCONNECTED;
187         }
188     }
189     MSE_LOG_INFO("%{public}s End", __PRETTY_FUNCTION__);
190 }
191 
SendEvent(const RawAddress & bda,const std::string & report,size_t reportSize,uint8_t masInstanceId)192 int MapMseMnscli::SendEvent(const RawAddress &bda, const std::string &report, size_t reportSize, uint8_t masInstanceId)
193 {
194     std::lock_guard<std::recursive_mutex> lock(mnsMapMutex_);
195     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
196 
197     std::string addr = bda.GetAddress();
198     if (mnsStateMap_.find(addr) != mnsStateMap_.end()) {
199         if (mnsStateMap_[addr] != BTConnectState::CONNECTED) {
200             return Result::FAIL;
201         }
202     }
203     if (auto iter = obexClientMap_.find(addr); iter != obexClientMap_.end()) {
204         ObexTlvParamters appPara {};
205         std::unique_ptr<ObexHeader> header = ObexHeader::CreateRequest(ObexOpeId::PUT_FINAL);
206         header->AppendItemConnectionId(GetConnectionId(bda.GetAddress()));
207         header->AppendItemSrm(true);
208         header->AppendItemType(HEADER_TYPE_EVENT);
209         ObexTlvParamters appParams {};
210         appParams.AppendTlvtriplet(TlvTriplet(MapMseParams::PARAM_MAS_INSTANCEID, masInstanceId));
211         header->AppendItemAppParams(appParams);
212         auto bodyObj = std::make_shared<ObexArrayBodyObject>();
213         bodyObj->Write((uint8_t *)report.data(), reportSize);
214         auto ret = iter->second->Put(*header, bodyObj);
215         return ret ? Result::SUCCEED : Result::FAIL;
216     }
217     return Result::FAIL;
218 }
219 
PostCallback(const RawAddress & remoteAddr,ObexClientConfig clientConfig,uint32_t remoteFeature)220 void MapMseMnscli::PostCallback(const RawAddress &remoteAddr, ObexClientConfig clientConfig, uint32_t remoteFeature)
221 {
222     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
223 
224     dispatcher_.PostTask(std::bind(&MapMseMnscli::SaveClientConfig, this, remoteAddr, clientConfig, remoteFeature));
225 }
226 
SaveClientConfig(const RawAddress & remoteAddr,ObexClientConfig clientConfig,uint32_t remoteFeature)227 void MapMseMnscli::SaveClientConfig(const RawAddress &remoteAddr, ObexClientConfig clientConfig, uint32_t remoteFeature)
228 {
229     std::lock_guard<std::recursive_mutex> lock(mnsMapMutex_);
230     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
231 
232     std::string address = remoteAddr.GetAddress();
233     obexConfigMap_[address] = clientConfig;
234     remoteFeatures_[address] = remoteFeature;
235 }
236 
GetRfcommNo(const SdpService & serviceAry,uint8_t & rfcommNo)237 void MapMseMnscli::GetRfcommNo(const SdpService &serviceAry, uint8_t &rfcommNo)
238 {
239     SdpProtocolDescriptor *descriptor = serviceAry.descriptor;
240     for (auto descriptorCount = 0; descriptorCount < serviceAry.descriptorNumber; ++descriptorCount, ++descriptor) {
241         if (descriptor->protocolUuid.uuid16 == UUID_PROTOCOL_RFCOMM) {
242             if (&(descriptor->parameter[0]) != nullptr) {
243                 rfcommNo = descriptor->parameter[0].value;
244                 break;
245             }
246         }
247     }
248 }
249 
GetVersionNumber(const SdpService & serviceAry,uint16_t & versionNumber)250 void MapMseMnscli::GetVersionNumber(const SdpService &serviceAry, uint16_t &versionNumber)
251 {
252     SdpProfileDescriptor *profileDescriptor = serviceAry.profileDescriptor;
253     for (auto profileCount = 0; profileCount < serviceAry.profileDescriptorNumber;
254          ++profileCount, ++profileDescriptor) {
255         if (profileDescriptor->profileUuid.uuid16 == MAP_PROFILE_DESCRIPTOR_UUID) {
256             versionNumber = profileDescriptor->versionNumber;
257             break;
258         }
259     }
260 }
261 
GetPsmRemoteFeature(const SdpService & serviceAry,uint16_t & psm,uint32_t & remoteFeature)262 void MapMseMnscli::GetPsmRemoteFeature(const SdpService &serviceAry, uint16_t &psm, uint32_t &remoteFeature)
263 {
264     SdpAttribute *attribute = serviceAry.attribute;
265     for (auto attSeqCount = 0; attSeqCount < serviceAry.attributeNumber; ++attSeqCount, ++attribute) {
266         if (attribute->attributeId == GOEP_L2CAP_PSM_ATTRIBUTE_ID) {
267             psm = *(uint16_t *)attribute->attributeValue;
268         } else if (attribute->attributeId == MAP_SUPPORTED_FEATURES_ATTRIBUTE_ID) {
269             remoteFeature = *(uint32_t *)attribute->attributeValue;
270         }
271     }
272 }
273 
SdpSearchCallback(const BtAddr * addr,const SdpService * serviceAry,uint16_t serviceNum,void * context)274 void MapMseMnscli::SdpSearchCallback(
275     const BtAddr *addr, const SdpService *serviceAry, uint16_t serviceNum, void *context)
276 {
277     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
278 
279     uint8_t rfcommNo = 0;
280     uint16_t psm = 0;
281     uint16_t versionNumber = 0;
282     ObexClientConfig obexConfig;
283     obexConfig.serviceUUID_.type = BT_UUID_128;
284     (void)memcpy_s(
285         obexConfig.serviceUUID_.uuid128,
286         sizeof(obexConfig.serviceUUID_.uuid128),
287         MNS_TARGET,
288         sizeof(MNS_TARGET));
289     obexConfig.addr_ = *addr;
290     if (serviceAry == nullptr) {
291         return;
292     }
293     uint32_t remoteFeature = MAP_SUPPORTED_FEATURES_DEFAULT;
294     for (uint16_t serviceCount = 0; serviceCount < serviceNum; ++serviceCount, ++serviceAry) {
295         if (serviceAry->classId->uuid16 != SERVICE_CLASS_UUID) {
296             continue;
297         }
298         GetRfcommNo(*serviceAry, rfcommNo);
299         GetVersionNumber(*serviceAry, versionNumber);
300         GetPsmRemoteFeature(*serviceAry, psm, remoteFeature);
301         if (psm != 0) {
302 #ifdef MAP_MSE_L2CAP_ENABLE
303             obexConfig.isGoepL2capPSM_ = true;
304 #else
305             obexConfig.isGoepL2capPSM_ = false;
306 #endif
307             obexConfig.lpsm_ = GOEP_L2CAP_LPSM;
308         }
309     }
310     if (versionNumber != 0 && (psm != 0 || rfcommNo != 0)) {
311         if (obexConfig.isGoepL2capPSM_) {
312             obexConfig.scn_ = psm;
313             obexConfig.mtu_ = OBEX_DEFAULT_MTU;
314             BTM_AddRemoteL2capPsmForLogging(BTM_HCI_LOG_FILTER_MODULE_MAP, psm, addr);
315         } else {
316             obexConfig.scn_ = rfcommNo;
317             obexConfig.mtu_ = OBEX_DEFAULT_MTU;
318             BTM_AddRemoteRfcommScnForLogging(BTM_HCI_LOG_FILTER_MODULE_MAP, rfcommNo, addr);
319         }
320     }
321     auto mnsClient = static_cast<MapMseMnscli *>(context);
322     mnsClient->PostCallback(RawAddress::ConvertToString(addr->addr), obexConfig, remoteFeature);
323 }
324 
GetRemoteFeatures(const std::string & addr)325 uint32_t MapMseMnscli::GetRemoteFeatures(const std::string &addr)
326 {
327     std::lock_guard<std::recursive_mutex> lock(mnsMapMutex_);
328     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
329 
330     uint32_t ret = 0x0;
331     if (remoteFeatures_.find(addr) != remoteFeatures_.end()) {
332         ret = remoteFeatures_[addr];
333     }
334     return ret;
335 }
336 
IsDisconnected(void) const337 bool MapMseMnscli::IsDisconnected(void) const
338 {
339     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
340 
341     bool ret = true;
342     for (auto &state : mnsStateMap_) {
343         if (BTConnectState::DISCONNECTED != state.second) {
344             ret = false;
345         }
346     }
347     return ret;
348 }
349 
SdpSearch(const RawAddress & remoteAddr)350 int MapMseMnscli::SdpSearch(const RawAddress &remoteAddr)
351 {
352     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
353 
354     if (obexConfigMap_.find(remoteAddr.GetAddress()) != obexConfigMap_.end()) {
355         return Result::FAIL;
356     }
357     BtAddr address;
358     address.type = BT_PUBLIC_DEVICE_ADDRESS;
359     remoteAddr.ConvertToUint8(address.addr, sizeof(address.addr));
360     BtUuid classid;
361     classid.type = BT_UUID_16;
362     classid.uuid16 = SERVICE_CLASS_UUID;
363     SdpUuid sdpUUid;
364     sdpUUid.uuidNum = 0x0001;
365     sdpUUid.uuid = &classid;
366     SdpAttributeIdList attributeIdList;
367     attributeIdList.type = SDP_TYPE_LIST;
368     attributeIdList.attributeIdList.attributeIdNumber = 0x5;
369     attributeIdList.attributeIdList.attributeId[0x0] = SDP_ATTRIBUTE_SERVICE_CLASS_ID_LIST;
370     attributeIdList.attributeIdList.attributeId[0x1] = SDP_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST;
371     attributeIdList.attributeIdList.attributeId[0x2] = SDP_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST;
372     attributeIdList.attributeIdList.attributeId[0x3] = GOEP_L2CAP_PSM_ATTRIBUTE_ID;
373     attributeIdList.attributeIdList.attributeId[0x4] = MAP_SUPPORTED_FEATURES_ATTRIBUTE_ID;
374     if (SDP_ServiceSearchAttribute(&address, &sdpUUid, attributeIdList, this, MapMseMnscli::SdpSearchCallback)) {
375         MSE_LOG_ERROR("Mns client Call SDP_ServiceSearchAttribute Error");
376         return Result::FAIL;
377     }
378     return Result::SUCCEED;
379 }
380 
MseClientObserver(MapMseMnscli & mnsClient)381 MapMseMnscli::MseClientObserver::MseClientObserver(MapMseMnscli &mnsClient) : mnsClient_(mnsClient)
382 {
383     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
384 }
385 
OnTransportFailed(ObexClient & client,int errCd)386 void MapMseMnscli::MseClientObserver::OnTransportFailed(ObexClient &client, int errCd)
387 {
388     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
389 
390     const RawAddress& remoteAddr = client.GetClientSession().GetRemoteAddr();
391     std::string address = remoteAddr.GetAddress();
392     {
393         std::lock_guard<std::recursive_mutex> lock(mnsClient_.mnsMapMutex_);
394         mnsClient_.mnsStateMap_[address] = BTConnectState::DISCONNECTED;
395     }
396     mnsClient_.RemoveOnConnected(address);
397     mnsClient_.mnsObserver_.OnDisconnected();
398 
399     if (errCd == CONNECT_COLLISION) {
400         mnsClient_.Connect(remoteAddr, mnsClient_.masIds_[address]);
401     }
402 }
403 
OnConnected(ObexClient & client,const ObexHeader & resp)404 void MapMseMnscli::MseClientObserver::OnConnected(ObexClient &client, const ObexHeader &resp)
405 {
406     std::lock_guard<std::recursive_mutex> lock(mnsClient_.mnsMapMutex_);
407     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
408 
409     std::string address = client.GetClientSession().GetRemoteAddr().GetAddress();
410     mnsClient_.mnsStateMap_[address] = BTConnectState::CONNECTED;
411     if (resp.GetItemConnectionId()) {
412         mnsClient_.connectionIdMap_[address] = resp.GetItemConnectionId()->GetWord();
413     }
414     stub::MapService::GetInstance()->EventConnected(address);
415 }
416 
OnConnectFailed(ObexClient & client,const ObexHeader & resp)417 void MapMseMnscli::MseClientObserver::OnConnectFailed(ObexClient &client, const ObexHeader &resp)
418 {
419     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
420 
421     client.Disconnect(false);
422 }
423 
OnDisconnected(ObexClient & client)424 void MapMseMnscli::MseClientObserver::OnDisconnected(ObexClient &client)
425 {
426     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
427 
428     std::string address = client.GetClientSession().GetRemoteAddr().GetAddress();
429     {
430         std::lock_guard<std::recursive_mutex> lock(mnsClient_.mnsMapMutex_);
431         mnsClient_.mnsStateMap_[address] = BTConnectState::DISCONNECTED;
432     }
433     mnsClient_.RemoveOnConnected(address);
434     mnsClient_.mnsObserver_.OnDisconnected();
435     stub::MapService::GetInstance()->EventDisConnected(address);
436 }
437 
OnActionCompleted(ObexClient & client,const ObexHeader & resp)438 void MapMseMnscli::MseClientObserver::OnActionCompleted(ObexClient &client, const ObexHeader &resp)
439 {
440     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
441     MSE_LOG_INFO("MapMseMnscli : Mns Event sent successfully.");
442     std::string address = client.GetClientSession().GetRemoteAddr().GetAddress();
443     stub::MapService::GetInstance()->EventSendComplete(address);
444 }
445 
RemoveOnConnected(std::string address)446 void MapMseMnscli::RemoveOnConnected(std::string address)
447 {
448     std::lock_guard<std::recursive_mutex> lock(mnsMapMutex_);
449     MSE_LOG_INFO("%{public}s Enter", __PRETTY_FUNCTION__);
450 
451     if (auto iter = connectionIdMap_.find(address); iter != connectionIdMap_.end()) {
452         connectionIdMap_.erase(iter);
453     }
454     if (auto config = obexConfigMap_.find(address); config != obexConfigMap_.end()) {
455         UnRegistGap(RawAddress(address), config->second.isGoepL2capPSM_, config->second.scn_);
456     }
457 }
458 }  // namespace bluetooth
459 }  // namespace OHOS