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 "obex_mp_server.h"
17 #include <memory>
18 #include "log.h"
19 
20 namespace OHOS {
21 namespace bluetooth {
22 // create obex server
ObexMpServer(const std::string & serviceName,const ObexServerConfig & config,ObexServerObserver & observer,utility::Dispatcher & dispatcher)23 ObexMpServer::ObexMpServer(const std::string &serviceName, const ObexServerConfig &config,
24     ObexServerObserver &observer, utility::Dispatcher &dispatcher)
25 {
26     OBEX_LOG_INFO("Call ObexMpServer %{public}s", __PRETTY_FUNCTION__);
27     serviceName_ = serviceName;
28     if (config.useRfcomm_) {
29         ObexPrivateServer::ObexPrivateServerConfig option;
30         option.isGoepL2capPSM_ = false;
31         option.scn_ = config.rfcommScn_;
32         option.mtu_ = config.rfcommMtu_;
33         option.isSupportSrm_ = false;  // rfcomm not support srm mode
34         option.isSupportReliableSession_ = config.isSupportReliableSession_;
35         rfcommServer_ = std::make_unique<ObexPrivateMpServer>(option, observer, dispatcher);
36     }
37     if (config.useL2cap_) {
38         ObexPrivateServer::ObexPrivateServerConfig option;
39         option.isGoepL2capPSM_ = true;
40         option.scn_ = config.l2capPsm_;
41         option.mtu_ = config.l2capMtu_;
42         option.isSupportSrm_ = config.isSupportSrm_;
43         option.isSupportReliableSession_ = config.isSupportReliableSession_;
44         l2capServer_ = std::make_unique<ObexPrivateMpServer>(option, observer, dispatcher);
45     }
46 }
47 
ObexPrivateMpServer(const ObexPrivateServerConfig & config,ObexServerObserver & observer,utility::Dispatcher & dispatcher)48 ObexPrivateMpServer::ObexPrivateMpServer(
49     const ObexPrivateServerConfig &config, ObexServerObserver &observer, utility::Dispatcher &dispatcher)
50     : ObexPrivateServer(config, observer, dispatcher)
51 {}
52 
HandlePutRequest(ObexServerSession & session,ObexHeader & req) const53 void ObexPrivateMpServer::HandlePutRequest(ObexServerSession &session, ObexHeader &req) const
54 {
55     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
56     if (req.GetFieldCode() == static_cast<uint8_t>(ObexOpeId::PUT)) {
57         SetBusy(session, true);
58         OBEX_LOG_DEBUG("HandlePutRequest:Server Received Put request without final bit!");
59         if (session.GetReceivedObject() == nullptr) {
60             OBEX_LOG_DEBUG("HandlePutRequest:Server Create ObexServerReceivedObject");
61             std::shared_ptr<ObexBodyObject> writer = std::make_shared<ObexArrayBodyObject>();
62             session.CreateReceivedObject(req, writer);
63         }
64         auto body = req.GetItemBody();
65         if (body != nullptr) {
66             OBEX_LOG_DEBUG("HandlePutRequest:Server Received Body From Request!");
67             session.GetReceivedObject()->AppendBody(body->GetBytes().get(), body->GetHeaderDataSize());
68         }
69         if (session.GetReceivedObject()->IsSrmReceiving()) {
70             return;
71         }
72         auto respHeader = ObexHeader::CreateResponse(ObexRspCode::CONTINUE);
73         auto connectId = req.GetItemConnectionId();
74         if (connectId != nullptr) {
75             respHeader->AppendItemConnectionId(connectId->GetWord());
76         }
77         if (isSupportSrm_ && req.GetItemSrm()) {
78             OBEX_LOG_DEBUG("HandlePutRequest:Server Response Set SRM = TRUE");
79             respHeader->AppendItemSrm(true);
80             session.GetReceivedObject()->SetSrmEnable(true);
81         }
82         if (session.GetReceivedObject()->IsSrmEnable() && req.GetItemSrmp()) {
83             OBEX_LOG_DEBUG("HandlePutRequest:Server Receive With SRMP");
84             session.GetReceivedObject()->SetSrmWait(req.GetItemSrmp());
85         }
86         if (session.GetReceivedObject()->IsSrmEnable() && !session.GetReceivedObject()->IsSrmWait()) {
87             OBEX_LOG_DEBUG("HandlePutRequest:Start SRM Receive...");
88             session.GetReceivedObject()->SetSrmReceiving();
89         }
90 
91         // when srmp header wait is use ?
92         int ret = session.SendResponse(*respHeader);
93         OBEX_LOG_DEBUG("HandlePutRequest:Server Send Response with ret = %{public}d", ret);
94         if (ret != 0) {
95             observer_.OnError(ret, "send response fail");
96         }
97     } else {
98         HandlePutFinalRequest(session, req);
99     }
100 }
101 
HandlePutFinalRequest(ObexServerSession & session,ObexHeader & req) const102 void ObexPrivateMpServer::HandlePutFinalRequest(ObexServerSession &session, ObexHeader &req) const
103 {
104     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
105     OBEX_LOG_DEBUG("HandlePutRequest:Server Received Put request with final bit!");
106     // final bit
107     if (session.GetReceivedObject() != nullptr) {
108         OBEX_LOG_DEBUG("HandlePutRequest:Server Has ObexServerReceivedObject!");
109         auto body = req.GetItemEndBody();
110         if (body != nullptr) {
111             OBEX_LOG_DEBUG("HandlePutRequest:Server Received End-Body From Request!");
112             session.GetReceivedObject()->AppendBody(body->GetBytes().get(), body->GetHeaderDataSize());
113         }
114         ObexPrivateServer::HandlePutRequest(session, *session.GetReceivedObject()->CreateReceivedHeader());
115         session.FreeReceivedObject();
116         return;
117     }
118     OBEX_LOG_DEBUG("HandlePutRequest:Server Has not ObexServerReceivedObject!");
119     auto body = req.GetItemEndBody();
120     if (body != nullptr) {
121         auto writer = std::make_shared<ObexArrayBodyObject>();
122         writer->Write(body->GetBytes().get(), body->GetHeaderDataSize());
123         OBEX_LOG_DEBUG("HandlePutRequest:Server Received End-Body From Request!");
124         req.RemoveItem(ObexHeader::END_OF_BODY);
125         req.SetExtendBodyObject(writer);
126     }
127     SetBusy(session, false);
128     ObexPrivateServer::HandlePutRequest(session, req);
129 }
130 
HandleTransportDataBusy(ObexServerSession & session,uint8_t isBusy)131 void ObexPrivateMpServer::HandleTransportDataBusy(ObexServerSession &session, uint8_t isBusy)
132 {
133     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
134     auto &sendObject = session.GetSendObject();
135     if (!sendObject) {
136         return;
137     }
138     bool oldBusy = sendObject->IsBusy();
139     bool newBusy = (isBusy == 0x01);
140     sendObject->SetBusy(newBusy);
141     // busy -> not busy , srm data is sending
142     if (oldBusy && !newBusy && sendObject->IsSrmSending()) {
143         OBEX_LOG_DEBUG("Transport change to not busy, continue send srm response data.");
144         session.SendSrmResponse();
145     }
146 }
147 
HandleGetRequest(ObexServerSession & session,ObexHeader & req)148 void ObexPrivateMpServer::HandleGetRequest(ObexServerSession &session, ObexHeader &req)
149 {
150     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
151     auto &sendObject = session.GetSendObject();
152     if (!sendObject) {
153         ObexPrivateServer::HandleGetRequest(session, req);
154         return;
155     }
156     OBEX_LOG_DEBUG("HandleGetRequest:Server Has ObexServerSendObject");
157     if (sendObject->IsSrmEnable()) {
158         if (sendObject->IsSrmWait() && !req.GetItemSrmp()) {
159             OBEX_LOG_DEBUG("HandleGetRequest:Server srmp wait end!");
160             sendObject->SetSrmWait(false);
161         }
162     }
163     sendObject->SetStartBodyResp(req.GetFieldCode() == static_cast<uint8_t>(ObexOpeId::GET_FINAL));
164     if (sendObject->IsSrmEnable() && !sendObject->IsSrmWait()) {
165         if (req.GetFieldCode() != static_cast<uint8_t>(ObexOpeId::GET_FINAL)) {
166             OBEX_LOG_DEBUG("HandleGetRequest: wait the GET request + Final Bit has been issued");
167             // GEOP:4.6 Using Single Response Mode
168             // GET operations with SRM enabled shall not send a GET response until the GET
169             // request + Final Bit has been issued.
170             return;
171         }
172         if (sendObject->IsSrmSending()) {
173             OBEX_LOG_ERROR("HandleGetRequest:other get srm is in progress, ignores this get request!");
174             return;
175         }
176         int ret = session.SendSrmResponse();
177         if (ret != 0) {
178             session.FreeSendObject();
179         }
180     } else {
181         OBEX_LOG_DEBUG("Send next get multi-packet responses");
182         auto nextReqHdr = sendObject->GetNextRespHeader();
183         if (nextReqHdr == nullptr) {
184             OBEX_LOG_ERROR("nextReqHdr is null!");
185             nextReqHdr = ObexHeader::CreateResponse(ObexRspCode::INTERNAL_SERVER_ERROR);
186         }
187         int ret = session.SendResponse(*nextReqHdr);
188         if (ret != 0) {
189             session.FreeSendObject();
190             observer_.OnError(ret, "send response fail");
191         }
192         if (nextReqHdr->GetFieldCode() != static_cast<uint8_t>(ObexRspCode::CONTINUE)) {
193             OBEX_LOG_DEBUG("session.sendObject reset to null");
194             session.FreeSendObject();
195             SetBusy(session, false);
196         }
197     }
198 }
199 
HandleAbortRequest(ObexServerSession & session,ObexHeader & req)200 void ObexPrivateMpServer::HandleAbortRequest(ObexServerSession &session, ObexHeader &req)
201 {
202     OBEX_LOG_INFO("Call %{public}s", __PRETTY_FUNCTION__);
203     session.FreeSendObject();
204     session.FreeReceivedObject();
205     auto header = ObexHeader::CreateResponse(ObexRspCode::SUCCESS);
206     int ret = session.SendResponse(*header);
207     SetBusy(session, false);
208     OBEX_LOG_DEBUG("send abort response %{public}d", ret);
209 }
210 }  // namespace bluetooth
211 }  // namespace OHOS