• 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 "pbap_pce_obex_client.h"
17 #include "pbap_pce_def.h"
18 #include "pbap_pce_service.h"
19 #include "log_util.h"
20 
21 namespace OHOS {
22 namespace bluetooth {
ObexFileBodyObject(const std::string & file)23 ObexFileBodyObject::ObexFileBodyObject(const std::string &file)
24 {
25     OpenOutFile(file);
26 }
27 
OpenOutFile(const std::string & file)28 void ObexFileBodyObject::OpenOutFile(const std::string &file)
29 {
30     ofs_.open(file, std::ios::out);
31     if (!ofs_.is_open()) {
32         PBAP_PCE_LOG_ERROR("%{public}s file  open failed", __PRETTY_FUNCTION__);
33     } else {
34         PBAP_PCE_LOG_DEBUG("%{public}s file=%{public}s  opened.", __PRETTY_FUNCTION__, file.c_str());
35     }
36 }
37 
Read(uint8_t * buf,size_t bufLen)38 size_t ObexFileBodyObject::Read(uint8_t *buf, size_t bufLen)
39 {
40     size_t readSize = bufLen;
41     return readSize;
42 }
43 
Write(const uint8_t * buf,size_t bufLen)44 size_t ObexFileBodyObject::Write(const uint8_t *buf, size_t bufLen)
45 {
46     if (ofs_.is_open()) {
47         auto buffer = reinterpret_cast<const char*>(buf);
48         ofs_.write(buffer, bufLen);
49         PBAP_PCE_LOG_DEBUG("%{public}s write file bufLen=%zu", __PRETTY_FUNCTION__, bufLen);
50     } else {
51         PBAP_PCE_LOG_ERROR("%{public}s file  open failed", __PRETTY_FUNCTION__);
52     }
53     return bufLen;
54 }
55 
Close()56 int ObexFileBodyObject::Close()
57 {
58     ofs_.close();
59     return 0;
60 }
61 
PbapPceObexClient(const ObexClientConfig & config,PbapPceService & pceService)62 PbapPceObexClient::PbapPceObexClient(const ObexClientConfig &config, PbapPceService &pceService)
63     : obexConfig_(config), pceService_(pceService)
64 {
65     observer_ = std::make_unique<PceObexObserver>(pceService_);
66     client_ = std::make_unique<ObexMpClient>(obexConfig_, *observer_, *pceService.GetDispatcher());
67 }
68 
~PbapPceObexClient()69 PbapPceObexClient::~PbapPceObexClient()
70 {}
71 
Connect(bool supported)72 int PbapPceObexClient::Connect(bool supported)
73 {
74     PBAP_PCE_LOG_INFO("%{public}s start", __PRETTY_FUNCTION__);
75     int ret = RET_BAD_STATUS;
76     if (observer_ == nullptr) {
77         PBAP_PCE_LOG_ERROR("%{public}s end, observer_ is null", __PRETTY_FUNCTION__);
78         return ret;
79     }
80     if (IsBusy()) {
81         PBAP_PCE_LOG_ERROR("%{public}s end, IS busy", __PRETTY_FUNCTION__);
82         return ret;
83     }
84     SetBusy(true);
85     if (supported) {
86         ObexTlvParamters p;
87         TlvTriplet tlv(static_cast<uint8_t>(PbapSupportedFeatures::PCE_PBAP_SUPPORTED_FEATURES), PBAP_PCE_FEATURES);
88         p.AppendTlvtriplet(tlv);
89         ObexConnectParams param = {.appParams_ = &p};
90         ret = client_->Connect(param);
91     } else {
92         ret = client_->Connect();
93     }
94 
95     PBAP_PCE_LOG_INFO("%{public}s end", __PRETTY_FUNCTION__);
96     return ret;
97 }
98 
Reconnect(ObexDigestChallenge & challenge,ObexDigestResponse & digest)99 int PbapPceObexClient::Reconnect(ObexDigestChallenge &challenge, ObexDigestResponse &digest)
100 {
101     PBAP_PCE_LOG_INFO("%{public}s start", __PRETTY_FUNCTION__);
102     int ret = RET_BAD_STATUS;
103     if (observer_ == nullptr) {
104         PBAP_PCE_LOG_ERROR("%{public}s end, observer_ is null", __PRETTY_FUNCTION__);
105         return ret;
106     }
107 
108     if (IsBusy()) {
109         PBAP_PCE_LOG_ERROR("%{public}s end, IS busy", __PRETTY_FUNCTION__);
110         return ret;
111     }
112     SetBusy(true);
113     ObexTlvParamters p;
114     ObexConnectParams param = {&p, &challenge, &digest};
115     ret = client_->Connect(param);
116     PBAP_PCE_LOG_INFO("%{public}s end", __PRETTY_FUNCTION__);
117     return ret;
118 }
119 
Disconnect(bool withObexReq) const120 int PbapPceObexClient::Disconnect(bool withObexReq) const
121 {
122     PBAP_PCE_LOG_INFO("%{public}s start", __PRETTY_FUNCTION__);
123     int ret = RET_BAD_STATUS;
124     if (client_ == nullptr) {
125         PBAP_PCE_LOG_ERROR("%{public}s end, client_ is null", __PRETTY_FUNCTION__);
126         return ret;
127     }
128     ret = client_->Disconnect(withObexReq);
129     PBAP_PCE_LOG_INFO("%{public}s end", __PRETTY_FUNCTION__);
130     return ret;
131 }
132 
Get(const ObexHeader & req,int reqMsgType) const133 int PbapPceObexClient::Get(const ObexHeader &req, int reqMsgType) const
134 {
135     PBAP_PCE_LOG_INFO("%{public}s start", __PRETTY_FUNCTION__);
136     int ret = RET_BAD_STATUS;
137     if ((client_ == nullptr) || (observer_ == nullptr)) {
138         PBAP_PCE_LOG_ERROR("%{public}s end, client_ or observer_ is null", __PRETTY_FUNCTION__);
139         return ret;
140     }
141 #ifdef PBAP_PCE_RECEIVED_BY_OBEX_ARRAY
142     auto writer = std::make_shared<ObexArrayBodyObject>();
143     ret = client_->Get(req, writer);
144 #else
145     if (reqMsgType == PCE_REQ_PULLPHONEBOOK) {
146         auto &device = client_->GetClientSession().GetRemoteAddr();
147         std::string file = pceService_.GetDownloadFileName(device);
148         auto writer = std::make_shared<ObexFileBodyObject>(file);
149         ret = client_->Get(req, writer);
150     } else {
151         auto writer = std::make_shared<ObexArrayBodyObject>();
152         ret = client_->Get(req, writer);
153     }
154 #endif  // PBAP_PCE_RECEIVED_BY_OBEX_ARRAY
155 
156     auto &pSession = client_->GetClientSession();
157     observer_->SetPhoneBookActionInfo(pSession.GetLastOpeId(), reqMsgType);
158 
159     PBAP_PCE_LOG_INFO("%{public}s end", __PRETTY_FUNCTION__);
160     return ret;
161 }
162 
SetPath(uint8_t flag,const std::u16string & path) const163 int PbapPceObexClient::SetPath(uint8_t flag, const std::u16string &path) const
164 {
165     PBAP_PCE_LOG_INFO("%{public}s start", __PRETTY_FUNCTION__);
166     int ret = RET_BAD_STATUS;
167     if ((client_ == nullptr) || (observer_ == nullptr)) {
168         PBAP_PCE_LOG_ERROR("%{public}s end, client_ or observer_ is null", __PRETTY_FUNCTION__);
169         return ret;
170     }
171 
172     // absolute path
173     char16_t separator = u'/';
174     if (path.find(separator) != std::u16string::npos) {
175         std::vector<std::u16string> paths;
176         size_t prevPos = 0;
177         size_t pos = 0;
178         while (pos < path.size()) {
179             if (path[pos] == separator) {
180                 paths.push_back(path.substr(prevPos, pos - prevPos));
181                 prevPos = pos + 1;
182             }
183             pos++;
184         }
185         paths.push_back(path.substr(prevPos, pos - prevPos));
186         ret = client_->SetPath(paths);
187     } else {
188         ret = client_->SetPath(flag, path);
189     }
190 
191     auto &pSession = client_->GetClientSession();
192     observer_->SetPhoneBookActionInfo(pSession.GetLastOpeId(), PCE_REQ_SETPHONEBOOK, path, flag);
193 
194     PBAP_PCE_LOG_INFO("%{public}s end", __PRETTY_FUNCTION__);
195     return ret;
196 }
197 
Abort() const198 int PbapPceObexClient::Abort() const
199 {
200     int ret = RET_BAD_STATUS;
201     if ((client_ == nullptr) || (observer_ == nullptr)) {
202         PBAP_PCE_LOG_ERROR("%{public}s client_ or observer_ is null", __PRETTY_FUNCTION__);
203         return ret;
204     }
205     ret = client_->Abort();
206     SetAbort(true);
207     return ret;
208 }
209 
GetClient() const210 ObexMpClient *PbapPceObexClient::GetClient() const
211 {
212     if (client_ == nullptr) {
213         PBAP_PCE_LOG_ERROR("%{public}s client_ is null", __PRETTY_FUNCTION__);
214         return nullptr;
215     }
216     return client_.get();
217 }
218 
OnTransportFailed(ObexClient & client,int errCd)219 void PbapPceObexClient::PceObexObserver::OnTransportFailed(ObexClient &client, int errCd)
220 {
221     PBAP_PCE_LOG_INFO("%{public}s start", __PRETTY_FUNCTION__);
222     PBAP_PCE_LOG_ERROR("Transport failed with error %{public}d", errCd);
223     isBusy_ = false;
224     const auto &device = client.GetClientSession().GetRemoteAddr();
225     utility::Message msg(PCE_TRANSPORT_FAILED, errCd);
226     pceService_.ProcessObexRespMessage(device, msg);
227     PBAP_PCE_LOG_INFO("%{public}s end", __PRETTY_FUNCTION__);
228 }
229 
OnConnected(ObexClient & client,const ObexHeader & resp)230 void PbapPceObexClient::PceObexObserver::OnConnected(ObexClient &client, const ObexHeader &resp)
231 {
232     PBAP_PCE_LOG_INFO("%{public}s start", __PRETTY_FUNCTION__);
233     isBusy_ = false;
234     const auto &device = client.GetClientSession().GetRemoteAddr();
235     std::unique_ptr<PbapPceObexMessage> obexMsg = std::make_unique<PbapPceObexMessage>(client, resp);
236     utility::Message msg(PCE_OBEX_CONNECTED, 0, static_cast<void *>(obexMsg.get()));
237     pceService_.ProcessObexRespMessage(device, msg);
238     PBAP_PCE_LOG_INFO("%{public}s end", __PRETTY_FUNCTION__);
239 }
240 
OnConnectFailed(ObexClient & client,const ObexHeader & resp)241 void PbapPceObexClient::PceObexObserver::OnConnectFailed(ObexClient &client, const ObexHeader &resp)
242 {
243     PBAP_PCE_LOG_INFO("%{public}s start", __PRETTY_FUNCTION__);
244     isBusy_ = false;
245     const auto &device = client.GetClientSession().GetRemoteAddr();
246     std::unique_ptr<PbapPceObexMessage> obexMsg = std::make_unique<PbapPceObexMessage>(client, resp);
247     utility::Message msg(PCE_OBEX_CONNECT_FAILED, 0, static_cast<void *>(obexMsg.get()));
248     pceService_.ProcessObexRespMessage(device, msg);
249     PBAP_PCE_LOG_INFO("%{public}s end", __PRETTY_FUNCTION__);
250 }
251 
OnDisconnected(ObexClient & client)252 void PbapPceObexClient::PceObexObserver::OnDisconnected(ObexClient &client)
253 {
254     PBAP_PCE_LOG_INFO("%{public}s start", __PRETTY_FUNCTION__);
255     isBusy_ = false;
256     const auto &device = client.GetClientSession().GetRemoteAddr();
257     utility::Message msg(PCE_OBEX_DISCONNECTED);
258     pceService_.ProcessObexRespMessage(device, msg);
259 
260     PBAP_PCE_LOG_INFO("%{public}s end", __PRETTY_FUNCTION__);
261 }
262 
OnActionCompleted(ObexClient & client,const ObexHeader & resp)263 void PbapPceObexClient::PceObexObserver::OnActionCompleted(ObexClient &client, const ObexHeader &resp)
264 {
265     PBAP_PCE_LOG_INFO("%{public}s start", __PRETTY_FUNCTION__);
266     isBusy_ = false;
267     auto &pSession = client.GetClientSession();
268     int lastCommandMsgType = 0;
269     std::u16string path;
270     uint8_t flags = 0;
271     GetPhoneBookActionInfo(pSession.GetLastOpeId(), lastCommandMsgType, path, flags);
272     const int offsetToComp = 1;
273     if (isAbort_) {
274         isAbort_ = false;
275         // req id to completed id
276         lastCommandMsgType = PCE_REQ_ABORTDOWNLOADING + offsetToComp;
277     } else {
278         // req id to completed id
279         lastCommandMsgType = lastCommandMsgType + offsetToComp;
280     }
281 
282     const auto &device = client.GetClientSession().GetRemoteAddr();
283     PbapPceActionObexMessage obexMsg(client, resp, path, flags);
284     utility::Message msg(lastCommandMsgType, 0, static_cast<void *>(&obexMsg));
285     pceService_.ProcessObexRespMessage(device, msg);
286     PBAP_PCE_LOG_INFO("%{public}s end", __PRETTY_FUNCTION__);
287 }
288 
OnBusy(ObexClient & client,bool isBusy)289 void PbapPceObexClient::PceObexObserver::OnBusy(ObexClient &client, bool isBusy)
290 {
291     auto &device = client.GetClientSession().GetRemoteAddr();
292     HILOGI("device=%{public}s, isBusy=%{public}d", GET_ENCRYPT_ADDR(device), isBusy ? 1 : 0);
293 }
294 
GetPhoneBookActionInfo(int operationId,int & retReqMsgType,std::u16string & retPath,uint8_t & retFlags) const295 bool PbapPceObexClient::PceObexObserver::GetPhoneBookActionInfo(
296     int operationId, int &retReqMsgType, std::u16string &retPath, uint8_t &retFlags) const
297 {
298     bool ret = true;
299     retReqMsgType = phoneBookActionInfo_.reqMsgType_;
300     retPath = phoneBookActionInfo_.path_;
301     retFlags = phoneBookActionInfo_.flags_;
302     return ret;
303 }
304 
SetPhoneBookActionInfo(int operationId,int reqMsgType,const std::u16string & path,uint8_t flags,bool isBusy)305 void PbapPceObexClient::PceObexObserver::SetPhoneBookActionInfo(
306     int operationId, int reqMsgType, const std::u16string &path, uint8_t flags, bool isBusy)
307 {
308     phoneBookActionInfo_.operationId_ = operationId;
309     phoneBookActionInfo_.reqMsgType_ = reqMsgType;
310     phoneBookActionInfo_.path_ = path;
311     phoneBookActionInfo_.flags_ = flags;
312     isBusy_ = isBusy;
313 }
314 
SetBusy(bool isBusy) const315 void PbapPceObexClient::SetBusy(bool isBusy) const
316 {
317     PBAP_PCE_LOG_INFO("%{public}s start", __PRETTY_FUNCTION__);
318     if (observer_ != nullptr) {
319         observer_->isBusy_ = isBusy;
320     }
321     PBAP_PCE_LOG_INFO("%{public}s end", __PRETTY_FUNCTION__);
322 }
323 
IsBusy() const324 bool PbapPceObexClient::IsBusy() const
325 {
326     PBAP_PCE_LOG_INFO("%{public}s start", __PRETTY_FUNCTION__);
327     if (observer_ != nullptr) {
328         return observer_->isBusy_;
329     }
330     PBAP_PCE_LOG_INFO("%{public}s end", __PRETTY_FUNCTION__);
331     return false;
332 }
333 
SetAbort(bool isAbort) const334 void PbapPceObexClient::SetAbort(bool isAbort) const
335 {
336     PBAP_PCE_LOG_INFO("%{public}s start", __PRETTY_FUNCTION__);
337     if (observer_ != nullptr) {
338         observer_->isAbort_ = isAbort;
339     }
340     PBAP_PCE_LOG_INFO("%{public}s end", __PRETTY_FUNCTION__);
341 }
342 }  // namespace bluetooth
343 }  // namespace OHOS
344