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 #ifndef OBEX_SESSION_H 17 #define OBEX_SESSION_H 18 19 #include <cstdint> 20 #include "btstack.h" 21 #include "dispatcher.h" 22 #include "obex_body.h" 23 #include "obex_headers.h" 24 #include "obex_transport.h" 25 26 namespace OHOS { 27 namespace bluetooth { 28 enum ObexReliableSessionState { 29 OBEX_RELIABLE_SESSION_INIT = 0, 30 OBEX_RELIABLE_SESSION_ACTIVE, 31 OBEX_RELIABLE_SESSION_SUSPENDED, 32 OBEX_RELIABLE_SESSION_RESUMED, 33 OBEX_RELIABLE_SESSION_CLOSED 34 }; 35 class ObexSession { 36 public: 37 struct ObexReliableSession { 38 // session’s last modification in seconds since January 1, 1970. 39 uint32_t lastAccessTimestampSec_ = 0; 40 41 // This is a 16-byte value, which is formed by taking the device 42 // address and nonce from the client and server and running the MD5 algorithm 43 // over the resulting string. The Session ID is created as follows: MD5(“Client 44 // Device Address” “Client Nonce” “Server Device Address” “Server Nonce”) 45 uint8_t sessionId_[16]; 46 47 // This is a 4-byte value that contains the number of seconds a session can be 48 // in suspend mode before it is considered closed. The value of 0xffffffff 49 // indicates a timeout of infinity. This is the default timeout. If a device does not 50 // send a timeout field then it can be assumed that the desired timeout is infinity. 51 // The timeout in affect is the smallest timeout sent by the client or server 52 uint32_t timeoutSec_ = 0; 53 54 // the counting capacity of the sequence number is 256 using digits 0 – 255 (0xFF). At 255 the sequence 55 // number wraps around to 0. 56 // When the session is first created the Session-Sequence-Number number is set to 0. The first command 57 // packet sent by the client after the session is established will contain a Session-Sequence-Number 58 // header with value of 0. The response to this packet from the server contains the next packet number 59 // expected. If the packet was received successfully then the value of the Session-Sequence-Number 60 // header in the response would be 1. 61 uint8_t sessionSequenceNumber_ = 0; 62 63 // ObexReliableSessionState 64 ObexReliableSessionState sessionState_; 65 }; 66 explicit ObexSession(const RawAddress &remoteAddr); 67 virtual ~ObexSession() = default; GetRemoteAddr()68 const RawAddress &GetRemoteAddr() const 69 { 70 return remoteAddr_; 71 } GetMaxPacketLength()72 const uint16_t &GetMaxPacketLength() const 73 { 74 return maxPacketLength_; 75 } SetMaxPacketLength(uint16_t maxPacketLength)76 void SetMaxPacketLength(uint16_t maxPacketLength) 77 { 78 maxPacketLength_ = maxPacketLength; 79 } GetConnectId()80 const uint32_t &GetConnectId() const 81 { 82 return connectId_; 83 } SetConnectId(uint32_t connectId)84 void SetConnectId(uint32_t connectId) 85 { 86 connectId_ = connectId; 87 } GetServiceUUID()88 const BtUuid &GetServiceUUID() const 89 { 90 return serviceUUID_; 91 } SetServiceUUID(const BtUuid & serviceUUID)92 void SetServiceUUID(const BtUuid &serviceUUID) 93 { 94 serviceUUID_ = serviceUUID; 95 } IsReliableSession()96 const bool &IsReliableSession() const 97 { 98 return isReliableSession_; 99 } IsBusy()100 const bool &IsBusy() const 101 { 102 return isBusy_; 103 } SetBusy(bool isBusy)104 void SetBusy(bool isBusy) 105 { 106 isBusy_ = isBusy; 107 } GetReliableSession()108 const std::unique_ptr<ObexReliableSession> &GetReliableSession() const 109 { 110 return reliableSession_; 111 } 112 113 protected: 114 // The device address of the device sending the header. 115 RawAddress remoteAddr_ {""}; 116 117 // The MOPL that an OBEX client can receive is stated in the OBEX Connect request, 118 // this shall be less than or equal to the MTU configured for packets received by L2CAP for the OBEX connection. 119 // A separate, and possibly different, MOPL is stated by the OBEX server in the OBEX Connect response, 120 // this shall be less than or equal to the L2CAP MTU configured by L2CAP for the OBEX connection. 121 // GOEP implementations shall support a minimum MOPL packet size of 255 bytes. 122 // For OBEX over L2CAP this means that implementations shall also support a minimum MTU of 255 bytes. 123 uint16_t maxPacketLength_ = 0; 124 125 // Connection Id is a 4-byte value that tells the recipient of the request which OBEX connection this 126 // request belongs to. The Connection Id header is optional. When in use, the Connection Id header must 127 // be the first header in the request. 128 uint32_t connectId_ = 0; 129 130 // Target is a byte sequence that identifies the intended target of the operation. On the receiving end, object 131 // name and type information provide one way of performing dispatching - this header offers an alternate 132 // way of directing an operation to the intended recipient. 133 BtUuid serviceUUID_ {}; 134 135 // true: reliable session 136 bool isReliableSession_ = false; 137 bool isBusy_ = false; 138 // ObexReliableSession 139 std::unique_ptr<ObexReliableSession> reliableSession_ = nullptr; 140 }; 141 class ObexSetPathObject { 142 public: 143 explicit ObexSetPathObject(const std::vector<std::u16string> &paths); 144 virtual ~ObexSetPathObject() = default; 145 std::u16string GetNextPath(); 146 bool IsDone() const; 147 148 private: 149 std::vector<std::u16string> paths_ {}; 150 size_t pos_ = 0; 151 }; 152 153 class ObexClientSendObject { 154 public: 155 ObexClientSendObject(const ObexHeader &firstReq, std::shared_ptr<ObexBodyObject> bodyReader, uint16_t mtu); 156 virtual ~ObexClientSendObject() = default; 157 std::unique_ptr<ObexHeader> GetNextReqHeader(bool useSrm = false); 158 bool IsDone() const; 159 void SetSrmEnable(bool srmEnable); 160 bool IsSrmEnable() const; 161 void SetSrmWait(bool wait); 162 bool IsSrmWait() const; 163 void SetSrmSending(); 164 bool IsSrmSending() const; 165 void SetBusy(bool isBusy); 166 bool IsBusy() const; 167 168 private: 169 bool SetBodyToHeader(ObexHeader &header, const uint16_t &remainLength); 170 int reqIndex_ = 0; 171 bool srmEnable_ = false; 172 bool srmWait_ = false; 173 bool isDone_ = false; 174 bool isSrmSending_ = false; 175 bool isBusy_ = false; 176 uint16_t mtu_ = 0; 177 std::unique_ptr<ObexHeader> firstReq_ = nullptr; 178 std::shared_ptr<ObexBodyObject> bodyReader_ = nullptr; 179 }; 180 181 class ObexClientReceivedObject { 182 public: 183 ObexClientReceivedObject( 184 const ObexHeader &firstReq, std::shared_ptr<ObexBodyObject> writer, bool supportSrm, int srmpCount); 185 virtual ~ObexClientReceivedObject() = default; 186 ObexHeader &GetFirstReqHeader() const; 187 std::unique_ptr<ObexHeader> GetContinueReqHeader(); 188 std::shared_ptr<ObexBodyObject> &GetBodyWriter(); 189 const ObexHeader *GetFirstRespHeader() const; 190 void CacheResp(const ObexHeader &resp); 191 void AppendBody(const uint8_t *body, const uint16_t bodyLen); 192 bool IsDone() const; 193 void SetDone(bool done); 194 void SetSrmEnable(bool srmEnable); 195 bool IsSrmEnable() const; 196 void SetSrmWait(bool wait); 197 bool IsSrmWait() const; 198 bool IsSupportSrmMode() const; 199 bool IsSendNextReq() const; 200 201 private: 202 bool srmEnable_ = false; 203 bool srmWait_ = false; 204 bool isDone_ = false; 205 bool supportSrmMode_ = false; 206 int srmpCount_ = 0; 207 bool srmpSended_ = false; 208 size_t receivedSize_ = 0; 209 std::unique_ptr<ObexHeader> firstReq_ = nullptr; 210 std::shared_ptr<ObexBodyObject> bodyWriter_ = nullptr; 211 std::unique_ptr<ObexHeader> firstResp_ = nullptr; 212 }; 213 214 class ObexClientSession : public ObexSession { 215 public: 216 explicit ObexClientSession(const RawAddress &remoteAddr); 217 ~ObexClientSession() override = default; GetLastOpeId()218 const uint8_t &GetLastOpeId() const 219 { 220 return lastOpeId_; 221 } SetLastOpeId(uint8_t lastOpeId)222 void SetLastOpeId(uint8_t lastOpeId) 223 { 224 lastOpeId_ = lastOpeId; 225 } GetLastRespCd()226 const uint8_t &GetLastRespCd() const 227 { 228 return lastRespCd_; 229 } SetLastRespCd(uint8_t lastRespCd)230 void SetLastRespCd(uint8_t lastRespCd) 231 { 232 lastRespCd_ = lastRespCd; 233 } GetLastReqHeader()234 const std::unique_ptr<ObexHeader> &GetLastReqHeader() const 235 { 236 return lastReqHeader_; 237 } SetLastReqHeader(const ObexHeader & req)238 void SetLastReqHeader(const ObexHeader &req) 239 { 240 lastReqHeader_ = std::make_unique<ObexHeader>(req); 241 } GetSetPathObject()242 std::unique_ptr<ObexSetPathObject> &GetSetPathObject() 243 { 244 return objForSetPath_; 245 } CreateSetPathObject(const std::vector<std::u16string> & paths)246 void CreateSetPathObject(const std::vector<std::u16string> &paths) 247 { 248 objForSetPath_ = std::make_unique<ObexSetPathObject>(paths); 249 } FreeSetPathObject()250 void FreeSetPathObject() 251 { 252 objForSetPath_ = nullptr; 253 } 254 GetReceivedObject()255 std::unique_ptr<ObexClientReceivedObject> &GetReceivedObject() 256 { 257 return receivedObject_; 258 } CreateReceivedObject(const ObexHeader & req,std::shared_ptr<ObexBodyObject> writer,bool supportSrm,int srmpCount)259 std::unique_ptr<ObexClientReceivedObject> &CreateReceivedObject( 260 const ObexHeader &req, std::shared_ptr<ObexBodyObject> writer, bool supportSrm, int srmpCount) 261 { 262 receivedObject_ = std::make_unique<ObexClientReceivedObject>(req, writer, supportSrm, srmpCount); 263 return receivedObject_; 264 } FreeReceivedObject()265 void FreeReceivedObject() 266 { 267 receivedObject_ = nullptr; 268 } 269 GetSendObject()270 std::unique_ptr<ObexClientSendObject> &GetSendObject() 271 { 272 return sendObject_; 273 } CreateSendObject(const ObexHeader & req,std::shared_ptr<ObexBodyObject> & bodyReader,uint16_t & mtu)274 std::unique_ptr<ObexClientSendObject> &CreateSendObject( 275 const ObexHeader &req, std::shared_ptr<ObexBodyObject> &bodyReader, uint16_t &mtu) 276 { 277 sendObject_ = std::make_unique<ObexClientSendObject>(req, bodyReader, mtu); 278 return sendObject_; 279 } FreeSendObject()280 void FreeSendObject() 281 { 282 sendObject_ = nullptr; 283 } 284 285 private: 286 std::unique_ptr<ObexClientSendObject> sendObject_ = nullptr; 287 std::unique_ptr<ObexClientReceivedObject> receivedObject_ = nullptr; 288 std::unique_ptr<ObexSetPathObject> objForSetPath_ = nullptr; 289 std::unique_ptr<ObexHeader> lastReqHeader_ = nullptr; 290 uint8_t lastOpeId_ = 0; 291 uint8_t lastRespCd_ = 0; 292 }; 293 294 class ObexServerReceivedObject { 295 public: 296 ObexServerReceivedObject(const ObexHeader &firstReq, std::shared_ptr<ObexBodyObject> writer); 297 virtual ~ObexServerReceivedObject() = default; 298 void AppendBody(const uint8_t *body, const uint16_t bodyLen); 299 std::shared_ptr<ObexBodyObject> &GetWriter(); 300 std::unique_ptr<ObexHeader> CreateReceivedHeader(); 301 void SetSrmEnable(bool srmEnable); 302 bool IsSrmEnable() const; 303 void SetSrmWait(bool wait); 304 bool IsSrmWait() const; 305 void SetSrmReceiving(); 306 bool IsSrmReceiving() const; 307 308 private: 309 std::unique_ptr<ObexHeader> baseReq_ = nullptr; 310 std::shared_ptr<ObexBodyObject> writer_ = nullptr; 311 bool srmEnable_ = false; 312 bool srmWait_ = false; 313 bool isSrmReceiving_ = false; 314 size_t receivedSize_ = 0; 315 BT_DISALLOW_COPY_AND_ASSIGN(ObexServerReceivedObject); 316 }; 317 318 class ObexServerSendObject { 319 public: 320 ObexServerSendObject(const ObexHeader &firstReq, const ObexHeader &firstResp, 321 std::shared_ptr<ObexBodyObject> bodyReader, uint16_t mtu, bool supportSrm); 322 virtual ~ObexServerSendObject() = default; 323 std::unique_ptr<ObexHeader> GetNextRespHeader(); 324 bool IsDone() const; 325 void SetSrmEnable(bool srmEnable); 326 bool IsSrmEnable() const; 327 void SetSrmWait(bool wait); 328 bool IsSrmWait() const; 329 void SetStartBodyResp(bool start); 330 void SetSrmSending(); 331 bool IsSrmSending() const; 332 void SetBusy(bool isBusy); 333 bool IsBusy() const; 334 bool IsSupportSrmMode() const; 335 336 private: 337 void SetSrmParam(ObexHeader &header); 338 bool SetBodyToHeader(ObexHeader &header, const uint16_t &remainLength); 339 int reqIndex_ = 0; 340 bool srmEnable_ = false; 341 bool srmWait_ = false; 342 bool isDone_ = false; 343 bool supportSrmMode_ = false; 344 bool startBodyResp_ = false; 345 bool isSrmSending_ = false; 346 bool isBusy_ = false; 347 uint16_t mtu_ = 0; 348 std::unique_ptr<ObexHeader> firstReq_ = nullptr; 349 std::shared_ptr<ObexBodyObject> bodyReader_ = nullptr; 350 std::unique_ptr<ObexHeader> firstResp_ = nullptr; 351 BT_DISALLOW_COPY_AND_ASSIGN(ObexServerSendObject); 352 }; 353 class ObexServerSession : public ObexSession { 354 public: 355 ObexServerSession(ObexTransport &transport, bool isSupportSrm, utility::Dispatcher &dispatcher, 356 std::function<int(ObexServerSession &)> removeFun, std::function<void(ObexServerSession &, bool)> setBusyFun); 357 ~ObexServerSession() override = default; 358 int Disconnect(); 359 int SendResponse(ObexHeader &resp) const; 360 int SendGetResponse(const ObexHeader &req, ObexHeader &resp, std::shared_ptr<ObexBodyObject> reader = nullptr); 361 int SendSimpleResponse(ObexRspCode rspCode) const; 362 int SendSrmResponse(); 363 void Invalid(); GetTransport()364 ObexTransport &GetTransport() const 365 { 366 return transport_; 367 } GetSendObject()368 std::unique_ptr<ObexServerSendObject> &GetSendObject() 369 { 370 return sendObject_; 371 } FreeSendObject()372 void FreeSendObject() 373 { 374 sendObject_ = nullptr; 375 } GetReceivedObject()376 std::unique_ptr<ObexServerReceivedObject> &GetReceivedObject() 377 { 378 return receivedObject_; 379 } CreateReceivedObject(const ObexHeader & firstReq,std::shared_ptr<ObexBodyObject> & writer)380 std::unique_ptr<ObexServerReceivedObject> &CreateReceivedObject( 381 const ObexHeader &firstReq, std::shared_ptr<ObexBodyObject> &writer) 382 { 383 receivedObject_ = std::make_unique<ObexServerReceivedObject>(firstReq, writer); 384 return receivedObject_; 385 } FreeReceivedObject()386 void FreeReceivedObject() 387 { 388 receivedObject_ = nullptr; 389 } IsSupportSrmMode()390 bool IsSupportSrmMode() const 391 { 392 return isSupportSrm_; 393 } 394 395 private: 396 int ProcessSendSrmResponse(); 397 std::unique_ptr<ObexServerSendObject> sendObject_ = nullptr; 398 std::unique_ptr<ObexServerReceivedObject> receivedObject_ = nullptr; 399 ObexTransport &transport_; 400 bool isSupportSrm_ = false; 401 utility::Dispatcher &dispatcher_; 402 std::function<int(ObexServerSession &)> removeFun_ {}; 403 std::function<void(ObexServerSession &, bool)> setBusyFun_ {}; 404 bool invalid_ = false; 405 BT_DISALLOW_COPY_AND_ASSIGN(ObexServerSession); 406 }; 407 } // namespace bluetooth 408 } // namespace OHOS 409 #endif // OBEX_SESSION_H 410