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