1 /* 2 * Copyright (c) 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 SOFT_BUS_CHANNEL_H 17 #define SOFT_BUS_CHANNEL_H 18 19 #include <atomic> 20 #include <condition_variable> 21 #include <mutex> 22 #include <memory> 23 #include <map> 24 #include <securec.h> 25 #include <string> 26 #include <zlib.h> 27 28 #include "accesstoken_log.h" 29 #include "nlohmann/json.hpp" 30 #include "rpc_channel.h" 31 #include "session.h" 32 #include "random.h" 33 34 namespace OHOS { 35 namespace Security { 36 namespace AccessToken { 37 class SoftBusChannel final : public RpcChannel, public std::enable_shared_from_this<SoftBusChannel> { 38 public: 39 SoftBusChannel(const std::string &deviceId); 40 virtual ~SoftBusChannel(); 41 42 /** 43 * @brief Build connection with peer device. 44 * 45 * @return Result code, 0 indicated build successfully, -1 indicates failure. 46 * @since 1.0 47 * @version 1.0 48 * @see Release 49 */ 50 int BuildConnection() override; 51 52 /** 53 * @brief Execute BaseRemoteCommand at peer device. 54 * 55 * @param commandName The name of Command. 56 * @param jsonPayload The json payload of command. 57 * @return Executed result response string. 58 * @since 1.0 59 * @version 1.0 60 */ 61 std::string ExecuteCommand(const std::string &commandName, const std::string &jsonPayload) override; 62 63 /** 64 * @brief Handle data received. This interface only use for soft bus channel. 65 * 66 * @param session Session with peer device. 67 * @param bytes Data sent from the peer device. 68 * @param length Data length sent from the peer device. 69 * @since 1.0 70 * @version 1.0 71 */ 72 void HandleDataReceived(int session, const unsigned char *bytes, int length) override; 73 74 /** 75 * @brief Close rpc connection when no data is being transmitted. it will run in a delayed task. 76 * 77 * @since 1.0 78 * @version 1.0 79 */ 80 void CloseConnection() override; 81 82 /** 83 * @brief Release resources when the device offline. 84 * 85 * @since 1.0 86 * @version 1.0 87 */ 88 void Release() override; 89 90 private: 91 /** 92 * @brief compress json command to char array command. 93 * 94 * @param type request or response 95 * @param id unique message id 96 * @param commandName command name 97 * @param jsonPayload command notated by json string 98 * @param bytes transfer data array 99 * @param bytesLength transfer data length 100 * @return The execute result, SUCCESS: 0; FAILURE: -1. 101 * @see Compress 102 * @since 1.0 103 * @version 1.0 104 */ 105 int PrepareBytes(const std::string &type, const std::string &id, const std::string &commandName, 106 const std::string &jsonPayload, const unsigned char *bytes, int &bytesLength); 107 108 /** 109 * @brief compress string to char array. 110 * 111 * @param json string to be compressed 112 * @param compressedBytes compressed data array 113 * @param compressedLength compressed data length 114 * @return The execute result, SUCCESS: 0; FAILURE: -1. 115 * @since 1.0 116 * @version 1.0 117 */ 118 int Compress(const std::string &json, const unsigned char *compressedBytes, int &compressedLength); 119 120 /** 121 * @brief decompress char array to string. 122 * 123 * @param bytes compressed data array 124 * @param length compressed data length 125 * @return decompressed string 126 * @since 1.0 127 * @version 1.0 128 */ 129 std::string Decompress(const unsigned char *bytes, const int length); 130 131 /** 132 * @brief transfer request data to soft bus. 133 * 134 * @param bytes data array to transfer 135 * @param bytesLength data length 136 * @return The execute result, SUCCESS: 0; FAILURE: -1. 137 * @since 1.0 138 * @version 1.0 139 */ 140 int SendRequestBytes(const unsigned char *bytes, const int bytesLength); 141 142 /** 143 * @brief transfer response data to soft bus. 144 * 145 * @param session response session id 146 * @param bytes data array to transfer 147 * @param bytesLength data length 148 * @return The execute result, SUCCESS: 0; FAILURE: -1. 149 * @since 1.0 150 * @version 1.0 151 */ 152 int SendResponseBytes(int session, const unsigned char *bytes, const int bytesLength); 153 154 /** 155 * @brief enforce session is available. if session is opened, reopen it. 156 * 157 * @return The execute result, SUCCESS: 0; FAILURE: -1. 158 * @since 1.0 159 * @version 1.0 160 */ 161 int CheckSessionMayReopenLocked(); 162 163 /** 164 * @brief check session is available. 165 * 166 * @return The execute result, available: true, otherwise: false. 167 * @since 1.0 168 * @version 1.0 169 */ 170 bool IsSessionAvailable(); 171 172 /** 173 * @brief cancel closing connection. 174 * 175 * @since 1.0 176 * @version 1.0 177 */ 178 void CancelCloseConnectionIfNeeded(); 179 180 /** 181 * @brief request callback for HandleDataReceived 182 * 183 * @param id unique message id 184 * @param commandName command name 185 * @param jsonPayload command notated by json string 186 * @return decompressed string 187 * @see HandleDataReceived 188 * @since 1.0 189 * @version 1.0 190 */ 191 void HandleRequest( 192 int session, const std::string &id, const std::string &commandName, const std::string &jsonPayload); 193 194 /** 195 * @brief response callback for HandleDataReceived 196 * 197 * @param id unique message id 198 * @param jsonPayload command notated by json string 199 * @return decompressed string 200 * @see HandleDataReceived 201 * @since 1.0 202 * @version 1.0 203 */ 204 void HandleResponse(const std::string &id, const std::string &jsonPayload); 205 206 /** 207 * @brief temp function to generate uuid. 208 * 209 * @param buf uuid string 210 * @param bufSize uuid string size 211 * @since 1.0 212 * @version 1.0 213 */ random_uuid(char buf[37],int bufSize)214 void random_uuid(char buf[37], int bufSize) 215 { 216 const int xbase = 15; 217 const int bbase = 255; 218 const int index6 = 6; 219 const int index8 = 8; 220 const int index3 = 3; 221 const int index5 = 5; 222 const int index7 = 7; 223 const int index9 = 9; 224 const int blen = 2; 225 const int uuidlen = 16; 226 const char *c = "89ab"; 227 char *p = buf; 228 int n; 229 230 for (n = 0; n < uuidlen; ++n) { 231 int b = static_cast<int32_t>(GetRandomUint32() % bbase); 232 switch (n) { 233 case index6: 234 if (sprintf_s(p, bufSize, "4%x", b % xbase) < 0) { 235 return; 236 } 237 break; 238 case index8: 239 if (sprintf_s(p, bufSize, "%c%x", c[GetRandomUint32() % strlen(c)], b % xbase) < 0) { 240 return; 241 } 242 break; 243 default: 244 if (sprintf_s(p, bufSize, "%02x", b) < 0) { 245 return; 246 } 247 break; 248 } 249 p += blen; 250 if (n == index3 || n == index5 || n == index7 || n == index9) { 251 *p++ = '-'; 252 break; 253 } 254 } 255 *p = 0; 256 // prevent array length warning 257 if (p - buf == bufSize) { 258 return; 259 } 260 } 261 262 // bind device id for this channel 263 std::string deviceId_; 264 265 // channel mutex 266 std::mutex mutex_; 267 268 // connection closing state. true: in closing, false: otherwise 269 bool isDelayClosing_; 270 271 // soft bus session mutex 272 std::mutex sessionMutex_; 273 274 // soft bus session id, -1 for invalid session id. 275 int session_; 276 277 // soft bus session busy flag, true: busy, false: otherwise 278 bool isSessionUsing_; 279 280 // communication callbacks map. key: unique message id, value: response callback. 281 std::map<std::string, std::function<void(std::string)>> callbacks_; 282 283 // callback function arguments: response string variable 284 std::string responseResult_; 285 // callback function execute variable 286 std::condition_variable loadedCond_; 287 }; 288 289 class SoftBusMessage { 290 public: SoftBusMessage(const std::string & type,const std::string & id,const std::string & commandName,const std::string & jsonPayload)291 SoftBusMessage( 292 const std::string &type, const std::string &id, const std::string &commandName, const std::string &jsonPayload) 293 : type_(type), id_(id), commandName_(commandName), jsonPayload_(jsonPayload) 294 {} 295 ~SoftBusMessage() = default; 296 IsValid()297 bool IsValid() const 298 { 299 if (this->type_.empty()) { 300 return false; 301 } 302 if (this->id_.empty()) { 303 return false; 304 } 305 if (this->commandName_.empty()) { 306 return false; 307 } 308 return !(this->jsonPayload_.empty()); 309 } 310 311 /** 312 * Convert SoftBusMessage object to corresponding json string. 313 * 314 * @return Soft bus message json string. 315 */ ToJson()316 std::string ToJson() const 317 { 318 nlohmann::json json; 319 json["type"] = this->type_; 320 json["id"] = this->id_; 321 json["commandName"] = this->commandName_; 322 json["jsonPayload"] = this->jsonPayload_; 323 return json.dump(); 324 } 325 GetType()326 const std::string &GetType() const 327 { 328 return type_; 329 } GetId()330 const std::string &GetId() const 331 { 332 return id_; 333 } GetCommandName()334 const std::string &GetCommandName() const 335 { 336 return commandName_; 337 } GetJsonPayload()338 const std::string &GetJsonPayload() const 339 { 340 return jsonPayload_; 341 } 342 343 static std::shared_ptr<SoftBusMessage> FromJson(const std::string &jsonString); 344 private: 345 std::string type_; 346 std::string id_; 347 std::string commandName_; 348 std::string jsonPayload_; 349 }; 350 } // namespace AccessToken 351 } // namespace Security 352 } // namespace OHOS 353 354 #endif // SOFT_BUS_CHANNEL_H 355