• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-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 #include "obex_client.h"
17 #include <cstring>
18 #include <iostream>
19 #include "buffer.h"
20 #include "log.h"
21 #include "obex_socket_transport.h"
22 #include "obex_utils.h"
23 #include "transport/transport_l2cap.h"
24 
25 namespace OHOS {
26 namespace bluetooth {
ObexClientTransportObserver(ObexClient & obexClient)27 ObexClient::ObexClientTransportObserver::ObexClientTransportObserver(ObexClient &obexClient) : obexClient_(obexClient)
28 {}
29 
OnTransportConnected(ObexTransport & transport)30 void ObexClient::ObexClientTransportObserver::OnTransportConnected(ObexTransport &transport)
31 {
32     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
33     OBEX_LOG_INFO("ClientId: %{public}s", obexClient_.clientId_.c_str());
34     if (!transport.IsConnected()) {
35         obexClient_.clientObserver_.OnTransportFailed(obexClient_, -1);
36         return;
37     }
38     obexClient_.clientState_ = ObexClientState::TRANSPORT_CONNECTED;
39     if (obexClient_.isSupportReliableSession_ && obexClient_.reliableSessionReqHeader_ != nullptr) {
40         obexClient_.SendRequest(*obexClient_.reliableSessionReqHeader_);
41     } else if (obexClient_.connectReqHeader_ != nullptr) {
42         obexClient_.SendConnectRequest(*obexClient_.connectReqHeader_);
43     }
44 }
45 
OnTransportDisconnected(ObexTransport & transport)46 void ObexClient::ObexClientTransportObserver::OnTransportDisconnected(ObexTransport &transport)
47 {
48     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
49     OBEX_LOG_INFO("ClientId: %{public}s", obexClient_.GetClientId().c_str());
50 
51     obexClient_.clientState_ = ObexClientState::TRANSPORT_DISCONNECTED;
52     obexClient_.isObexConnected_ = false;
53     obexClient_.connectReqHeader_ = nullptr;
54     obexClient_.clientObserver_.OnDisconnected(obexClient_);
55 }
56 
OnTransportDataBusy(ObexTransport & transport,uint8_t isBusy)57 void ObexClient::ObexClientTransportObserver::OnTransportDataBusy(ObexTransport &transport, uint8_t isBusy)
58 {
59     OBEX_LOG_INFO("Call %{public}s, isBusy %{public}d", __PRETTY_FUNCTION__, isBusy);
60     OBEX_LOG_INFO("ClientId: %{public}s", obexClient_.GetClientId().c_str());
61     obexClient_.HandleTransportDataBusy(isBusy);
62 }
63 
OnTransportDataAvailable(ObexTransport & transport,ObexPacket & obexPacket)64 void ObexClient::ObexClientTransportObserver::OnTransportDataAvailable(
65     ObexTransport &transport, ObexPacket &obexPacket)
66 {
67     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
68     OBEX_LOG_INFO("ClientId: %{public}s", obexClient_.GetClientId().c_str());
69     obexClient_.isProcessing_ = false;
70     auto resp = GetObexHeaderFromPacket(obexPacket);
71     if (!resp) {
72         return;
73     }
74     obexClient_.clientSession_->SetLastRespCd(resp->GetFieldCode());
75     OBEX_LOG_DEBUG("lastOpeId : %02X", obexClient_.clientSession_->GetLastOpeId());
76     switch (obexClient_.clientSession_->GetLastOpeId()) {
77         case static_cast<uint8_t>(ObexOpeId::CONNECT):
78             HandleDataAvailableConnect(*resp);
79             break;
80         case static_cast<uint8_t>(ObexOpeId::DISCONNECT):
81             HandleDataAvailableDisconnect(*resp);
82             break;
83         case static_cast<uint8_t>(ObexOpeId::PUT):
84         case static_cast<uint8_t>(ObexOpeId::PUT_FINAL):
85             HandleDataAvailablePut(*resp);
86             break;
87         case static_cast<uint8_t>(ObexOpeId::GET):
88         case static_cast<uint8_t>(ObexOpeId::GET_FINAL):
89             HandleDataAvailableGet(*resp);
90             break;
91         case static_cast<uint8_t>(ObexOpeId::SETPATH):
92             HandleDataAvailableSetPath(*resp);
93             break;
94         case static_cast<uint8_t>(ObexOpeId::SESSION):
95             HandleDataAvailableSession(*resp);
96             break;
97         case static_cast<uint8_t>(ObexOpeId::ABORT):
98             HandleDataAvailableAbort(*resp);
99             break;
100         case static_cast<uint8_t>(ObexOpeId::ACTION):
101             HandleDataAvailableAction(*resp);
102             break;
103         default:
104             break;
105     }
106 }
107 
HandleDataAvailableAction(const ObexHeader & resp)108 void ObexClient::ObexClientTransportObserver::HandleDataAvailableAction(const ObexHeader &resp)
109 {
110     obexClient_.clientObserver_.OnActionCompleted(obexClient_, resp);
111 }
112 
HandleDataAvailableAbort(const ObexHeader & resp)113 void ObexClient::ObexClientTransportObserver::HandleDataAvailableAbort(const ObexHeader &resp)
114 {
115     if (resp.GetFieldCode() == static_cast<uint8_t>(ObexRspCode::CONTINUE)) {
116         // Skip unfinished get/put contniue packet
117         OBEX_LOG_DEBUG("abort request is sended, therefore skip unfinished get/put contniue packet");
118         return;
119     }
120     obexClient_.AbortDataAvailable(resp);
121 }
122 
HandleDataAvailableSession(const ObexHeader & resp)123 void ObexClient::ObexClientTransportObserver::HandleDataAvailableSession(const ObexHeader &resp)
124 {
125     if (resp.GetFieldCode() == static_cast<uint8_t>(ObexRspCode::SUCCESS)) {
126         auto sessionParams = resp.GetItemSessionParams();
127         // sessionParams is not exists? do disconnect
128         if (sessionParams == nullptr) {
129             obexClient_.Disconnect();
130             return;
131         }
132         obexClient_.isReliableSessionCreated_ = true;
133         obexClient_.clientState_ = ObexClientState::RELIABLE_SESSION_CREATED;
134         // will support in the future: COPY Session param to ClientSession
135         obexClient_.SendConnectRequest(*obexClient_.connectReqHeader_);
136     } else {
137         obexClient_.clientObserver_.OnActionCompleted(obexClient_, resp);
138     }
139 }
140 
HandleDataAvailableSetPath(const ObexHeader & resp)141 void ObexClient::ObexClientTransportObserver::HandleDataAvailableSetPath(const ObexHeader &resp)
142 {
143     obexClient_.SetPathDataAvailable(resp);
144 }
145 
HandleDataAvailablePut(const ObexHeader & resp)146 void ObexClient::ObexClientTransportObserver::HandleDataAvailablePut(const ObexHeader &resp)
147 {
148     obexClient_.PutDataAvailable(resp);
149 }
150 
HandleDataAvailableGet(const ObexHeader & resp)151 void ObexClient::ObexClientTransportObserver::HandleDataAvailableGet(const ObexHeader &resp)
152 {
153     obexClient_.GetDataAvailable(resp);
154 }
155 
HandleDataAvailableDisconnect(const ObexHeader & resp)156 void ObexClient::ObexClientTransportObserver::HandleDataAvailableDisconnect(const ObexHeader &resp)
157 {
158     obexClient_.clientObserver_.OnActionCompleted(obexClient_, resp);
159     obexClient_.clientState_ = ObexClientState::OBEX_DISCONNECTED;
160     obexClient_.isObexConnected_ = false;
161     obexClient_.connectReqHeader_ = nullptr;
162     obexClient_.clientTransport_->Disconnect();
163 }
164 
HandleDataAvailableConnect(const ObexHeader & resp)165 void ObexClient::ObexClientTransportObserver::HandleDataAvailableConnect(const ObexHeader &resp)
166 {
167     if (resp.GetFieldCode() == static_cast<uint8_t>(ObexRspCode::SUCCESS)) {
168         obexClient_.clientState_ = ObexClientState::OBEX_CONNECTED;
169         // set connected and mtu
170         obexClient_.isObexConnected_ = true;
171         uint16_t serverMaxPktLen = *resp.GetFieldMaxPacketLength();
172         if (serverMaxPktLen > OBEX_MINIMUM_MTU && serverMaxPktLen < obexClient_.clientSession_->GetMaxPacketLength()) {
173             obexClient_.clientSession_->SetMaxPacketLength(serverMaxPktLen);
174             OBEX_LOG_DEBUG("MTU Reset to:%{public}d", serverMaxPktLen);
175         }
176         // connect id
177         auto connectId = resp.GetItemConnectionId();
178         if (connectId != nullptr) {
179             obexClient_.clientSession_->SetConnectId(connectId->GetWord());
180         }
181         obexClient_.clientObserver_.OnConnected(obexClient_, resp);
182     } else {
183         obexClient_.clientObserver_.OnConnectFailed(obexClient_, resp);
184     }
185 }
186 
OnTransportError(ObexTransport & transport,int errCd)187 void ObexClient::ObexClientTransportObserver::OnTransportError(ObexTransport &transport, int errCd)
188 {
189     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
190     OBEX_LOG_ERROR("ClientId: %{public}s, errCd: %{public}d", obexClient_.GetClientId().c_str(), errCd);
191     obexClient_.clientObserver_.OnTransportFailed(obexClient_, errCd);
192 }
193 
GetObexHeaderFromPacket(ObexPacket & obexPacket)194 std::unique_ptr<bluetooth::ObexHeader> ObexClient::ObexClientTransportObserver::GetObexHeaderFromPacket(
195     ObexPacket &obexPacket)
196 {
197     uint8_t *packetBuf = obexPacket.GetBuffer();
198     size_t packetBufSize = obexPacket.GetSize();
199     if (packetBufSize < ObexHeader::MIN_PACKET_LENGTH) {
200         OBEX_LOG_ERROR("dataSize[%{public}zu] < min[%{public}d]", packetBufSize, ObexHeader::MIN_PACKET_LENGTH);
201         return nullptr;
202     }
203     uint16_t packetLength = ObexUtils::GetBufData16(&packetBuf[0], 1);
204     if (packetLength != packetBufSize) {
205         OBEX_LOG_ERROR("packetLength[%{public}hu] != packetBufSize[%{public}zu]", packetLength, packetBufSize);
206         return nullptr;
207     }
208     std::unique_ptr<bluetooth::ObexHeader> resp;
209 
210     if (obexClient_.clientSession_->GetLastOpeId() == static_cast<uint8_t>(ObexOpeId::CONNECT)) {
211         resp = ObexHeader::ParseResponse(packetBuf, packetLength, true);
212     } else {
213         resp = ObexHeader::ParseResponse(packetBuf, packetLength, false);
214     }
215     if (resp == nullptr) {
216         OBEX_LOG_ERROR("ParseResponse failure");
217         return nullptr;
218     }
219     return resp;
220 }
221 
ObexClient(const ObexClientConfig & config,ObexClientObserver & observer,utility::Dispatcher & dispatcher)222 ObexClient::ObexClient(const ObexClientConfig &config, ObexClientObserver &observer, utility::Dispatcher &dispatcher)
223     : clientObserver_(observer), dispatcher_(dispatcher)
224 {
225     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
226     isObexConnected_ = false;
227     transportObserver_ = std::make_unique<ObexClientTransportObserver>(*this);
228     ObexClientSocketTransport::Option option;
229     option.addr_ = config.addr_;
230     option.scn_ = config.scn_;
231     option.mtu_ = config.mtu_;
232     option.lpsm_ = config.lpsm_;
233 
234     option.isGoepL2capPSM_ = config.isGoepL2capPSM_;
235     clientTransport_ = std::make_unique<ObexClientSocketTransport>(option, *transportObserver_, dispatcher);
236     isSupportSrm_ = config.isSupportSrm_;  // srm mode
237     isSupportReliableSession_ = config.isSupportReliableSession_;
238     clientSession_ = std::make_unique<ObexClientSession>(RawAddress::ConvertToString(config.addr_.addr));
239     clientSession_->SetMaxPacketLength(config.mtu_);
240     clientSession_->SetServiceUUID(config.serviceUUID_);
241     clientSession_->FreeSendObject();
242     connectReqHeader_ = nullptr;
243     clientState_ = ObexClientState::INIT;
244 }
245 
246 // send obex request
SendRequest(const ObexHeader & req)247 int ObexClient::SendRequest(const ObexHeader &req)
248 {
249     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
250     OBEX_LOG_INFO("ClientId: %{public}s", GetClientId().c_str());
251     if (req.GetFieldCode() == static_cast<uint8_t>(ObexOpeId::SESSION)) {
252         auto sessionParams = req.GetItemSessionParams();
253         if (sessionParams == nullptr) {
254             OBEX_LOG_ERROR("Request of session is invalid!");
255             return -1;
256         }
257         const TlvTriplet *tlv = sessionParams->GetTlvtriplet(ObexSessionParameters::SESSION_OPCODE);
258         if (tlv == nullptr) {
259             OBEX_LOG_ERROR("Request of session is invalid!");
260             return -1;
261         }
262         if (!CheckBeforeSession(tlv->GetVal()[0])) {
263             return -1;
264         }
265     } else {
266         if (!CheckBeforeRequest(req.GetFieldCode())) {
267             return -1;
268         }
269     }
270 
271     if (req.GetFieldPacketLength() > clientSession_->GetMaxPacketLength()) {
272         OBEX_LOG_ERROR(
273             "Request packet length[%{public}d] > mtu[%{public}d].", req.GetFieldPacketLength(), clientSession_->GetMaxPacketLength());
274         return -1;
275     }
276     auto obexPacket = req.Build();
277     bool srmEnable = false;
278     if (req.HasHeader(ObexHeader::SRM)) {
279         srmEnable = req.GetItemSrm();
280     }
281     if ((req.GetFieldCode() == static_cast<uint8_t>(ObexOpeId::PUT)) &&
282         !srmEnable) {
283         isProcessing_ = false;
284     } else {
285         isProcessing_ = true;
286     }
287     bool ret = clientTransport_->Write(obexPacket->GetPacket());
288     if (!ret) {
289         OBEX_LOG_ERROR("SendRequest Fail!");
290         isProcessing_ = false;
291         return -1;
292     }
293     OBEX_LOG_DEBUG("Client Set lastOpeId: 0x%02X", req.GetFieldCode());
294 
295     clientSession_->SetLastOpeId(req.GetFieldCode());
296     clientSession_->SetLastReqHeader(req);
297 
298     return 0;
299 }
300 
301 // send obex connect request
Connect()302 int ObexClient::Connect()
303 {
304     ObexConnectParams connectParams;
305     return Connect(connectParams);
306 }
307 
308 // send obex connect request with params
Connect(ObexConnectParams & connectParams)309 int ObexClient::Connect(ObexConnectParams &connectParams)
310 {
311     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
312     OBEX_LOG_INFO("ClientId: %{public}s", GetClientId().c_str());
313     if (!CheckBeforeRequest(static_cast<uint8_t>(ObexOpeId::CONNECT))) {
314         return -1;
315     }
316     std::unique_ptr<ObexHeader> header = ObexHeader::CreateRequest(ObexOpeId::CONNECT);
317     const BtUuid &serviceUUID = clientSession_->GetServiceUUID();
318     if (serviceUUID.uuid128[0] != 0x00) {
319         header->AppendItemTarget(&serviceUUID.uuid128[0], sizeof(serviceUUID.uuid128));
320     }
321     if (connectParams.appParams_ != nullptr) {
322         header->AppendItemAppParams(*connectParams.appParams_);
323     }
324     if (connectParams.authChallenges_ != nullptr) {
325         header->AppendItemAuthChallenges(*connectParams.authChallenges_);
326     }
327     if (connectParams.authResponses_ != nullptr) {
328         header->AppendItemAuthResponse(*connectParams.authResponses_);
329     }
330     if (connectParams.count != nullptr) {
331         header->AppendItemCount(*connectParams.count);
332     }
333     // create transport before obex connect
334     if (!clientTransport_->IsConnected()) {
335         connectReqHeader_ = std::move(header);
336         return clientTransport_->Connect();
337     }
338     return SendConnectRequest(*header);
339 }
340 
341 // send obex disconnect request
Disconnect(bool withObexReq)342 int ObexClient::Disconnect(bool withObexReq)
343 {
344     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
345     OBEX_LOG_INFO("ClientId: %{public}s", GetClientId().c_str());
346     if (withObexReq) {
347         if (!CheckBeforeRequest(static_cast<uint8_t>(ObexOpeId::DISCONNECT))) {
348             return -1;
349         }
350         auto req = ObexHeader::CreateRequest(ObexOpeId::DISCONNECT);
351         if (isReliableSessionCreated_) {
352             req->AppendItemSessionSeqNum(clientSession_->GetReliableSession()->sessionSequenceNumber_++);
353         }
354         uint32_t connectId = clientSession_->GetConnectId();
355         if (connectId != 0x00) {
356             req->AppendItemConnectionId(connectId);
357         }
358         return SendRequest(*req);
359     }
360     return clientTransport_->Disconnect();
361 }
362 
363 // send obex abort request
Abort()364 int ObexClient::Abort()
365 {
366     dispatcher_.PostTask(std::bind(&ObexClient::ProcessAbort, this));
367     return 0;
368 }
369 
ProcessAbort()370 int ObexClient::ProcessAbort()
371 {
372     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
373     OBEX_LOG_INFO("ClientId: %{public}s", GetClientId().c_str());
374     if (isWaitingSendAbort_ || isAbortSended_) {
375         OBEX_LOG_ERROR("Abort is processing!");
376         return -1;
377     }
378     isAbortSended_ = false;
379     if (isProcessing_) {
380         isAbortSended_ = false;
381         switch (clientSession_->GetLastOpeId()) {
382             case static_cast<uint8_t>(ObexOpeId::PUT):
383             case static_cast<uint8_t>(ObexOpeId::PUT_FINAL):
384             case static_cast<uint8_t>(ObexOpeId::GET):
385             case static_cast<uint8_t>(ObexOpeId::GET_FINAL):
386                 isWaitingSendAbort_ = true;
387                 break;
388             default:
389                 isWaitingSendAbort_ = false;
390                 break;
391         }
392         return 0;
393     }
394     return SendAbortRequest();
395 }
396 
SendAbortRequest()397 int ObexClient::SendAbortRequest()
398 {
399     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
400     OBEX_LOG_INFO("ClientId: %{public}s", GetClientId().c_str());
401     if (!CheckBeforeRequest(static_cast<uint8_t>(ObexOpeId::ABORT))) {
402         return -1;
403     }
404     auto req = ObexHeader::CreateRequest(ObexOpeId::ABORT);
405     uint32_t connectId = clientSession_->GetConnectId();
406     if (connectId != 0x00) {
407         req->AppendItemConnectionId(connectId);
408     }
409     isWaitingSendAbort_ = false;
410     isAbortSended_ = true;
411     return SendRequest(*req);
412 }
413 
414 // send obex put request
Put(const ObexHeader & req)415 int ObexClient::Put(const ObexHeader &req)
416 {
417     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
418     OBEX_LOG_INFO("ClientId: %{public}s", GetClientId().c_str());
419     if (!CheckBeforeRequest(req.GetFieldCode())) {
420         return -1;
421     }
422     if (req.GetFieldCode() != static_cast<uint8_t>(ObexOpeId::PUT) &&
423         req.GetFieldCode() != static_cast<uint8_t>(ObexOpeId::PUT_FINAL)) {
424         OBEX_LOG_ERROR("Opcode is wrong.");
425         return -1;
426     }
427     return SendRequest(req);
428 }
429 
430 // send obex get request
Get(const ObexHeader & req)431 int ObexClient::Get(const ObexHeader &req)
432 {
433     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
434     OBEX_LOG_INFO("ClientId: %{public}s", GetClientId().c_str());
435     if (!CheckBeforeRequest(req.GetFieldCode())) {
436         return -1;
437     }
438     if (req.GetFieldCode() != static_cast<uint8_t>(ObexOpeId::GET) &&
439         req.GetFieldCode() != static_cast<uint8_t>(ObexOpeId::GET_FINAL)) {
440         OBEX_LOG_ERROR("Opcode is wrong.");
441         return -1;
442     }
443     return SendRequest(req);
444 }
445 
446 // send obex set_path request
SetPath(uint8_t flag,const std::u16string & path)447 int ObexClient::SetPath(uint8_t flag, const std::u16string &path)
448 {
449     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
450     OBEX_LOG_INFO("ClientId: %{public}s", GetClientId().c_str());
451     if (!CheckBeforeRequest(static_cast<uint8_t>(ObexOpeId::SETPATH))) {
452         return -1;
453     }
454     if (path.find(u"/") != std::u16string::npos) {
455         OBEX_LOG_ERROR("The path shall not include any path information!");
456         return -1;
457     }
458     auto req = ObexHeader::CreateRequest(ObexOpeId::SETPATH);
459     req->SetFieldFlags(flag);
460     uint32_t connectId = clientSession_->GetConnectId();
461     if (connectId != 0x00) {
462         req->AppendItemConnectionId(connectId);
463     }
464     if (path.length() > 0) {
465         req->AppendItemName(path);
466     }
467     return SendRequest(*req);
468 }
469 
470 // send obex action request
Copy(const std::u16string & srcName,const std::u16string & destName)471 int ObexClient::Copy(const std::u16string &srcName, const std::u16string &destName)
472 {
473     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
474     OBEX_LOG_INFO("ClientId: %{public}s", GetClientId().c_str());
475     // will support in the future
476     return 0;
477 }
478 
Move(const std::u16string & srcName,const std::u16string & destName)479 int ObexClient::Move(const std::u16string &srcName, const std::u16string &destName)
480 {
481     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
482     OBEX_LOG_INFO("ClientId: %{public}s", GetClientId().c_str());
483     // will support in the future
484     return 0;
485 }
486 
SetPermissions(const std::u16string & name,const uint32_t permissions)487 int ObexClient::SetPermissions(const std::u16string &name, const uint32_t permissions)
488 {
489     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
490     OBEX_LOG_INFO("ClientId: %{public}s", GetClientId().c_str());
491     // will support in the future
492     return 0;
493 }
494 
495 // send obex session request
496 // This command must include a Session-Parameters header containing the Session Opcode, Device Address and Nonce
497 // fields. Optionally, a Timeout field can be included.
CreateSession()498 int ObexClient::CreateSession()
499 {
500     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
501     // will support in the future
502     return CreateSession(OBEX_SESSION_MAX_TIMEOUT_SEC);
503 }
504 
CreateSession(uint32_t timeoutSec)505 int ObexClient::CreateSession(uint32_t timeoutSec)
506 {
507     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
508     return 0;
509 }
510 
511 // This command must include a Session-Parameters header containing the Session Opcode field.
512 // Optionally, a Timeout field can be included.
SuspendSession()513 int ObexClient::SuspendSession()
514 {
515     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
516     return 0;
517 }
518 
519 // This command must include a Session-Parameters header containing the Session Opcode, Device Address, Nonce,
520 // and Session ID and fields. Optionally, a Timeout field can be included.
ResumeSession()521 int ObexClient::ResumeSession()
522 {
523     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
524     return 0;
525 }
526 
527 // This command must include a Session-Parameters header containing the Session Opcode and Session ID fields.
CloseSession()528 int ObexClient::CloseSession()
529 {
530     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
531     return 0;
532 }
533 
534 // This command must include a Session-Parameters header containing the Session Opcode field.
535 // Optionally, a Timeout field can be included.
SetSessionTimeout(uint32_t timeoutSec)536 int ObexClient::SetSessionTimeout(uint32_t timeoutSec)
537 {
538     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
539     return 0;
540 }
541 
CheckBeforeSession(uint8_t sessionOpcode)542 bool ObexClient::CheckBeforeSession(uint8_t sessionOpcode)
543 {
544     return true;
545 }
546 
CheckBeforeRequest(uint8_t opeId) const547 bool ObexClient::CheckBeforeRequest(uint8_t opeId) const
548 {
549     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
550     if (isProcessing_) {
551         OBEX_LOG_ERROR("Another operation is being processed, please try again later.");
552         return false;
553     }
554     bool checkConnect = true;
555     bool needConnected = true;
556     switch (opeId) {
557         case static_cast<uint8_t>(ObexOpeId::CONNECT):
558             needConnected = false;
559             break;
560         case static_cast<uint8_t>(ObexOpeId::SESSION):
561             checkConnect = false;  // Session's connect check is in CheckBeforeSession
562             break;
563         case static_cast<uint8_t>(ObexOpeId::DISCONNECT):
564             if (!isObexConnected_) {
565                 OBEX_LOG_ERROR("Already Disconnected from the server.");
566                 return false;
567             }
568             break;
569         default:
570             break;
571     }
572     if (checkConnect) {
573         if (needConnected && !isObexConnected_) {
574             OBEX_LOG_ERROR(
575                 "Please connect first. Before obex connected, only SESSION(Create) and CONNECT Operation can "
576                 "be called.");
577             return false;
578         }
579         if (!needConnected && isObexConnected_) {
580             OBEX_LOG_ERROR("Already connected to server.");
581             return false;
582         }
583     }
584     return true;
585 }
586 
PutDataAvailable(const ObexHeader & resp)587 void ObexClient::PutDataAvailable(const ObexHeader &resp)
588 {
589     if (isWaitingSendAbort_) {
590         isProcessing_ = false;
591         SendAbortRequest();
592         return;
593     }
594     SetBusy(false);
595     clientObserver_.OnActionCompleted(*this, resp);
596 }
597 
GetDataAvailable(const ObexHeader & resp)598 void ObexClient::GetDataAvailable(const ObexHeader &resp)
599 {
600     if (isWaitingSendAbort_) {
601         isProcessing_ = false;
602         SendAbortRequest();
603         return;
604     }
605     SetBusy(false);
606     clientObserver_.OnActionCompleted(*this, resp);
607 }
608 
SetPathDataAvailable(const ObexHeader & resp)609 void ObexClient::SetPathDataAvailable(const ObexHeader &resp)
610 {
611     clientObserver_.OnActionCompleted(*this, resp);
612 }
613 
AbortDataAvailable(const ObexHeader & resp)614 void ObexClient::AbortDataAvailable(const ObexHeader &resp)
615 {
616     isWaitingSendAbort_ = false;
617     isAbortSended_ = false;
618     SetBusy(false);
619     clientObserver_.OnActionCompleted(*this, resp);
620 }
621 
HandleTransportDataBusy(uint8_t isBusy)622 void ObexClient::HandleTransportDataBusy(uint8_t isBusy)
623 {
624     OBEX_LOG_INFO("Call %{public}s, isBusy %{public}d", __PRETTY_FUNCTION__, isBusy);
625     clientObserver_.OnBusy(*this, isBusy);
626 }
627 
SendConnectRequest(ObexHeader & header)628 int ObexClient::SendConnectRequest(ObexHeader &header)
629 {
630     int minPacketSize = std::min(clientTransport_->GetMaxSendPacketSize(),
631         clientTransport_->GetMaxReceivePacketSize());
632     minPacketSize = std::min(minPacketSize, (int)clientSession_->GetMaxPacketLength());
633     if (minPacketSize > OBEX_MAXIMUM_MTU) {
634         minPacketSize = OBEX_MAXIMUM_MTU;
635     } else if (minPacketSize < OBEX_MINIMUM_MTU) {
636         minPacketSize = OBEX_MINIMUM_MTU;
637     }
638     header.SetFieldMaxPacketLength(minPacketSize);
639     clientSession_->SetMaxPacketLength(minPacketSize);
640     OBEX_LOG_DEBUG("SendConnect with mtu:%{public}d", minPacketSize);
641     return SendRequest(header);
642 }
643 
GetClientSession() const644 ObexClientSession &ObexClient::GetClientSession() const
645 {
646     return *clientSession_;
647 }
648 
GetClientId()649 const std::string &ObexClient::GetClientId()
650 {
651     if (clientId_.empty()) {
652         clientId_ = (clientTransport_ == nullptr) ? "" : clientTransport_->GetTransportKey();
653     }
654     return clientId_;
655 }
656 
RegisterL2capLPsm(uint16_t lpsm)657 int ObexClient::RegisterL2capLPsm(uint16_t lpsm)
658 {
659     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
660     OBEX_LOG_INFO("RegisterL2capLPsm: 0x%04X", lpsm);
661     return L2capTransport::RegisterClientPsm(lpsm);
662 }
663 
DeregisterL2capLPsm(uint16_t lpsm)664 void ObexClient::DeregisterL2capLPsm(uint16_t lpsm)
665 {
666     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
667     OBEX_LOG_INFO("DeregisterL2capLPsm: 0x%04X", lpsm);
668     L2capTransport::DeregisterClientPsm(lpsm);
669 }
670 
SetBusy(bool isBusy)671 void ObexClient::SetBusy(bool isBusy)
672 {
673     if (clientSession_->IsBusy() != isBusy) {
674         clientSession_->SetBusy(isBusy);
675         OBEX_LOG_INFO("[%{public}s] ObexBusy=%{public}d", GetClientId().c_str(), isBusy);
676         clientObserver_.OnBusy(*this, isBusy);
677     }
678 }
679 
OnBusy(ObexClient & client,bool isBusy)680 void ObexClientObserver::OnBusy(ObexClient &client, bool isBusy)
681 {
682     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
683 }
684 }  // namespace bluetooth
685 }  // namespace OHOS
686