1 /* 2 * Copyright (C) 2021 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 #include "base.h" 16 #include <algorithm> 17 #include <chrono> 18 #include <cstdio> 19 #include <cstring> 20 #include <dirent.h> 21 #include <openssl/bio.h> 22 #include <openssl/buffer.h> 23 #include <openssl/evp.h> 24 #include <openssl/md5.h> 25 #include <random> 26 #include <sstream> 27 #include <sys/stat.h> 28 #include <thread> 29 #include <vector> 30 #ifdef HDC_HILOG 31 #include "hilog/log.h" 32 #endif 33 using namespace std::chrono; 34 35 namespace Hdc { 36 namespace Base { 37 constexpr int DEF_FILE_PERMISSION = 0750; GetLogLevel()38 uint8_t GetLogLevel() 39 { 40 return g_logLevel; 41 } 42 #ifndef HDC_HILOG 43 std::atomic<bool> g_logCache = true; 44 #endif 45 uint8_t g_logLevel = LOG_DEBUG; // tmp set,now debugmode.LOG_OFF when release;; SetLogLevel(const uint8_t logLevel)46 void SetLogLevel(const uint8_t logLevel) 47 { 48 g_logLevel = logLevel; 49 } 50 GetLogLevelByEnv()51 uint8_t GetLogLevelByEnv() 52 { 53 char *env = getenv(ENV_SERVER_LOG.c_str()); 54 if (!env) { 55 return GetLogLevel(); 56 } 57 size_t len = strlen(env); 58 59 size_t maxLen = 1; 60 if (len > maxLen) { 61 WRITE_LOG(LOG_WARN, "OHOS_HDC_LOG_LEVEL %s is not in (0, 6] range", env); 62 return GetLogLevel(); 63 } 64 65 for (size_t i = 0; i < len; i++) { 66 if (isdigit(env[i]) == 0) { 67 WRITE_LOG(LOG_WARN, "OHOS_HDC_LOG_LEVEL %s is not digit", env); 68 return GetLogLevel(); 69 } 70 } 71 72 uint8_t logLevel = static_cast<uint8_t>(atoi(env)); 73 if (logLevel < 0 || logLevel > LOG_LAST) { 74 WRITE_LOG(LOG_WARN, "OHOS_HDC_LOG_LEVEL %d is not in (0, 6] range", logLevel); 75 } else { 76 return logLevel; 77 } 78 79 return GetLogLevel(); 80 } 81 82 // Commenting the code will optimize and tune all log codes, and the compilation volume will be greatly reduced 83 #define ENABLE_DEBUGLOG 84 #ifdef ENABLE_DEBUGLOG GetLogDebugFunctionName(string & debugInfo,int line,string & threadIdString)85 void GetLogDebugFunctionName(string &debugInfo, int line, string &threadIdString) 86 { 87 string tmpString = GetFileNameAny(debugInfo); 88 debugInfo = StringFormat("%s:%d", tmpString.c_str(), line); 89 if (g_logLevel < LOG_DEBUG) { 90 debugInfo = ""; 91 threadIdString = ""; 92 } else { 93 debugInfo = "[" + debugInfo + "]"; 94 threadIdString = StringFormat("[%x]", std::hash<std::thread::id> {}(std::this_thread::get_id())); 95 } 96 } 97 GetLogLevelAndTime(uint8_t logLevel,string & logLevelString,string & timeString)98 void GetLogLevelAndTime(uint8_t logLevel, string &logLevelString, string &timeString) 99 { 100 system_clock::time_point timeNow = system_clock::now(); // now time 101 system_clock::duration sinceUnix0 = timeNow.time_since_epoch(); // since 1970 102 time_t sSinceUnix0 = duration_cast<seconds>(sinceUnix0).count(); 103 std::tm *tim = std::localtime(&sSinceUnix0); 104 switch (logLevel) { 105 case LOG_FATAL: 106 logLevelString = "F"; 107 break; 108 case LOG_INFO: 109 logLevelString = "I"; 110 break; 111 case LOG_WARN: 112 logLevelString = "W"; 113 break; 114 case LOG_DEBUG: // will reduce performance 115 logLevelString = "D"; 116 break; 117 default: // all, just more IO/Memory information 118 logLevelString = "A"; 119 break; 120 } 121 string msTimeSurplus; 122 if (g_logLevel >= LOG_DEBUG) { 123 const auto sSinceUnix0Rest = duration_cast<milliseconds>(sinceUnix0).count() % TIME_BASE; 124 msTimeSurplus = StringFormat(".%03llu", sSinceUnix0Rest); 125 } 126 timeString = msTimeSurplus; 127 if (tim != nullptr) { 128 char buffer[TIME_BUF_SIZE]; 129 (void)strftime(buffer, TIME_BUF_SIZE, "%Y-%m-%d %H:%M:%S", tim); 130 timeString = StringFormat("%s%s", buffer, msTimeSurplus.c_str()); 131 } 132 } 133 134 #ifndef HDC_HILOG LogToPath(const char * path,const char * str)135 void LogToPath(const char *path, const char *str) 136 { 137 // logfile, not thread-safe 138 #ifdef HDC_DEBUG_UART 139 // make a log path print. 140 static std::once_flag firstLog; 141 std::call_once(firstLog, [&]() { printf("log at %s\n", path); }); 142 // better than open log file every time. 143 static std::unique_ptr<FILE, decltype(&fclose)> file(fopen(path, "w"), &fclose); 144 FILE *fp = file.get(); 145 if (fp == nullptr) { 146 return; 147 } 148 if (fprintf(fp, "%s", str) > 0 && fflush(fp)) { 149 // make ci happy 150 } 151 fclose(fp); 152 #else 153 int flags = UV_FS_O_RDWR | UV_FS_O_APPEND | UV_FS_O_CREAT; 154 uv_fs_t req; 155 int fd = uv_fs_open(nullptr, &req, path, flags, S_IWUSR | S_IRUSR, nullptr); 156 if (fd < 0) { 157 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 158 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 159 uv_fs_req_cleanup(&req); 160 PrintMessage("LogToPath uv_fs_open %s error %s", path, buffer); 161 return; 162 } 163 string text(str); 164 uv_buf_t wbf = uv_buf_init((char *)str, text.size()); 165 uv_fs_req_cleanup(&req); 166 uv_fs_write(nullptr, &req, fd, &wbf, 1, -1, nullptr); 167 uv_fs_close(nullptr, &req, fd, nullptr); 168 #endif 169 } 170 GetTimeString(string & timeString)171 void GetTimeString(string &timeString) 172 { 173 system_clock::time_point timeNow = system_clock::now(); 174 system_clock::duration sinceUnix0 = timeNow.time_since_epoch(); // since 1970 175 time_t sinceUnix0Time = duration_cast<seconds>(sinceUnix0).count(); 176 std::tm *timeTm = std::localtime(&sinceUnix0Time); 177 178 const auto sinceUnix0Rest = duration_cast<milliseconds>(sinceUnix0).count() % TIME_BASE; 179 string msTimeSurplus = StringFormat("%03llu", sinceUnix0Rest); 180 timeString = msTimeSurplus; 181 if (timeTm != nullptr) { 182 char buffer[TIME_BUF_SIZE] = {0}; 183 if (strftime(buffer, TIME_BUF_SIZE, "%Y%m%d-%H%M%S", timeTm) > 0) { 184 timeString = StringFormat("%s%s", buffer, msTimeSurplus.c_str()); 185 } 186 } 187 } 188 CompareLogFileName(const string & a,const string & b)189 bool CompareLogFileName(const string &a, const string &b) 190 { 191 return strcmp(a.c_str(), b.c_str()) < 0; 192 } 193 RemoveOlderLogFiles()194 void RemoveOlderLogFiles() 195 { 196 vector<string> files; 197 DIR* dir = opendir(GetTmpDir().c_str()); 198 if (dir == nullptr) { 199 WRITE_LOG(LOG_WARN, "open log dir failed"); 200 return; 201 } 202 203 struct dirent* entry; 204 while ((entry = readdir(dir)) != nullptr) { 205 string fileName = entry->d_name; 206 if (strncmp(fileName.c_str(), LOG_FILE_NAME_PREFIX.c_str(), LOG_FILE_NAME_PREFIX.size()) == 0) { 207 files.push_back(fileName); 208 } 209 } 210 closedir(dir); 211 212 if (files.size() <= MAX_LOG_FILE_COUNT) { 213 return; 214 } 215 216 // Sort file names by time, with earlier ones coming first 217 sort(files.begin(), files.end(), CompareLogFileName); 218 219 uint16_t deleteCount = files.size() - MAX_LOG_FILE_COUNT; 220 WRITE_LOG(LOG_INFO, "will delete log file, count: %u", deleteCount); 221 uint16_t count = 0; 222 for (auto name : files) { 223 if (count >= deleteCount) { 224 break; 225 } 226 string deleteFile = GetTmpDir() + name; 227 WRITE_LOG(LOG_INFO, "delete: %s", deleteFile.c_str()); 228 unlink(deleteFile.c_str()); 229 count++; 230 } 231 } 232 LogToFile(const char * str)233 void LogToFile(const char *str) 234 { 235 string path = GetTmpDir() + LOG_FILE_NAME; 236 RollLogFile(path.c_str()); 237 LogToPath(path.c_str(), str); 238 } 239 LogToCache(const char * str)240 void LogToCache(const char *str) 241 { 242 string path = GetTmpDir() + LOG_CACHE_NAME; 243 LogToPath(path.c_str(), str); 244 } 245 RollLogFile(const char * path)246 void RollLogFile(const char *path) 247 { 248 int value = -1; 249 uv_fs_t fs; 250 value = uv_fs_stat(nullptr, &fs, path, nullptr); 251 if (value != 0) { 252 constexpr int bufSize = 1024; 253 char buf[bufSize] = { 0 }; 254 uv_strerror_r(value, buf, bufSize); 255 PrintMessage("RollLogFile error log file %s not exist %s", path, buf); 256 return; 257 } 258 uint64_t size = fs.statbuf.st_size; 259 if (size < LOG_FILE_MAX_SIZE) { 260 return; 261 } 262 string timeStr; 263 GetTimeString(timeStr); 264 string last = GetTmpDir() + LOG_FILE_NAME_PREFIX + timeStr + ".log"; 265 value = uv_fs_rename(nullptr, &fs, path, last.c_str(), nullptr); 266 if (value != 0) { 267 constexpr int bufSize = 1024; 268 char buf[bufSize] = { 0 }; 269 uv_strerror_r(value, buf, bufSize); 270 PrintMessage("RollLogFile error rename %s to %s %s", path, last.c_str(), buf); 271 return; 272 } 273 RemoveOlderLogFiles(); 274 } 275 ChmodLogFile()276 void ChmodLogFile() 277 { 278 string path = GetTmpDir() + LOG_FILE_NAME; 279 uv_fs_t req = {}; 280 uv_fs_req_cleanup(&req); 281 int rc = uv_fs_chmod(nullptr, &req, path.c_str(), 0664, nullptr); 282 if (rc < 0) { 283 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 284 uv_strerror_r(rc, buffer, BUF_SIZE_DEFAULT); 285 WRITE_LOG(LOG_FATAL, "uv_fs_chmod %s failed %s", path.c_str(), buffer); 286 } 287 } 288 #endif 289 PrintLogEx(const char * functionName,int line,uint8_t logLevel,const char * msg,...)290 void PrintLogEx(const char *functionName, int line, uint8_t logLevel, const char *msg, ...) 291 { 292 if (logLevel > g_logLevel) { 293 return; 294 } 295 296 char buf[BUF_SIZE_DEFAULT4] = { 0 }; // only 4k to avoid stack overflow in 32bit or L0 297 va_list vaArgs; 298 va_start(vaArgs, msg); 299 const int retSize = vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, msg, vaArgs); 300 va_end(vaArgs); 301 if (retSize < 0) { 302 return; 303 } 304 305 #ifdef HDC_HILOG 306 string tmpPath = functionName; 307 string filePath = GetFileNameAny(tmpPath); 308 static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = {LOG_CORE, 0xD002D13, "HDC_LOG"}; 309 switch (static_cast<int>(logLevel)) { 310 case static_cast<int>(LOG_DEBUG): 311 // Info level log can be printed default in hilog, debug can't 312 OHOS::HiviewDFX::HiLog::Info(LOG_LABEL, "[%{public}s:%{public}d] %{public}s", 313 filePath.c_str(), line, buf); 314 break; 315 case static_cast<int>(LOG_INFO): 316 OHOS::HiviewDFX::HiLog::Info(LOG_LABEL, "[%{public}s:%{public}d] %{public}s", 317 filePath.c_str(), line, buf); 318 break; 319 case static_cast<int>(LOG_WARN): 320 OHOS::HiviewDFX::HiLog::Warn(LOG_LABEL, "[%{public}s:%{public}d] %{public}s", 321 filePath.c_str(), line, buf); 322 break; 323 case static_cast<int>(LOG_FATAL): 324 OHOS::HiviewDFX::HiLog::Fatal(LOG_LABEL, "[%{public}s:%{public}d] %{public}s", 325 filePath.c_str(), line, buf); 326 break; 327 default: 328 break; 329 } 330 #else 331 string logLevelString; 332 string threadIdString; 333 string sep = "\n"; 334 string timeString; 335 if (string(buf).back() == '\n') { 336 sep = "\r\n"; 337 } 338 string debugInfo = functionName; 339 GetLogDebugFunctionName(debugInfo, line, threadIdString); 340 GetLogLevelAndTime(logLevel, logLevelString, timeString); 341 string logBuf = StringFormat("[%s][%s]%s%s %s%s", logLevelString.c_str(), timeString.c_str(), 342 threadIdString.c_str(), debugInfo.c_str(), buf, sep.c_str()); 343 344 printf("%s", logBuf.c_str()); 345 fflush(stdout); 346 347 if (!g_logCache) { 348 LogToFile(logBuf.c_str()); 349 } else { 350 LogToCache(logBuf.c_str()); 351 } 352 #endif 353 return; 354 } 355 #else // else ENABLE_DEBUGLOG.If disabled, the entire output code will be optimized by the compiler PrintLogEx(const char * functionName,int line,uint8_t logLevel,char * msg,...)356 void PrintLogEx(const char *functionName, int line, uint8_t logLevel, char *msg, ...) 357 { 358 } 359 #endif // ENABLE_DEBUGLOG 360 PrintMessage(const char * fmt,...)361 void PrintMessage(const char *fmt, ...) 362 { 363 va_list ap; 364 va_start(ap, fmt); 365 if (vfprintf(stdout, fmt, ap) > 0) { 366 fprintf(stdout, "\n"); 367 } 368 va_end(ap); 369 } 370 371 // if can linkwith -lstdc++fs, use std::filesystem::path(path).filename(); GetFileNameAny(string & path)372 string GetFileNameAny(string &path) 373 { 374 string tmpString = path; 375 size_t tmpNum = tmpString.rfind('/'); 376 if (tmpNum == std::string::npos) { 377 tmpNum = tmpString.rfind('\\'); 378 if (tmpNum == std::string::npos) { 379 return tmpString; 380 } 381 } 382 tmpString = tmpString.substr(tmpNum + 1, tmpString.size() - tmpNum); 383 return tmpString; 384 } 385 SetTcpOptions(uv_tcp_t * tcpHandle,int bufMaxSize)386 void SetTcpOptions(uv_tcp_t *tcpHandle, int bufMaxSize) 387 { 388 if (!tcpHandle) { 389 return; 390 } 391 uv_tcp_keepalive(tcpHandle, 1, GLOBAL_TIMEOUT); 392 // if MAX_SIZE_IOBUF==5k,bufMaxSize at least 40k. It must be set to io 8 times is more appropriate, 393 // otherwise asynchronous IO is too fast, a lot of IO is wasted on IOloop, transmission speed will decrease 394 395 uv_recv_buffer_size((uv_handle_t *)tcpHandle, &bufMaxSize); 396 uv_send_buffer_size((uv_handle_t *)tcpHandle, &bufMaxSize); 397 } 398 ReallocBuf(uint8_t ** origBuf,int * nOrigSize,size_t sizeWanted)399 void ReallocBuf(uint8_t **origBuf, int *nOrigSize, size_t sizeWanted) 400 { 401 if (*nOrigSize > 0) 402 return; 403 if (sizeWanted <= 0 || sizeWanted >= HDC_BUF_MAX_BYTES) { 404 WRITE_LOG(LOG_WARN, "ReallocBuf failed, sizeWanted:%d", sizeWanted); 405 return; 406 } 407 *origBuf = new uint8_t[sizeWanted]; 408 if (!*origBuf) { 409 WRITE_LOG(LOG_WARN, "ReallocBuf failed, origBuf is null. sizeWanted:%d", sizeWanted); 410 return; 411 } 412 *nOrigSize = sizeWanted; 413 } 414 415 // As an uv_alloc_cb it must keep the same as prototype AllocBufferCallback(uv_handle_t * handle,size_t sizeSuggested,uv_buf_t * buf)416 void AllocBufferCallback(uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf) 417 { 418 const int size = GetMaxBufSize(); 419 buf->base = (char *)new uint8_t[size](); 420 if (buf->base) { 421 buf->len = size - 1; 422 } 423 } 424 425 // As an uv_write_cb it must keep the same as prototype SendCallback(uv_write_t * req,int status)426 void SendCallback(uv_write_t *req, int status) 427 { 428 StartTraceScope("Base::SendCallback"); 429 if (status < 0) { 430 constexpr int bufSize = 1024; 431 char buf[bufSize] = { 0 }; 432 uv_strerror_r(status, buf, bufSize); 433 WRITE_LOG(LOG_WARN, "SendCallback failed,status:%d %s", status, buf); 434 } 435 delete[]((uint8_t *)req->data); 436 delete req; 437 } 438 439 // xxx must keep sync with uv_loop_close/uv_walk etc. TryCloseLoop(uv_loop_t * ptrLoop,const char * callerName)440 bool TryCloseLoop(uv_loop_t *ptrLoop, const char *callerName) 441 { 442 // UV_RUN_DEFAULT: Runs the event loop until the reference count drops to zero. Always returns zero. 443 // UV_RUN_ONCE: Poll for new events once. Note that this function blocks if there are no pending events. 444 // Returns zero when done (no active handles or requests left), or non-zero if more events are 445 // expected meaning you should run the event loop again sometime in the future). 446 // UV_RUN_NOWAIT: Poll for new events once but don't block if there are no pending events. 447 uint8_t closeRetry = 0; 448 bool ret = false; 449 constexpr int maxRetry = 3; 450 for (closeRetry = 0; closeRetry < maxRetry; ++closeRetry) { 451 if (uv_loop_close(ptrLoop) == UV_EBUSY) { 452 if (closeRetry > 2) { // 2:try 2 times close,the 3rd try shows uv loop cannot close. 453 WRITE_LOG(LOG_WARN, "%s close busy,try:%d", callerName, closeRetry); 454 } 455 456 if (ptrLoop->active_handles >= 2) { // 2:at least 2 handles for read & write. 457 WRITE_LOG(LOG_DEBUG, "TryCloseLoop issue"); 458 } 459 auto clearLoopTask = [](uv_handle_t *handle, void *arg) -> void { TryCloseHandle(handle); }; 460 uv_walk(ptrLoop, clearLoopTask, nullptr); 461 // If all processing ends, Then return0,this call will block 462 if (!ptrLoop->active_handles) { 463 ret = true; 464 break; 465 } 466 if (!uv_run(ptrLoop, UV_RUN_ONCE)) { 467 ret = true; 468 break; 469 } 470 usleep(10000); // 10000:sleep for 10s 471 } else { 472 WRITE_LOG(LOG_DEBUG, "Try close loop success"); 473 ret = true; 474 break; 475 } 476 } 477 return ret; 478 } 479 480 // xxx must keep sync with uv_loop_close/uv_walk etc. TryCloseChildLoop(uv_loop_t * ptrLoop,const char * callerName)481 bool TryCloseChildLoop(uv_loop_t *ptrLoop, const char *callerName) 482 { 483 // UV_RUN_DEFAULT: Runs the event loop until the reference count drops to zero. Always returns zero. 484 // UV_RUN_ONCE: Poll for new events once. Note that this function blocks if there are no pending events. 485 // Returns zero when done (no active handles or requests left), or non-zero if more events are 486 // expected meaning you should run the event loop again sometime in the future). 487 // UV_RUN_NOWAIT: Poll for new events once but don't block if there are no pending events. 488 uint8_t closeRetry = 0; 489 bool ret = false; 490 constexpr int maxRetry = 3; 491 for (closeRetry = 0; closeRetry < maxRetry; ++closeRetry) { 492 if (uv_loop_close(ptrLoop) == UV_EBUSY) { 493 if (closeRetry > 2) { // 2:try 2 times close,the 3rd try shows uv loop cannot close. 494 WRITE_LOG(LOG_WARN, "%s close busy,try:%d", callerName, closeRetry); 495 } 496 497 if (ptrLoop->active_handles >= 2) { // 2:at least 2 handles for read & write. 498 WRITE_LOG(LOG_DEBUG, "TryCloseLoop issue"); 499 } 500 auto clearLoopTask = [](uv_handle_t *handle, void *arg) -> void { TryCloseHandle(handle); }; 501 uv_walk(ptrLoop, clearLoopTask, nullptr); 502 #ifdef HDC_HOST 503 // If all processing ends, Then return0,this call will block 504 if (!ptrLoop->active_handles) { 505 ret = true; 506 break; 507 } 508 if (!uv_run(ptrLoop, UV_RUN_ONCE)) { 509 ret = true; 510 break; 511 } 512 usleep(10000); // 10000:sleep for 10s 513 #else 514 int r = 0; 515 int count = 0; 516 do { 517 count++; 518 r = uv_run(ptrLoop, UV_RUN_NOWAIT); 519 uv_sleep(MILL_SECONDS); //10 millseconds 520 } while (r != 0 && count <= COUNT); 521 #endif 522 } else { 523 WRITE_LOG(LOG_DEBUG, "Try close loop success"); 524 ret = true; 525 break; 526 } 527 } 528 return ret; 529 } 530 531 // Some handles may not be initialized or activated yet or have been closed, skip the closing process TryCloseHandle(const uv_handle_t * handle)532 void TryCloseHandle(const uv_handle_t *handle) 533 { 534 TryCloseHandle(handle, nullptr); 535 } 536 TryCloseHandle(const uv_handle_t * handle,uv_close_cb closeCallBack)537 void TryCloseHandle(const uv_handle_t *handle, uv_close_cb closeCallBack) 538 { 539 TryCloseHandle(handle, false, closeCallBack); 540 } 541 TryCloseHandle(const uv_handle_t * handle,bool alwaysCallback,uv_close_cb closeCallBack)542 void TryCloseHandle(const uv_handle_t *handle, bool alwaysCallback, uv_close_cb closeCallBack) 543 { 544 bool hasCallClose = false; 545 if (handle->loop && !uv_is_closing(handle)) { 546 uv_close((uv_handle_t *)handle, closeCallBack); 547 hasCallClose = true; 548 } 549 if (!hasCallClose && alwaysCallback) { 550 closeCallBack((uv_handle_t *)handle); 551 } 552 } 553 SendToStream(uv_stream_t * handleStream,const uint8_t * buf,const int bufLen)554 int SendToStream(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen) 555 { 556 StartTraceScope("Base::SendToStream"); 557 if (bufLen > static_cast<int>(HDC_BUF_MAX_BYTES)) { 558 return ERR_BUF_ALLOC; 559 } 560 uint8_t *pDynBuf = new uint8_t[bufLen]; 561 if (!pDynBuf) { 562 WRITE_LOG(LOG_WARN, "SendToStream, alloc failed, size:%d", bufLen); 563 return ERR_BUF_ALLOC; 564 } 565 if (memcpy_s(pDynBuf, bufLen, buf, bufLen)) { 566 WRITE_LOG(LOG_WARN, "SendToStream, memory copy failed, size:%d", bufLen); 567 delete[] pDynBuf; 568 return ERR_BUF_COPY; 569 } 570 return SendToStreamEx(handleStream, pDynBuf, bufLen, nullptr, 571 reinterpret_cast<void *>(SendCallback), reinterpret_cast<void *>(pDynBuf)); 572 } 573 574 // handleSend is used for pipe thread sending, set nullptr for tcp, and dynamically allocated by malloc when buf 575 // is required SendToStreamEx(uv_stream_t * handleStream,const uint8_t * buf,const int bufLen,uv_stream_t * handleSend,const void * finishCallback,const void * pWriteReqData)576 int SendToStreamEx(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen, uv_stream_t *handleSend, 577 const void *finishCallback, const void *pWriteReqData) 578 { 579 StartTraceScope("Base::SendToStreamEx"); 580 int ret = ERR_GENERIC; 581 uv_write_t *reqWrite = new uv_write_t(); 582 if (!reqWrite) { 583 WRITE_LOG(LOG_WARN, "SendToStreamEx, new write_t failed, size:%d", bufLen); 584 return ERR_BUF_ALLOC; 585 } 586 uv_buf_t bfr; 587 while (true) { 588 reqWrite->data = (void *)pWriteReqData; 589 bfr.base = (char *)buf; 590 bfr.len = bufLen; 591 if (!uv_is_writable(handleStream)) { 592 WRITE_LOG(LOG_WARN, "SendToStreamEx, uv_is_writable false, size:%d", bufLen); 593 delete reqWrite; 594 break; 595 } 596 // handleSend must be a TCP socket or pipe, which is a server or a connection (listening or 597 // connected state). Bound sockets or pipes will be assumed to be servers. 598 if (handleSend) { 599 ret = uv_write2(reqWrite, handleStream, &bfr, 1, handleSend, (uv_write_cb)finishCallback); 600 } else { 601 ret = uv_write(reqWrite, handleStream, &bfr, 1, (uv_write_cb)finishCallback); 602 } 603 if (ret < 0) { 604 WRITE_LOG(LOG_WARN, "SendToStreamEx, uv_write false, size:%d", bufLen); 605 delete reqWrite; 606 ret = ERR_IO_FAIL; 607 break; 608 } 609 ret = bufLen; 610 break; 611 } 612 return ret; 613 } 614 SendToPollFd(int fd,const uint8_t * buf,const int bufLen)615 int SendToPollFd(int fd, const uint8_t *buf, const int bufLen) 616 { 617 if (bufLen > static_cast<int>(HDC_BUF_MAX_BYTES)) { 618 return ERR_BUF_ALLOC; 619 } 620 uint8_t *pDynBuf = new uint8_t[bufLen]; 621 if (!pDynBuf) { 622 WRITE_LOG(LOG_WARN, "SendToPollFd, alloc failed, size:%d", bufLen); 623 return ERR_BUF_ALLOC; 624 } 625 if (memcpy_s(pDynBuf, bufLen, buf, bufLen)) { 626 WRITE_LOG(LOG_WARN, "SendToPollFd, memory copy failed, size:%d", bufLen); 627 delete[] pDynBuf; 628 return ERR_BUF_COPY; 629 } 630 int ret = Base::WriteToFd(fd, pDynBuf, bufLen); 631 delete[] pDynBuf; 632 return ret; 633 } 634 GetRuntimeMSec()635 uint64_t GetRuntimeMSec() 636 { 637 struct timespec times = { 0, 0 }; 638 long time; 639 clock_gettime(CLOCK_MONOTONIC, ×); 640 time = times.tv_sec * TIME_BASE + times.tv_nsec / (TIME_BASE * TIME_BASE); 641 return time; 642 } 643 GetRandom(const uint64_t min,const uint64_t max)644 uint64_t GetRandom(const uint64_t min, const uint64_t max) 645 { 646 #ifdef HARMONY_PROJECT 647 uint64_t ret; 648 uv_random(nullptr, nullptr, &ret, sizeof(ret), 0, nullptr); 649 #else 650 uint64_t ret; 651 std::random_device rd; 652 std::mt19937 gen(rd()); 653 std::uniform_int_distribution<uint64_t> dis(min, max); 654 ret = dis(gen); 655 #endif 656 return ret; 657 } 658 GetRandomString(const uint16_t expectedLen)659 string GetRandomString(const uint16_t expectedLen) 660 { 661 srand(static_cast<unsigned int>(GetRandom())); 662 string ret = string(expectedLen, '0'); 663 std::stringstream val; 664 for (auto i = 0; i < expectedLen; ++i) { 665 val << std::hex << (rand() % BUF_SIZE_MICRO); 666 } 667 ret = val.str(); 668 return ret; 669 } 670 GetRandomNum(const int min,const int max)671 int GetRandomNum(const int min, const int max) 672 { 673 return static_cast<int>(GetRandom(min, max)); 674 } 675 ConnectKey2IPPort(const char * connectKey,char * outIP,uint16_t * outPort)676 int ConnectKey2IPPort(const char *connectKey, char *outIP, uint16_t *outPort) 677 { 678 char bufString[BUF_SIZE_TINY] = ""; 679 if (strncpy_s(bufString, sizeof(bufString), connectKey, strlen(connectKey))) { 680 return ERR_BUF_COPY; 681 } 682 char *p = strrchr(bufString, ':'); 683 if (!p) { 684 return ERR_PARM_FORMAT; 685 } 686 *p = '\0'; 687 if (!strlen(bufString) || strlen(bufString) > 40) { // 40 : bigger than length of ipv6 688 return ERR_PARM_SIZE; 689 } 690 uint16_t wPort = static_cast<uint16_t>(atoi(p + 1)); 691 if (EOK != strcpy_s(outIP, BUF_SIZE_TINY, bufString)) { 692 return ERR_BUF_COPY; 693 } 694 *outPort = wPort; 695 return RET_SUCCESS; 696 } 697 698 // After creating the session worker thread, execute it on the main thread FinishWorkThread(uv_work_t * req,int status)699 void FinishWorkThread(uv_work_t *req, int status) 700 { 701 // This is operated in the main thread 702 delete req; 703 } 704 705 // at the finish of pFuncAfterThread must free uv_work_t* 706 // clang-format off StartWorkThread(uv_loop_t * loop,uv_work_cb pFuncWorkThread,uv_after_work_cb pFuncAfterThread,void * pThreadData)707 int StartWorkThread(uv_loop_t *loop, uv_work_cb pFuncWorkThread, 708 uv_after_work_cb pFuncAfterThread, void *pThreadData) 709 { 710 uv_work_t *workThread = new uv_work_t(); 711 if (!workThread) { 712 return -1; 713 } 714 workThread->data = pThreadData; 715 uv_queue_work(loop, workThread, pFuncWorkThread, pFuncAfterThread); 716 return 0; 717 } 718 // clang-format on 719 SplitCommandToArgs(const char * cmdStringLine,int * slotIndex)720 char **SplitCommandToArgs(const char *cmdStringLine, int *slotIndex) 721 { 722 constexpr int extraBufSize = 2; 723 char **argv; 724 char *temp = nullptr; 725 int argc = 0; 726 char a = 0; 727 size_t i = 0; 728 size_t j = 0; 729 size_t len = 0; 730 bool isQuoted = false; 731 bool isText = false; 732 bool isSpace = false; 733 734 len = strlen(cmdStringLine); 735 if (len < 1) { 736 return nullptr; 737 } 738 i = ((len + extraBufSize) / extraBufSize) * sizeof(void *) + sizeof(void *); 739 argv = reinterpret_cast<char **>(new(std::nothrow) char[i + (len + extraBufSize) * sizeof(char)]); 740 if (argv == nullptr) { 741 WRITE_LOG(LOG_FATAL, "SplitCommandToArgs new argv failed"); 742 return nullptr; 743 } 744 temp = reinterpret_cast<char *>((reinterpret_cast<uint8_t *>(argv)) + i); 745 argc = 0; 746 argv[argc] = temp; 747 isQuoted = false; 748 isText = false; 749 isSpace = true; 750 i = 0; 751 j = 0; 752 753 while ((a = cmdStringLine[i]) != 0) { 754 if (isQuoted) { 755 if (a == '\"') { 756 isQuoted = false; 757 } else { 758 temp[j] = a; 759 ++j; 760 } 761 } else { 762 switch (a) { 763 case '\"': 764 isQuoted = true; 765 isText = true; 766 if (isSpace) { 767 argv[argc] = temp + j; 768 ++argc; 769 } 770 isSpace = false; 771 break; 772 case ' ': 773 case '\t': 774 case '\n': 775 case '\r': 776 if (isText) { 777 temp[j] = '\0'; 778 ++j; 779 } 780 isText = false; 781 isSpace = true; 782 break; 783 default: 784 isText = true; 785 if (isSpace) { 786 argv[argc] = temp + j; 787 ++argc; 788 } 789 temp[j] = a; 790 ++j; 791 isSpace = false; 792 break; 793 } 794 } 795 ++i; 796 } 797 temp[j] = '\0'; 798 argv[argc] = nullptr; 799 800 (*slotIndex) = argc; 801 return argv; 802 } 803 RunPipeComand(const char * cmdString,char * outBuf,uint16_t sizeOutBuf,bool ignoreTailLf)804 bool RunPipeComand(const char *cmdString, char *outBuf, uint16_t sizeOutBuf, bool ignoreTailLf) 805 { 806 FILE *pipeHandle = popen(cmdString, "r"); 807 if (pipeHandle == nullptr) { 808 return false; 809 } 810 int bytesRead = 0; 811 int bytesOnce = 0; 812 while (!feof(pipeHandle)) { 813 bytesOnce = fread(outBuf, 1, sizeOutBuf - bytesRead, pipeHandle); 814 if (bytesOnce <= 0) { 815 break; 816 } 817 bytesRead += bytesOnce; 818 } 819 if (bytesRead && ignoreTailLf) { 820 if (outBuf[bytesRead - 1] == '\n') { 821 outBuf[bytesRead - 1] = '\0'; 822 } 823 } 824 pclose(pipeHandle); 825 return bytesRead; 826 } 827 828 // bufLen == 0: alloc buffer in heap, need free it later 829 // >0: read max nBuffLen bytes to *buff 830 // ret value: <0 or bytes read ReadBinFile(const char * pathName,void ** buf,const size_t bufLen)831 int ReadBinFile(const char *pathName, void **buf, const size_t bufLen) 832 { 833 uint8_t *pDst = nullptr; 834 size_t byteIO = 0; 835 uv_fs_t req; 836 int ret = uv_fs_stat(nullptr, &req, pathName, nullptr); 837 if (ret < 0) { 838 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 839 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 840 uv_fs_req_cleanup(&req); 841 WRITE_LOG(LOG_FATAL, "ReadBinFile uv_fs_stat %s error %s", pathName, buffer); 842 return -1; 843 } 844 size_t nFileSize = req.statbuf.st_size; 845 size_t readMax = 0; 846 uint8_t dynamicBuf = 0; 847 ret = -3; // -3:error for ReadBinFile 848 if (bufLen == 0) { 849 dynamicBuf = 1; 850 pDst = new uint8_t[nFileSize + 1](); // tail \0 851 if (!pDst) { 852 return -1; 853 } 854 readMax = nFileSize; 855 } else { 856 if (nFileSize > bufLen) { 857 return -2; // -2:error for bufLen 858 } 859 readMax = nFileSize; 860 pDst = reinterpret_cast<uint8_t *>(buf); // The first address of the static array is the array address 861 } 862 863 string srcPath(pathName); 864 string resolvedPath = CanonicalizeSpecPath(srcPath); 865 uv_buf_t rbf = uv_buf_init((char *)pDst, readMax); 866 uv_fs_req_cleanup(&req); 867 int fd = uv_fs_open(nullptr, &req, resolvedPath.c_str(), O_RDONLY, 0, nullptr); 868 if (fd < 0) { 869 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 870 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 871 WRITE_LOG(LOG_FATAL, "ReadBinFile uv_fs_open %s error %s", resolvedPath.c_str(), buffer); 872 goto ReadFileFromPath_Finish; 873 } 874 uv_fs_req_cleanup(&req); 875 byteIO = uv_fs_read(nullptr, &req, fd, &rbf, 1, 0, nullptr); 876 uv_fs_close(nullptr, nullptr, fd, nullptr); 877 if (byteIO != readMax) { 878 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 879 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 880 WRITE_LOG(LOG_FATAL, "ReadBinFile uv_fs_read %s error %s byteIO:%llu readMax:%llu", 881 resolvedPath.c_str(), buffer, byteIO, readMax); 882 goto ReadFileFromPath_Finish; 883 } 884 ret = 0; 885 ReadFileFromPath_Finish: 886 if (ret) { 887 if (dynamicBuf) { 888 delete[] pDst; 889 } 890 } else { 891 if (dynamicBuf) { 892 *buf = pDst; 893 } 894 ret = byteIO; 895 } 896 return ret; 897 } 898 WriteBinFile(const char * pathName,const uint8_t * buf,const size_t bufLen,bool newFile)899 int WriteBinFile(const char *pathName, const uint8_t *buf, const size_t bufLen, bool newFile) 900 { 901 string resolvedPath; 902 string srcPath(pathName); 903 int flags = 0; 904 if (newFile) { 905 flags = UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_TRUNC; 906 // no std::fs supoort, else std::filesystem::canonical,-lstdc++fs 907 if (srcPath.find("..") != string::npos) { 908 return ERR_FILE_PATH_CHECK; 909 } 910 resolvedPath = srcPath.c_str(); 911 } else { 912 flags = UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_APPEND; 913 resolvedPath = CanonicalizeSpecPath(srcPath); 914 } 915 uv_fs_t req; 916 int fd = uv_fs_open(nullptr, &req, resolvedPath.c_str(), flags, S_IWUSR | S_IRUSR, nullptr); 917 if (fd < 0) { 918 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 919 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 920 uv_fs_req_cleanup(&req); 921 WRITE_LOG(LOG_FATAL, "WriteBinFile uv_fs_open %s error %s", resolvedPath.c_str(), buffer); 922 return ERR_FILE_OPEN; 923 } 924 uv_buf_t wbf = uv_buf_init((char *)buf, bufLen); 925 uv_fs_req_cleanup(&req); 926 size_t bytesDone = uv_fs_write(nullptr, &req, fd, &wbf, 1, 0, nullptr); 927 uv_fs_close(nullptr, &req, fd, nullptr); 928 if (bytesDone != bufLen) { 929 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 930 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 931 uv_fs_req_cleanup(&req); 932 WRITE_LOG(LOG_FATAL, "WriteBinFile uv_fs_write %s error %s bytesDone:%llu bufLen:%llu", 933 resolvedPath.c_str(), buffer, bytesDone, bufLen); 934 return ERR_BUF_SIZE; 935 } 936 return RET_SUCCESS; 937 } 938 CloseIdleCallback(uv_handle_t * handle)939 void CloseIdleCallback(uv_handle_t *handle) 940 { 941 delete (uv_idle_t *)handle; 942 }; 943 CloseTimerCallback(uv_handle_t * handle)944 void CloseTimerCallback(uv_handle_t *handle) 945 { 946 delete (uv_timer_t *)handle; 947 }; 948 949 // return value: <0 error; 0 can start new server instance; >0 server already exists ProgramMutex(const char * procname,bool checkOrNew)950 int ProgramMutex(const char *procname, bool checkOrNew) 951 { 952 char bufPath[BUF_SIZE_DEFAULT] = ""; 953 char buf[BUF_SIZE_DEFAULT] = ""; 954 char pidBuf[BUF_SIZE_TINY] = ""; 955 size_t size = sizeof(buf); 956 if (uv_os_tmpdir(buf, &size) < 0) { 957 WRITE_LOG(LOG_FATAL, "Tmppath failed"); 958 return ERR_API_FAIL; 959 } 960 if (snprintf_s(bufPath, sizeof(bufPath), sizeof(bufPath) - 1, "%s%c.%s.pid", buf, Base::GetPathSep(), procname) 961 < 0) { 962 return ERR_BUF_OVERFLOW; 963 } 964 int pid = static_cast<int>(getpid()); 965 if (snprintf_s(pidBuf, sizeof(pidBuf), sizeof(pidBuf) - 1, "%d", pid) < 0) { 966 return ERR_BUF_OVERFLOW; 967 } 968 // no need to CanonicalizeSpecPath, else not work 969 umask(0); 970 uv_fs_t req; 971 int fd = uv_fs_open(nullptr, &req, bufPath, O_RDWR | O_CREAT, 0666, nullptr); // 0666:permission 972 if (fd < 0) { 973 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 974 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 975 uv_fs_req_cleanup(&req); 976 WRITE_LOG(LOG_FATAL, "Open mutex file %s failed!!! %s", bufPath, buffer); 977 return ERR_FILE_OPEN; 978 } 979 #ifdef _WIN32 980 if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "Global\\%s", procname) < 0) { 981 uv_fs_close(nullptr, &req, fd, nullptr); 982 return ERR_BUF_OVERFLOW; 983 } 984 HANDLE hMutex = CreateMutex(nullptr, FALSE, buf); 985 DWORD dwError = GetLastError(); 986 if (ERROR_ALREADY_EXISTS == dwError || ERROR_ACCESS_DENIED == dwError) { 987 uv_fs_close(nullptr, &req, fd, nullptr); 988 WRITE_LOG(LOG_DEBUG, "File \"%s\" locked. proc already exit!!!\n", procname); 989 return 1; 990 } 991 if (checkOrNew) { 992 CloseHandle(hMutex); 993 } 994 #else 995 struct flock fl; 996 fl.l_type = F_WRLCK; 997 fl.l_start = 0; 998 fl.l_whence = SEEK_SET; 999 fl.l_len = 0; 1000 int retChild = fcntl(fd, F_SETLK, &fl); 1001 if (retChild == -1) { 1002 WRITE_LOG(LOG_DEBUG, "File \"%s\" locked. proc already exit!!!\n", bufPath); 1003 uv_fs_close(nullptr, &req, fd, nullptr); 1004 return 1; 1005 } 1006 #endif 1007 int rc = 0; 1008 uv_fs_req_cleanup(&req); 1009 rc = uv_fs_ftruncate(nullptr, &req, fd, 0, nullptr); 1010 if (rc == -1) { 1011 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1012 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1013 uv_fs_close(nullptr, &req, fd, nullptr); 1014 WRITE_LOG(LOG_FATAL, "ftruncate file %s failed!!! %s", bufPath, buffer); 1015 return ERR_FILE_STAT; 1016 } 1017 uv_buf_t wbf = uv_buf_init(pidBuf, strlen(pidBuf)); 1018 uv_fs_req_cleanup(&req); 1019 rc = uv_fs_write(nullptr, &req, fd, &wbf, 1, 0, nullptr); 1020 if (rc == -1) { 1021 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1022 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1023 uv_fs_close(nullptr, &req, fd, nullptr); 1024 WRITE_LOG(LOG_FATAL, "write file %s failed!!! %s", bufPath, buffer); 1025 return ERR_FILE_WRITE; 1026 } 1027 WRITE_LOG(LOG_DEBUG, "Write mutext to %s, pid:%s", bufPath, pidBuf); 1028 if (checkOrNew) { 1029 // close it for check only 1030 uv_fs_close(nullptr, &req, fd, nullptr); 1031 } 1032 // Do not close the file descriptor, the process will be mutext effect under no-Win32 OS 1033 return RET_SUCCESS; 1034 } 1035 SplitString(const string & origString,const string & seq,vector<string> & resultStrings)1036 void SplitString(const string &origString, const string &seq, vector<string> &resultStrings) 1037 { 1038 string::size_type p1 = 0; 1039 string::size_type p2 = origString.find(seq); 1040 1041 while (p2 != string::npos) { 1042 if (p2 == p1) { 1043 ++p1; 1044 p2 = origString.find(seq, p1); 1045 continue; 1046 } 1047 resultStrings.push_back(origString.substr(p1, p2 - p1)); 1048 p1 = p2 + seq.size(); 1049 p2 = origString.find(seq, p1); 1050 } 1051 1052 if (p1 != origString.size()) { 1053 resultStrings.push_back(origString.substr(p1)); 1054 } 1055 } 1056 GetShellPath()1057 string GetShellPath() 1058 { 1059 struct stat filecheck; 1060 string shellPath = "/bin/sh"; 1061 if (stat(shellPath.c_str(), &filecheck) < 0) { 1062 shellPath = "/system/bin/sh"; 1063 if (stat(shellPath.c_str(), &filecheck) < 0) { 1064 shellPath = "sh"; 1065 } 1066 } 1067 return shellPath; 1068 } 1069 1070 // Not supported on some platforms, Can only be achieved manually HostToNet(uint64_t val)1071 uint64_t HostToNet(uint64_t val) 1072 { 1073 if (htonl(1) == 1) { 1074 return val; 1075 } 1076 int offset = 32; 1077 return ((static_cast<uint64_t>(htonl(val))) << offset) + htonl(val >> offset); 1078 } 1079 NetToHost(uint64_t val)1080 uint64_t NetToHost(uint64_t val) 1081 { 1082 if (htonl(1) == 1) { 1083 return val; 1084 } 1085 int offset = 32; 1086 return ((static_cast<uint64_t>(ntohl(val))) << offset) + ntohl(val >> offset); 1087 } 1088 GetPathSep()1089 char GetPathSep() 1090 { 1091 #ifdef _WIN32 1092 const char sep = '\\'; 1093 #else 1094 const char sep = '/'; 1095 #endif 1096 return sep; 1097 } 1098 GetFullFilePath(string & s)1099 string GetFullFilePath(string &s) 1100 { // cannot use s.rfind(std::filesystem::path::preferred_separator 1101 // remove last sep, and update input 1102 while (s.back() == GetPathSep()) { 1103 s.pop_back(); 1104 } 1105 1106 size_t i = s.rfind(GetPathSep(), s.length()); 1107 if (i != string::npos) { 1108 return (s.substr(i + 1, s.length() - i)); 1109 } 1110 return s; 1111 } 1112 GetPathWithoutFilename(const string & s)1113 string GetPathWithoutFilename(const string &s) 1114 { 1115 size_t i = s.rfind(GetPathSep(), s.length()); 1116 if (i != string::npos) { 1117 return (s.substr(0, i + 1)); 1118 } 1119 return s; 1120 } 1121 GetHdcAbsolutePath()1122 string GetHdcAbsolutePath() 1123 { 1124 char path[BUF_SIZE_DEFAULT4] = { 0 }; 1125 size_t nPathSize = sizeof(path); 1126 int ret = uv_exepath(path, &nPathSize); 1127 if (ret < 0) { 1128 char buf[BUF_SIZE_DEFAULT] = { 0 }; 1129 uv_err_name_r(ret, buf, BUF_SIZE_DEFAULT); 1130 WRITE_LOG(LOG_WARN, "uvexepath ret:%d error:%s", ret, buf); 1131 return ""; 1132 } 1133 1134 return string(path); 1135 } 1136 CreateSocketPair(int * fds)1137 int CreateSocketPair(int *fds) 1138 { 1139 #ifndef _WIN32 1140 #ifdef HOST_MAC 1141 int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 1142 if (ret == 0) { 1143 for (auto i = 0; i < STREAM_SIZE; ++i) { 1144 if (fcntl(fds[i], F_SETFD, FD_CLOEXEC) == -1) { 1145 CloseFd(fds[0]); 1146 CloseFd(fds[1]); 1147 constexpr int bufSize = 1024; 1148 char buf[bufSize] = { 0 }; 1149 strerror_r(errno, buf, bufSize); 1150 WRITE_LOG(LOG_WARN, "fcntl failed to set FD_CLOEXEC: %s", buf); 1151 return -1; 1152 } 1153 } 1154 } 1155 return ret; 1156 #else 1157 return socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds); 1158 #endif 1159 #else 1160 struct sockaddr_in addr; 1161 socklen_t addrlen = sizeof(addr); 1162 int reuse = 1; 1163 if (fds == 0) { 1164 return -1; 1165 } 1166 int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 1167 if (listener == -1) { 1168 return -2; // -2:sockets error 1169 } 1170 Base::ZeroStruct(addr); 1171 addr.sin_family = AF_INET; 1172 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1173 addr.sin_port = 0; 1174 fds[0] = fds[1] = (int)-1; 1175 do { 1176 if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, (socklen_t)sizeof(reuse))) { 1177 break; 1178 } 1179 if (::bind(listener, (struct sockaddr *)&addr, sizeof(addr))) { 1180 break; 1181 } 1182 if (getsockname(listener, (struct sockaddr *)&addr, &addrlen)) { 1183 break; 1184 } 1185 if (listen(listener, 1)) { 1186 break; 1187 } 1188 fds[0] = socket(AF_INET, SOCK_STREAM, 0); 1189 if (fds[0] == -1) { 1190 break; 1191 } 1192 if (connect(fds[0], (struct sockaddr *)&addr, sizeof(addr)) == -1) { 1193 break; 1194 } 1195 fds[1] = accept(listener, nullptr, nullptr); 1196 if (fds[1] == -1) { 1197 break; 1198 } 1199 closesocket(listener); 1200 return 0; 1201 } while (0); 1202 1203 closesocket(listener); 1204 closesocket(fds[0]); 1205 closesocket(fds[1]); 1206 return -1; 1207 #endif 1208 } 1209 CloseSocketPair(int * fds)1210 void CloseSocketPair(int *fds) 1211 { 1212 #ifndef _WIN32 1213 CloseFd(fds[0]); 1214 CloseFd(fds[1]); 1215 #else 1216 closesocket(fds[0]); 1217 closesocket(fds[1]); 1218 #endif 1219 } 1220 StringEndsWith(string s,string sub)1221 int StringEndsWith(string s, string sub) 1222 { 1223 return s.rfind(sub) == (s.length() - sub.length()) ? 1 : 0; 1224 } 1225 GetFileType(mode_t mode)1226 const char *GetFileType(mode_t mode) 1227 { 1228 switch (mode & S_IFMT) { 1229 case S_IFDIR: 1230 return "directory"; 1231 case S_IFLNK: 1232 return "symlink"; 1233 case S_IFREG: 1234 return "regular file"; 1235 #ifndef _WIN32 1236 case S_IFBLK: 1237 return "block device"; 1238 case S_IFCHR: 1239 return "character device"; 1240 case S_IFIFO: 1241 return "FIFO/pipe"; 1242 case S_IFSOCK: 1243 return "socket"; 1244 #endif 1245 default: 1246 return "Unknown"; 1247 } 1248 } 1249 BuildErrorString(const char * localPath,const char * op,const char * err,string & str)1250 void BuildErrorString(const char *localPath, const char *op, const char *err, string &str) 1251 { 1252 // avoid to use stringstream 1253 str = op; 1254 str += " "; 1255 str += localPath; 1256 str += " failed, "; 1257 str += err; 1258 } 1259 1260 // Both absolute and relative paths support CheckDirectoryOrPath(const char * localPath,bool pathOrDir,bool readWrite,string & errStr,mode_t & fm)1261 bool CheckDirectoryOrPath(const char *localPath, bool pathOrDir, bool readWrite, string &errStr, mode_t &fm) 1262 { 1263 if (pathOrDir) { // filepath 1264 uv_fs_t req; 1265 mode_t mode; 1266 fm = mode_t(~S_IFMT); 1267 int r = uv_fs_lstat(nullptr, &req, localPath, nullptr); 1268 if (r) { 1269 constexpr int bufSize = 1024; 1270 char buf[bufSize] = { 0 }; 1271 uv_strerror_r((int)req.result, buf, bufSize); 1272 BuildErrorString(localPath, "lstat", buf, errStr); 1273 } 1274 1275 mode = req.statbuf.st_mode; 1276 uv_fs_req_cleanup(&req); 1277 1278 if ((r == 0) && (mode & S_IFDIR)) { 1279 fm = S_IFDIR; 1280 } else if ((r == 0) && (mode & S_IFREG)) { // is file 1281 uv_fs_access(nullptr, &req, localPath, readWrite ? R_OK : W_OK, nullptr); 1282 if (req.result) { 1283 const char *op = readWrite ? "access R_OK" : "access W_OK"; 1284 constexpr int bufSize = 1024; 1285 char buf[bufSize] = { 0 }; 1286 uv_strerror_r((int)req.result, buf, bufSize); 1287 BuildErrorString(localPath, op, buf, errStr); 1288 } 1289 uv_fs_req_cleanup(&req); 1290 if (req.result == 0) { 1291 return true; 1292 } 1293 } else if (r == 0) { 1294 const char *type = GetFileType(mode); 1295 errStr = "Not support "; 1296 errStr += type; 1297 errStr += ": "; 1298 errStr += localPath; 1299 } 1300 } else { // dir 1301 errStr = "Not support dir: "; 1302 errStr += localPath; 1303 } 1304 return false; 1305 } 1306 TryCreateDirectory(const string & path,string & err)1307 bool TryCreateDirectory(const string &path, string &err) 1308 { 1309 uv_fs_t req; 1310 int r = uv_fs_lstat(nullptr, &req, path.c_str(), nullptr); 1311 mode_t mode = req.statbuf.st_mode; 1312 uv_fs_req_cleanup(&req); 1313 if (r < 0) { 1314 WRITE_LOG(LOG_DEBUG, "path not exist create dir = %s", path.c_str()); 1315 r = uv_fs_mkdir(nullptr, &req, path.c_str(), DEF_FILE_PERMISSION, nullptr); 1316 uv_fs_req_cleanup(&req); 1317 if (r < 0) { 1318 constexpr int bufSize = 1024; 1319 char buf[bufSize] = { 0 }; 1320 uv_strerror_r((int)req.result, buf, bufSize); 1321 WRITE_LOG(LOG_WARN, "create dir %s failed %s", path.c_str(), buf); 1322 err = "Error create directory, path:"; 1323 err += path.c_str(); 1324 return false; 1325 } 1326 } else { 1327 if (!((mode & S_IFMT) == S_IFDIR)) { 1328 WRITE_LOG(LOG_WARN, "%s exist, not directory", path.c_str()); 1329 err = "Not a directoty, path:"; 1330 err += path.c_str(); 1331 return false; 1332 } 1333 } 1334 return true; 1335 } 1336 CheckDirectoryOrPath(const char * localPath,bool pathOrDir,bool readWrite)1337 bool CheckDirectoryOrPath(const char *localPath, bool pathOrDir, bool readWrite) 1338 { 1339 string strUnused; 1340 mode_t mode = mode_t(~S_IFMT); 1341 return CheckDirectoryOrPath(localPath, pathOrDir, readWrite, strUnused, mode); 1342 } 1343 1344 // Using openssl encryption and decryption method, high efficiency; when encrypting more than 64 bytes, 1345 // the carriage return will not be added, and the tail padding 00 is removed when decrypting 1346 // The return value is the length of the string after Base64 Base64EncodeBuf(const uint8_t * input,const int length,uint8_t * bufOut)1347 int Base64EncodeBuf(const uint8_t *input, const int length, uint8_t *bufOut) 1348 { 1349 return EVP_EncodeBlock(bufOut, input, length); 1350 } 1351 Base64Encode(const uint8_t * input,const int length)1352 vector<uint8_t> Base64Encode(const uint8_t *input, const int length) 1353 { 1354 vector<uint8_t> retVec; 1355 uint8_t *pBuf = nullptr; 1356 while (true) { 1357 if (static_cast<uint32_t>(length) > HDC_BUF_MAX_BYTES) { 1358 break; 1359 } 1360 int base64Size = length * 1.4 + 256; 1361 if (!(pBuf = new uint8_t[base64Size]())) { 1362 break; 1363 } 1364 int childRet = Base64EncodeBuf(input, length, pBuf); 1365 if (childRet <= 0) { 1366 break; 1367 } 1368 retVec.insert(retVec.begin(), pBuf, pBuf + childRet); 1369 break; 1370 } 1371 if (pBuf) { 1372 delete[] pBuf; 1373 } 1374 1375 return retVec; 1376 } 1377 CalcDecodeLength(const uint8_t * b64input)1378 inline int CalcDecodeLength(const uint8_t *b64input) 1379 { 1380 int len = strlen(reinterpret_cast<char *>(const_cast<uint8_t *>(b64input))); 1381 if (!len) { 1382 return 0; 1383 } 1384 int padding = 0; 1385 if (b64input[len - 1] == '=' && b64input[len - LAST_EQUAL_NUM] == '=') { 1386 // last two chars are = 1387 padding = 2; // 2 : last two chars 1388 } else if (b64input[len - 1] == '=') { 1389 // last char is = 1390 padding = 1; 1391 } 1392 return static_cast<int>(len * DECODE_SCALE - padding); 1393 } 1394 1395 // return -1 error; >0 decode size Base64DecodeBuf(const uint8_t * input,const int length,uint8_t * bufOut)1396 int Base64DecodeBuf(const uint8_t *input, const int length, uint8_t *bufOut) 1397 { 1398 int nRetLen = CalcDecodeLength(input); 1399 if (!nRetLen) { 1400 return 0; 1401 } 1402 1403 if (EVP_DecodeBlock(bufOut, input, length) > 0) { 1404 return nRetLen; 1405 } 1406 return 0; 1407 } 1408 Base64Decode(const uint8_t * input,const int length)1409 string Base64Decode(const uint8_t *input, const int length) 1410 { 1411 string retString; 1412 uint8_t *pBuf = nullptr; 1413 while (true) { 1414 if (static_cast<uint32_t>(length) > HDC_BUF_MAX_BYTES) { 1415 break; 1416 } 1417 // must less than length 1418 if (!(pBuf = new uint8_t[length]())) { 1419 break; 1420 } 1421 int childRet = Base64DecodeBuf(input, length, pBuf); 1422 if (childRet <= 0) { 1423 break; 1424 } 1425 retString = (reinterpret_cast<char *>(pBuf)); 1426 break; 1427 } 1428 if (pBuf) { 1429 delete[] pBuf; 1430 } 1431 return retString; 1432 } 1433 ReverseBytes(void * start,int size)1434 void ReverseBytes(void *start, int size) 1435 { 1436 uint8_t *istart = (uint8_t *)start; 1437 uint8_t *iend = istart + size; 1438 std::reverse(istart, iend); 1439 } 1440 1441 // clang-format off StringFormat(const char * const formater,...)1442 const string StringFormat(const char * const formater, ...) 1443 { 1444 va_list vaArgs; 1445 va_start(vaArgs, formater); 1446 string ret = StringFormat(formater, vaArgs); 1447 va_end(vaArgs); 1448 return ret; 1449 } 1450 StringFormat(const char * const formater,va_list & vaArgs)1451 const string StringFormat(const char * const formater, va_list &vaArgs) 1452 { 1453 std::vector<char> args(GetMaxBufSize()); 1454 const int retSize = vsnprintf_s( 1455 args.data(), GetMaxBufSize(), (args.size() >= 1) ? (args.size() - 1) : 0, formater, vaArgs); 1456 if (retSize < 0) { 1457 return std::string(""); 1458 } else { 1459 return std::string(args.data(), retSize); 1460 } 1461 } 1462 // clang-format on 1463 GetVersion()1464 string GetVersion() 1465 { 1466 const uint8_t a = 'a'; 1467 uint8_t major = (HDC_VERSION_NUMBER >> 28) & 0xff; 1468 uint8_t minor = (HDC_VERSION_NUMBER << 4 >> 24) & 0xff; 1469 uint8_t version = (HDC_VERSION_NUMBER << 12 >> 24) & 0xff; 1470 uint8_t fix = (HDC_VERSION_NUMBER << 20 >> 28) & 0xff; // max 16, tail is p 1471 string ver = StringFormat("%x.%x.%x%c", major, minor, version, a + fix); 1472 return "Ver: " + ver; 1473 } 1474 IdleUvTask(uv_loop_t * loop,void * data,uv_idle_cb cb)1475 bool IdleUvTask(uv_loop_t *loop, void *data, uv_idle_cb cb) 1476 { 1477 uv_idle_t *idle = new(std::nothrow) uv_idle_t(); 1478 if (idle == nullptr) { 1479 return false; 1480 } 1481 idle->data = data; 1482 uv_idle_init(loop, idle); 1483 uv_idle_start(idle, cb); 1484 // delete by callback 1485 return true; 1486 } 1487 TimerUvTask(uv_loop_t * loop,void * data,uv_timer_cb cb,int repeatTimeout)1488 bool TimerUvTask(uv_loop_t *loop, void *data, uv_timer_cb cb, int repeatTimeout) 1489 { 1490 uv_timer_t *timer = new(std::nothrow) uv_timer_t(); 1491 if (timer == nullptr) { 1492 return false; 1493 } 1494 timer->data = data; 1495 uv_timer_init(loop, timer); 1496 uv_timer_start(timer, cb, 0, repeatTimeout); 1497 // delete by callback 1498 return true; 1499 } 1500 1501 // callback, uint8_t flag, string msg, const void * data DelayDo(uv_loop_t * loop,const int delayMs,const uint8_t flag,string msg,void * data,std::function<void (const uint8_t,string &,const void *)> cb)1502 bool DelayDo(uv_loop_t *loop, const int delayMs, const uint8_t flag, string msg, void *data, 1503 std::function<void(const uint8_t, string &, const void *)> cb) 1504 { 1505 struct DelayDoParam { 1506 uv_timer_t handle; 1507 uint8_t flag; 1508 string msg; 1509 void *data; 1510 std::function<void(const uint8_t, string &, const void *)> cb; 1511 }; 1512 auto funcDelayDo = [](uv_timer_t *handle) -> void { 1513 DelayDoParam *st = (DelayDoParam *)handle->data; 1514 st->cb(st->flag, st->msg, st->data); 1515 uv_close((uv_handle_t *)handle, [](uv_handle_t *handle) { 1516 DelayDoParam *st = (DelayDoParam *)handle->data; 1517 delete st; 1518 }); 1519 }; 1520 DelayDoParam *st = new(std::nothrow) DelayDoParam(); 1521 if (st == nullptr) { 1522 return false; 1523 } 1524 st->cb = cb; 1525 st->flag = flag; 1526 st->msg = msg; 1527 st->data = data; 1528 st->handle.data = st; 1529 uv_timer_init(loop, &st->handle); 1530 uv_timer_start(&st->handle, funcDelayDo, delayMs, 0); 1531 return true; 1532 } 1533 ReplaceAll(string str,const string from,const string to)1534 string ReplaceAll(string str, const string from, const string to) 1535 { 1536 string::size_type startPos = 0; 1537 while ((startPos = str.find(from, startPos)) != string::npos) { 1538 str.replace(startPos, from.length(), to); 1539 startPos += to.length(); // Handles case where 'to' is a substring of 'from' 1540 } 1541 return str; 1542 } 1543 CanonicalizeSpecPath(string & src)1544 string CanonicalizeSpecPath(string &src) 1545 { 1546 char resolvedPath[PATH_MAX] = { 0 }; 1547 #if defined(_WIN32) 1548 if (!_fullpath(resolvedPath, src.c_str(), PATH_MAX)) { 1549 WRITE_LOG(LOG_FATAL, "_fullpath %s failed", src.c_str()); 1550 return ""; 1551 } 1552 #else 1553 if (realpath(src.c_str(), resolvedPath) == nullptr) { 1554 WRITE_LOG(LOG_FATAL, "realpath %s failed", src.c_str()); 1555 return ""; 1556 } 1557 #endif 1558 string res(resolvedPath); 1559 return res; 1560 } 1561 UnicodeToUtf8(const char * src,bool reverse)1562 string UnicodeToUtf8(const char *src, bool reverse) 1563 { 1564 #if defined(_WIN32) 1565 UINT from = CP_ACP; 1566 UINT to = CP_UTF8; 1567 int count = 0; 1568 if (reverse) { 1569 from = CP_UTF8; 1570 to = CP_ACP; 1571 } 1572 count = MultiByteToWideChar(from, 0, src, -1, nullptr, 0); 1573 if (count <= 0) { 1574 DWORD err = GetLastError(); 1575 WRITE_LOG(LOG_FATAL, "MultiByteToWideChar failed %s error:%lu", src, err); 1576 return ""; 1577 } 1578 wchar_t *wstr = new(std::nothrow) wchar_t[count + 1](); 1579 if (wstr == nullptr) { 1580 WRITE_LOG(LOG_FATAL, "new wstr failed count:%d", count); 1581 return ""; 1582 } 1583 count = MultiByteToWideChar(from, 0, src, -1, wstr, count); 1584 if (count <= 0) { 1585 DWORD err = GetLastError(); 1586 WRITE_LOG(LOG_FATAL, "MultiByteToWideChar failed to wstr %s error:%lu", src, err); 1587 delete[] wstr; 1588 return ""; 1589 } 1590 count = WideCharToMultiByte(to, 0, wstr, -1, nullptr, 0, nullptr, nullptr); 1591 if (count <= 0) { 1592 DWORD err = GetLastError(); 1593 WRITE_LOG(LOG_FATAL, "WideCharToMultiByte failed %s error:%lu", wstr, err); 1594 delete[] wstr; 1595 return ""; 1596 } 1597 char *ustr = new(std::nothrow) char[count + 1](); 1598 if (ustr == nullptr) { 1599 WRITE_LOG(LOG_FATAL, "new ustr failed count:%d", count); 1600 delete[] wstr; 1601 return ""; 1602 } 1603 count = WideCharToMultiByte(to, 0, wstr, -1, ustr, count, nullptr, nullptr); 1604 if (count <= 0) { 1605 DWORD err = GetLastError(); 1606 WRITE_LOG(LOG_FATAL, "WideCharToMultiByte failed to ustr %s error:%lu", wstr, err); 1607 delete[] wstr; 1608 delete[] ustr; 1609 return ""; 1610 } 1611 string rc(ustr); 1612 delete[] wstr; 1613 delete[] ustr; 1614 return rc; 1615 #else 1616 string rc(src); 1617 return rc; 1618 #endif 1619 } 1620 CalcCheckSum(const uint8_t * data,int len)1621 uint8_t CalcCheckSum(const uint8_t *data, int len) 1622 { 1623 uint8_t ret = 0; 1624 for (int i = 0; i < len; ++i) { 1625 ret += data[i]; 1626 } 1627 return ret; 1628 } 1629 DuplicateUvSocket(uv_tcp_t * tcp)1630 uv_os_sock_t DuplicateUvSocket(uv_tcp_t *tcp) 1631 { 1632 uv_os_sock_t dupFd = -1; 1633 #ifdef _WIN32 1634 WSAPROTOCOL_INFO info; 1635 ZeroStruct(info); 1636 if (WSADuplicateSocketA(tcp->socket, GetCurrentProcessId(), &info) < 0) { 1637 return dupFd; 1638 } 1639 dupFd = WSASocketA(0, 0, 0, &info, 0, 0); 1640 #else 1641 uv_os_fd_t fdOs; 1642 if (uv_fileno((const uv_handle_t *)tcp, &fdOs) < 0) { 1643 return ERR_API_FAIL; 1644 } 1645 dupFd = dup(uv_open_osfhandle(fdOs)); 1646 #endif 1647 return dupFd; 1648 } 1649 GetCwd()1650 string GetCwd() 1651 { 1652 int value = -1; 1653 char path[PATH_MAX] = ""; 1654 size_t size = sizeof(path); 1655 string res; 1656 value = uv_cwd(path, &size); 1657 if (value < 0) { 1658 constexpr int bufSize = 1024; 1659 char buf[bufSize] = { 0 }; 1660 uv_strerror_r(value, buf, bufSize); 1661 WRITE_LOG(LOG_FATAL, "get path failed: %s", buf); 1662 return res; 1663 } 1664 size_t len = 0; 1665 len = strlen(path); 1666 if (len < 1 || len >= PATH_MAX - 1) { 1667 WRITE_LOG(LOG_FATAL, "get path failed: buffer space max"); 1668 return res; 1669 } 1670 if (path[len - 1] != Base::GetPathSep()) { 1671 path[len] = Base::GetPathSep(); 1672 } 1673 res = path; 1674 return res; 1675 } 1676 GetTmpDir()1677 string GetTmpDir() 1678 { 1679 string res; 1680 #ifdef HDC_HOST 1681 int value = -1; 1682 char path[PATH_MAX] = ""; 1683 size_t size = sizeof(path); 1684 value = uv_os_tmpdir(path, &size); 1685 if (value < 0) { 1686 constexpr int bufSize = 1024; 1687 char buf[bufSize] = { 0 }; 1688 uv_strerror_r(value, buf, bufSize); 1689 WRITE_LOG(LOG_FATAL, "get tmppath failed: %s", buf); 1690 return res; 1691 } 1692 if (strlen(path) >= PATH_MAX - 1) { 1693 WRITE_LOG(LOG_FATAL, "get tmppath failed: buffer space max"); 1694 return res; 1695 } 1696 if (path[strlen(path) - 1] != Base::GetPathSep()) { 1697 path[strlen(path)] = Base::GetPathSep(); 1698 } 1699 res = path; 1700 #else 1701 res = "/data/local/tmp/"; 1702 #endif 1703 return res; 1704 } 1705 1706 #ifndef HDC_HILOG SetLogCache(bool enable)1707 void SetLogCache(bool enable) 1708 { 1709 g_logCache = enable; 1710 } 1711 RemoveLogFile()1712 void RemoveLogFile() 1713 { 1714 if (g_logCache) { 1715 string path = GetTmpDir() + LOG_FILE_NAME; 1716 string timeStr; 1717 GetTimeString(timeStr); 1718 string bakPath = GetTmpDir() + LOG_FILE_NAME_PREFIX + timeStr + ".log"; 1719 string cachePath = GetTmpDir() + LOG_CACHE_NAME; 1720 rename(path.c_str(), bakPath.c_str()); 1721 rename(cachePath.c_str(), path.c_str()); 1722 g_logCache = false; 1723 RemoveOlderLogFiles(); 1724 } 1725 } 1726 RemoveLogCache()1727 void RemoveLogCache() 1728 { 1729 string cachePath = GetTmpDir() + LOG_CACHE_NAME; 1730 unlink(cachePath.c_str()); 1731 } 1732 #endif 1733 IsRoot()1734 bool IsRoot() 1735 { 1736 #ifdef _WIN32 1737 // reserve 1738 return true; 1739 #else 1740 if (getuid() == 0) { 1741 return true; 1742 } 1743 #endif 1744 return false; 1745 } 1746 IsAbsolutePath(string & path)1747 bool IsAbsolutePath(string &path) 1748 { 1749 bool ret = false; 1750 #ifdef _WIN32 1751 // shlwapi.h PathIsRelativeA not link in harmony project 1752 // c:\ or UNC path '\\hostname\share\file' 1753 ret = path.find(":\\") == 1 || path.find("\\\\") == 0; 1754 #else 1755 ret = path[0] == '/'; 1756 #endif 1757 return ret; 1758 } 1759 CloseFd(int & fd)1760 int CloseFd(int &fd) 1761 { 1762 int rc = 0; 1763 if (fd > 0) { 1764 rc = close(fd); 1765 if (rc < 0) { 1766 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1767 #ifdef _WIN32 1768 strerror_s(buffer, BUF_SIZE_DEFAULT, errno); 1769 #else 1770 strerror_r(errno, buffer, BUF_SIZE_DEFAULT); 1771 #endif 1772 WRITE_LOG(LOG_WARN, "close fd: %d failed errno:%d %s", fd, errno, buffer); 1773 } else { 1774 fd = -1; 1775 } 1776 } 1777 return rc; 1778 } 1779 InitProcess(void)1780 void InitProcess(void) 1781 { 1782 #ifndef _WIN32 1783 umask(0); 1784 signal(SIGPIPE, SIG_IGN); 1785 signal(SIGCHLD, SIG_IGN); 1786 signal(SIGALRM, SIG_IGN); 1787 signal(SIGTTIN, SIG_IGN); 1788 signal(SIGTTOU, SIG_IGN); 1789 #endif 1790 } 1791 DeInitProcess(void)1792 void DeInitProcess(void) 1793 { 1794 #ifndef _WIN32 1795 mode_t writePermission = 022; 1796 umask(writePermission); 1797 signal(SIGPIPE, SIG_DFL); 1798 signal(SIGCHLD, SIG_DFL); 1799 signal(SIGALRM, SIG_DFL); 1800 signal(SIGTTIN, SIG_DFL); 1801 signal(SIGTTOU, SIG_DFL); 1802 #endif 1803 } 1804 ReadFromFd(int fd,void * buf,size_t count)1805 int ReadFromFd(int fd, void *buf, size_t count) 1806 { 1807 #ifdef _WIN32 1808 DWORD bytesRead = 0; 1809 OVERLAPPED ov = {}; 1810 SOCKET s = fd; 1811 BOOL bWriteStat = ReadFile((HANDLE)s, buf, count, &bytesRead, &ov); 1812 if (bWriteStat) { 1813 return bytesRead; 1814 } else { 1815 return -1; 1816 } 1817 #else 1818 return TEMP_FAILURE_RETRY(read(fd, buf, count)); 1819 #endif 1820 } 1821 WriteToFd(int fd,const void * buf,size_t count)1822 int WriteToFd(int fd, const void *buf, size_t count) 1823 { 1824 #ifdef _WIN32 1825 DWORD bytesWrite = 0; 1826 OVERLAPPED ov = {}; 1827 SOCKET s = fd; 1828 BOOL bWriteStat = WriteFile((HANDLE)s, buf, count, &bytesWrite, &ov); 1829 if (bWriteStat) { 1830 return 1; 1831 } else { 1832 return -1; 1833 } 1834 #else 1835 return TEMP_FAILURE_RETRY(write(fd, buf, count)); 1836 #endif 1837 } 1838 TrimSubString(string & str,string substr)1839 void TrimSubString(string &str, string substr) 1840 { 1841 std::string::size_type pos = 0; 1842 while ((pos = str.find(substr, pos)) != std::string::npos) { 1843 str.erase(pos, substr.length()); 1844 } 1845 } 1846 // first 16 bytes is tag 1847 // second 16 bytes is length 1848 // flow the value TlvAppend(string & tlv,string tag,string val)1849 bool TlvAppend(string &tlv, string tag, string val) 1850 { 1851 if (tag.empty()) { 1852 return false; 1853 } 1854 unsigned int tlen = tag.length(); 1855 if (tlen < TLV_TAG_LEN) { 1856 tag.append(TLV_TAG_LEN - tlen, ' '); 1857 } 1858 tlv.append(tag); 1859 string vallen = std::to_string(val.length()); 1860 unsigned int vlen = vallen.length(); 1861 if (vlen < TLV_VAL_LEN) { 1862 vallen.append(TLV_VAL_LEN - vlen, ' '); 1863 } 1864 tlv.append(vallen); 1865 tlv.append(val); 1866 return true; 1867 } TlvToStringMap(string tlv,std::map<string,string> & tlvmap)1868 bool TlvToStringMap(string tlv, std::map<string, string> &tlvmap) 1869 { 1870 if (tlv.length() < TLV_MIN_LEN) { 1871 return false; 1872 } 1873 while (tlv.length() >= TLV_MIN_LEN) { 1874 string tag = tlv.substr(0, TLV_TAG_LEN); 1875 TrimSubString(tag, " "); 1876 tlv.erase(0, TLV_TAG_LEN); 1877 1878 string vallen = tlv.substr(0, TLV_VAL_LEN); 1879 TrimSubString(vallen, " "); 1880 int len = atoi(vallen.c_str()); 1881 if (len < 0) { 1882 return false; 1883 } 1884 tlv.erase(0, TLV_VAL_LEN); 1885 1886 if (tlv.length() < static_cast<uint32_t>(len)) { 1887 return false; 1888 } 1889 string val = tlv.substr(0, len); 1890 tlv.erase(0, len); 1891 1892 tlvmap[tag] = val; 1893 } 1894 return true; 1895 } 1896 1897 } 1898 } // namespace Hdc 1899