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_CLIENT_H 17 #define OBEX_CLIENT_H 18 19 #include <cstdint> 20 #include <cstring> 21 #include "btstack.h" 22 #include "dispatcher.h" 23 #include "obex_body.h" 24 #include "obex_headers.h" 25 #include "obex_session.h" 26 #include "obex_transport.h" 27 #include "obex_types.h" 28 29 namespace OHOS { 30 namespace bluetooth { 31 enum class ObexClientState : uint8_t { 32 INIT = 0, 33 TRANSPORT_CONNECTED, 34 RELIABLE_SESSION_CREATED, 35 OBEX_CONNECTED, 36 OBEX_DISCONNECTED, 37 RELIABLE_SESSION_SUSPENDED, 38 RELIABLE_SESSION_RESUMED, 39 RELIABLE_SESSION_CLOSED, 40 TRANSPORT_DISCONNECTED 41 }; 42 43 struct ObexClientConfig { 44 BtAddr addr_ {}; // Remote bluetooth address 45 uint16_t lpsm_ = 0; // l2cap's local psm while use l2cap 46 uint16_t scn_ = 0; // Rfcomm's channel num/ l2cap's psm 47 uint16_t mtu_ = 0; // The Maximum OBEX Packet Length.Default 1024byte 48 bool isGoepL2capPSM_ = false; // L2cap:true, rfcomm:false 49 bool isSupportSrm_ = false; // Using Single Response Mode 50 bool isSupportReliableSession_ = false; // Using reliable session 51 BtUuid serviceUUID_ {}; // Service's UUID128 52 }; 53 54 struct ObexConnectParams { 55 ObexTlvParamters *appParams_ = nullptr; // Application Parameters 56 ObexDigestChallenge *authChallenges_ = nullptr; // Auth Challenges 57 ObexDigestResponse *authResponses_ = nullptr; // Auth Responses 58 uint32_t *count = nullptr; // Count 59 }; 60 61 class ObexClient; 62 /** 63 * @brief Callback function \n 64 * used to notify the upper layer of the event and related information. 65 */ 66 class ObexClientObserver { 67 public: 68 virtual ~ObexClientObserver() = default; 69 /** 70 * @brief Called OnTransportFailed 71 * @param client ObexClient 72 * @param errCd error code 73 */ 74 virtual void OnTransportFailed(ObexClient &client, int errCd) = 0; 75 /** 76 * @brief Called OnConnected 77 * 78 * @param client ObexClient 79 * @param resp The Response from Server 80 */ 81 virtual void OnConnected(ObexClient &client, const ObexHeader &resp) = 0; 82 /** 83 * @brief Called OnConnectFailed 84 * 85 * @param client ObexClient 86 * @param resp The Response from Server 87 */ 88 virtual void OnConnectFailed(ObexClient &client, const ObexHeader &resp) = 0; 89 /** 90 * @brief Called OnDisconnected 91 * 92 * @param client ObexClient 93 */ 94 virtual void OnDisconnected(ObexClient &client) = 0; 95 /** 96 * @brief Called OnActionCompleted 97 * 98 * @param client ObexClient 99 * @param resp The Response from Server 100 */ 101 virtual void OnActionCompleted(ObexClient &client, const ObexHeader &resp) = 0; 102 /** 103 * @brief Called OnBusy 104 * 105 * @param client ObexClient 106 * @param isBusy true:become busy false:become not busy 107 */ 108 virtual void OnBusy(ObexClient &client, bool isBusy); 109 }; 110 111 /** 112 * @brief ObexClient\n 113 * ObexClient 114 */ 115 class ObexClient { 116 public: 117 // create obex client 118 explicit ObexClient(const ObexClientConfig &config, ObexClientObserver &observer, utility::Dispatcher &dispatcher); 119 120 // destroy obex client 121 virtual ~ObexClient() = default; 122 123 /** 124 * @brief send obex request 125 * 126 * @param req the data of obex request 127 * @return int Request processing result:0:succeeded -1:failed 128 */ 129 int SendRequest(const ObexHeader &req); 130 131 /** 132 * @brief send obex connect request 133 * 134 * @return int Request processing result:0:succeeded -1:failed 135 */ 136 int Connect(); 137 /** 138 * @brief send obex connect request with Parameters 139 * 140 * @param connectParams Connect Parameters 141 * @return int Request processing result:0:succeeded -1:failed 142 */ 143 int Connect(ObexConnectParams &connectParams); 144 /** 145 * @brief send obex disconnect request 146 * @param withObexReq is send obex disconnect request 147 * @return int Request processing result:0:succeeded -1:failed 148 */ 149 int Disconnect(bool withObexReq = true); 150 /** 151 * @brief send obex abort request 152 * 153 * @return int Request processing result:0:succeeded -1:failed 154 */ 155 int Abort(); 156 157 /** 158 * @brief send obex put request 159 * 160 * @param req the data of obex request 161 * @return int Request processing result:0:succeeded -1:failed 162 */ 163 int Put(const ObexHeader &req); 164 165 /** 166 * @brief send obex get request 167 * 168 * @param req the data of obex request for get 169 * @return int Request processing result:0:succeeded -1:failed 170 */ 171 int Get(const ObexHeader &req); 172 173 /** 174 * @brief send obex set_path request 175 * 176 * @param flag SETPATH flag \n 177 * bit 0:backup a level before applying name (equivalent to ../ on many systems)\n 178 * @see OBEX_SETPATH_BACKUP 179 * bit 1:Don’t create folder if it does not exist, return an error instead. 180 * @see OBEX_SETPATH_NOCREATE 181 * @param path path 182 * @return int Request processing result:0:succeeded -1:failed 183 */ 184 int SetPath(uint8_t flag, const std::u16string &path); 185 186 /** 187 * @brief send obex copy action request 188 * 189 * @param srcName Copy source name 190 * @param destName Copy destination name 191 * @return int Request processing result:0:succeeded -1:failed 192 */ 193 int Copy(const std::u16string &srcName, const std::u16string &destName); 194 /** 195 * @brief send obex move action request 196 * 197 * @param srcName Move source name 198 * @param destName Move destination name 199 * @return int Request processing result:0:succeeded -1:failed 200 */ 201 int Move(const std::u16string &srcName, const std::u16string &destName); 202 /** 203 * @brief send obex set permissions action request 204 * 205 * @param name Indicates the name of the object to perform the action upon. 206 * @param permissions Indicates the permissions for a Set Permissions action. 207 * @return int Request processing result:0:succeeded -1:failed 208 */ 209 int SetPermissions(const std::u16string &name, const uint32_t permissions); 210 211 /** 212 * @brief send obex CREATESESSION request \n 213 * The CREATESESSION command is sent by the Client to create a new session. 214 * @return int Request processing result:0:succeeded -1:failed 215 */ 216 int CreateSession(); 217 /** 218 * @brief send obex CREATESESSION request \n 219 * The CREATESESSION command is sent by the Client to create a new session. 220 * @param timeoutSec timeout specifying the number of seconds. 221 * default is OBEX_SESSION_MAX_TIMEOUT_SEC 222 * @return int Request processing result:0:succeeded -1:failed 223 */ 224 static int CreateSession(uint32_t timeoutSec); 225 226 /** 227 * @brief send obex SUSPENDSESSION request \n 228 * SUSPENDSESSION is used to gracefully suspend the active session. 229 * @return int Request processing result:0:succeeded -1:failed 230 */ 231 static int SuspendSession(); 232 233 /** 234 * @brief send obex RESUMESESSION request \n 235 * RESUMESESSION is used to resume a session that has been suspended. 236 * @return int Request processing result:0:succeeded -1:failed 237 */ 238 static int ResumeSession(); 239 240 /** 241 * @brief send obex CLOSESESSION request \n 242 * CLOSESESSION is used to gracefully close an existing session. 243 * @return int Request processing result:0:succeeded -1:failed 244 */ 245 static int CloseSession(); 246 247 /** 248 * @brief send obex SETTIMEOUT request \n 249 * The SETTIMEOUT command is used to negotiate a new timeout specifying the number of seconds a \n 250 * session should be maintained while the session is suspended. 251 * @param timeoutSec timeout specifying the number of seconds 252 * @return int Request processing result:0:succeeded -1:failed 253 */ 254 static int SetSessionTimeout(uint32_t timeoutSec = OBEX_SESSION_MAX_TIMEOUT_SEC); 255 256 // Get ClientSession 257 ObexClientSession &GetClientSession() const; 258 259 // Get GetClientId 260 const std::string &GetClientId(); 261 262 static int RegisterL2capLPsm(uint16_t lpsm); 263 static void DeregisterL2capLPsm(uint16_t lpsm); 264 265 protected: 266 // Client Transport Obsverver 267 class ObexClientTransportObserver : public ObexTransportObserver { 268 public: 269 explicit ObexClientTransportObserver(ObexClient &obexClient); 270 ~ObexClientTransportObserver() override = default; 271 // call back from transport 272 void OnTransportConnected(ObexTransport &transport) override; 273 void OnTransportDisconnected(ObexTransport &transport) override; 274 void OnTransportDataAvailable(ObexTransport &transport, ObexPacket &obexPacket) override; 275 void OnTransportDataBusy(ObexTransport &transport, uint8_t isBusy) override; 276 void OnTransportError(ObexTransport &transport, int errCd) override; 277 278 private: 279 ObexClient &obexClient_; 280 std::unique_ptr<bluetooth::ObexHeader> GetObexHeaderFromPacket(ObexPacket &obexPacket); 281 void HandleDataAvailableConnect(const ObexHeader &resp); 282 void HandleDataAvailableDisconnect(const ObexHeader &resp); 283 void HandleDataAvailablePut(const ObexHeader &resp); 284 void HandleDataAvailableGet(const ObexHeader &resp); 285 void HandleDataAvailableSetPath(const ObexHeader &resp); 286 void HandleDataAvailableSession(const ObexHeader &resp); 287 void HandleDataAvailableAbort(const ObexHeader &resp); 288 void HandleDataAvailableAction(const ObexHeader &resp); 289 BT_DISALLOW_COPY_AND_ASSIGN(ObexClientTransportObserver); 290 }; 291 292 int ProcessAbort(); 293 int SendAbortRequest(); 294 int SendConnectRequest(ObexHeader &header); 295 bool CheckBeforeRequest(uint8_t opeId) const; 296 static bool CheckBeforeSession(uint8_t sessionOpcode); 297 virtual void PutDataAvailable(const ObexHeader &resp); 298 virtual void GetDataAvailable(const ObexHeader &resp); 299 virtual void SetPathDataAvailable(const ObexHeader &resp); 300 virtual void AbortDataAvailable(const ObexHeader &resp); 301 virtual void HandleTransportDataBusy(uint8_t isBusy); 302 virtual void SetBusy(bool isBusy); 303 std::unique_ptr<ObexClientTransportObserver> transportObserver_ = nullptr; 304 std::unique_ptr<ObexClientSession> clientSession_ = nullptr; 305 std::unique_ptr<ObexClientTransport> clientTransport_ = nullptr; 306 std::unique_ptr<ObexHeader> connectReqHeader_ = nullptr; 307 std::unique_ptr<ObexHeader> reliableSessionReqHeader_ = nullptr; 308 ObexClientObserver &clientObserver_; 309 ObexClientState clientState_ = ObexClientState::INIT; 310 bool isObexConnected_ = false; 311 bool isWaitingSendAbort_ = false; 312 bool isAbortSended_ = false; 313 bool isReliableSessionCreated_ = false; 314 bool isSupportSrm_ = false; 315 bool isSupportReliableSession_ = false; 316 bool isProcessing_ = false; 317 std::string clientId_ = ""; 318 utility::Dispatcher &dispatcher_; 319 BT_DISALLOW_COPY_AND_ASSIGN(ObexClient); 320 }; 321 } // namespace bluetooth 322 } // namespace OHOS 323 #endif // OBEX_CLIENT_H