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