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