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