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