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 GetRandomU32()726 uint32_t GetRandomU32() 727 { 728 uint32_t ret; 729 std::random_device rd; 730 std::mt19937 gen(rd()); 731 std::uniform_int_distribution<uint32_t> dis(0, UINT32_MAX); 732 ret = dis(gen); 733 return ret; 734 } 735 GetRandom(const uint64_t min,const uint64_t max)736 uint64_t GetRandom(const uint64_t min, const uint64_t max) 737 { 738 #ifdef HARMONY_PROJECT 739 uint64_t ret; 740 uv_random(nullptr, nullptr, &ret, sizeof(ret), 0, nullptr); 741 #else 742 uint64_t ret; 743 std::random_device rd; 744 std::mt19937 gen(rd()); 745 std::uniform_int_distribution<uint64_t> dis(min, max); 746 ret = dis(gen); 747 #endif 748 return ret; 749 } 750 GetSecureRandom(void)751 uint32_t GetSecureRandom(void) 752 { 753 uint32_t result = static_cast<uint32_t>(GetRandom()); 754 #ifdef _WIN32 755 const int randomByteCount = 4; 756 HCRYPTPROV hCryptProv; 757 BYTE pbData[randomByteCount]; 758 do { 759 if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) { 760 if (GetLastError() != NTE_BAD_KEYSET) { 761 WRITE_LOG(LOG_FATAL, "CryptAcquireContext first failed %x", GetLastError()); 762 break; 763 } 764 if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { 765 WRITE_LOG(LOG_FATAL, "CryptAcquireContext second failed %x", GetLastError()); 766 break; 767 } 768 } 769 if (!CryptGenRandom(hCryptProv, randomByteCount, pbData)) { 770 WRITE_LOG(LOG_FATAL, "CryptGenRandom failed %x", GetLastError()); 771 } 772 if (hCryptProv) { 773 CryptReleaseContext(hCryptProv, 0); 774 } 775 result = *(reinterpret_cast<uint32_t*>(pbData)); 776 } while (0); 777 #else 778 std::ifstream randomFile("/dev/random", std::ios::binary); 779 do { 780 if (!randomFile.is_open()) { 781 WRITE_LOG(LOG_FATAL, "open /dev/random failed"); 782 break; 783 } 784 randomFile.read(reinterpret_cast<char*>(&result), sizeof(result)); 785 } while (0); 786 randomFile.close(); 787 #endif 788 return result; 789 } 790 GetRandomString(const uint16_t expectedLen)791 string GetRandomString(const uint16_t expectedLen) 792 { 793 srand(static_cast<unsigned int>(GetRandom())); 794 string ret = string(expectedLen, '0'); 795 std::stringstream val; 796 for (auto i = 0; i < expectedLen; ++i) { 797 val << std::hex << (rand() % BUF_SIZE_MICRO); 798 } 799 ret = val.str(); 800 return ret; 801 } 802 803 #ifndef HDC_HOST GetSecureRandomString(const uint16_t expectedLen)804 string GetSecureRandomString(const uint16_t expectedLen) 805 { 806 string ret = string(expectedLen, '0'); 807 std::ifstream randomFile("/dev/random", std::ios::binary); 808 do { 809 if (!randomFile.is_open()) { 810 WRITE_LOG(LOG_FATAL, "open /dev/random failed"); 811 break; 812 } 813 std::stringstream val; 814 unsigned char tmpByte; 815 for (auto i = 0; i < expectedLen; ++i) { 816 randomFile.read(reinterpret_cast<char*>(&tmpByte), 1); 817 val << std::hex << (tmpByte % BUF_SIZE_MICRO); 818 } 819 ret = val.str(); 820 } while (0); 821 randomFile.close(); 822 823 return ret; 824 } 825 #endif 826 GetRandomNum(const int min,const int max)827 int GetRandomNum(const int min, const int max) 828 { 829 return static_cast<int>(GetRandom(min, max)); 830 } 831 ConnectKey2IPPort(const char * connectKey,char * outIP,uint16_t * outPort,size_t outSize)832 int ConnectKey2IPPort(const char *connectKey, char *outIP, uint16_t *outPort, size_t outSize) 833 { 834 char bufString[BUF_SIZE_TINY] = ""; 835 if (strncpy_s(bufString, sizeof(bufString), connectKey, strlen(connectKey))) { 836 return ERR_BUF_COPY; 837 } 838 char *p = strrchr(bufString, ':'); 839 if (!p) { 840 return ERR_PARM_FORMAT; 841 } 842 *p = '\0'; 843 if (!strlen(bufString) || strlen(bufString) > 40) { // 40 : bigger than length of ipv6 844 return ERR_PARM_SIZE; 845 } 846 uint16_t wPort = static_cast<uint16_t>(atoi(p + 1)); 847 if (EOK != strcpy_s(outIP, outSize, bufString)) { 848 return ERR_BUF_COPY; 849 } 850 *outPort = wPort; 851 return RET_SUCCESS; 852 } 853 854 // After creating the session worker thread, execute it on the main thread FinishWorkThread(uv_work_t * req,int status)855 void FinishWorkThread(uv_work_t *req, int status) 856 { 857 // This is operated in the main thread 858 delete req; 859 } 860 861 // at the finish of pFuncAfterThread must free uv_work_t* 862 // clang-format off StartWorkThread(uv_loop_t * loop,uv_work_cb pFuncWorkThread,uv_after_work_cb pFuncAfterThread,void * pThreadData)863 int StartWorkThread(uv_loop_t *loop, uv_work_cb pFuncWorkThread, 864 uv_after_work_cb pFuncAfterThread, void *pThreadData) 865 { 866 uv_work_t *workThread = new uv_work_t(); 867 if (!workThread) { 868 return -1; 869 } 870 workThread->data = pThreadData; 871 uv_queue_work(loop, workThread, pFuncWorkThread, pFuncAfterThread); 872 return 0; 873 } 874 // clang-format on 875 SplitCommandToArgs(const char * cmdStringLine,int * slotIndex)876 char **SplitCommandToArgs(const char *cmdStringLine, int *slotIndex) 877 { 878 constexpr int extraBufSize = 2; 879 char **argv; 880 char *temp = nullptr; 881 int argc = 0; 882 char a = 0; 883 size_t i = 0; 884 size_t j = 0; 885 size_t len = 0; 886 bool isQuoted = false; 887 bool isText = false; 888 bool isSpace = false; 889 890 len = strlen(cmdStringLine); 891 if (len < 1) { 892 return nullptr; 893 } 894 i = ((len + extraBufSize) / extraBufSize) * sizeof(void *) + sizeof(void *); 895 argv = reinterpret_cast<char **>(new(std::nothrow) char[i + (len + extraBufSize) * sizeof(char)]); 896 if (argv == nullptr) { 897 WRITE_LOG(LOG_FATAL, "SplitCommandToArgs new argv failed"); 898 return nullptr; 899 } 900 temp = reinterpret_cast<char *>((reinterpret_cast<uint8_t *>(argv)) + i); 901 argc = 0; 902 argv[argc] = temp; 903 isQuoted = false; 904 isText = false; 905 isSpace = true; 906 i = 0; 907 j = 0; 908 909 while ((a = cmdStringLine[i]) != 0) { 910 if (isQuoted) { 911 if (a == '\"') { 912 isQuoted = false; 913 } else { 914 temp[j] = a; 915 ++j; 916 } 917 } else { 918 switch (a) { 919 case '\"': 920 isQuoted = true; 921 isText = true; 922 if (isSpace) { 923 argv[argc] = temp + j; 924 ++argc; 925 } 926 isSpace = false; 927 break; 928 case ' ': 929 case '\t': 930 case '\n': 931 case '\r': 932 if (isText) { 933 temp[j] = '\0'; 934 ++j; 935 } 936 isText = false; 937 isSpace = true; 938 break; 939 default: 940 isText = true; 941 if (isSpace) { 942 argv[argc] = temp + j; 943 ++argc; 944 } 945 temp[j] = a; 946 ++j; 947 isSpace = false; 948 break; 949 } 950 } 951 ++i; 952 } 953 temp[j] = '\0'; 954 argv[argc] = nullptr; 955 956 (*slotIndex) = argc; 957 return argv; 958 } 959 RunPipeComand(const char * cmdString,char * outBuf,uint16_t sizeOutBuf,bool ignoreTailLf)960 bool RunPipeComand(const char *cmdString, char *outBuf, uint16_t sizeOutBuf, bool ignoreTailLf) 961 { 962 FILE *pipeHandle = popen(cmdString, "r"); 963 if (pipeHandle == nullptr) { 964 return false; 965 } 966 int bytesRead = 0; 967 int bytesOnce = 0; 968 while (!feof(pipeHandle)) { 969 bytesOnce = fread(outBuf, 1, sizeOutBuf - bytesRead, pipeHandle); 970 if (bytesOnce <= 0) { 971 break; 972 } 973 bytesRead += bytesOnce; 974 } 975 if (bytesRead && ignoreTailLf) { 976 if (outBuf[bytesRead - 1] == '\n') { 977 outBuf[bytesRead - 1] = '\0'; 978 } 979 } 980 pclose(pipeHandle); 981 return bytesRead; 982 } 983 984 // bufLen == 0: alloc buffer in heap, need free it later 985 // >0: read max nBuffLen bytes to *buff 986 // ret value: <0 or bytes read ReadBinFile(const char * pathName,void ** buf,const size_t bufLen)987 int ReadBinFile(const char *pathName, void **buf, const size_t bufLen) 988 { 989 uint8_t *pDst = nullptr; 990 size_t byteIO = 0; 991 uv_fs_t req; 992 int ret = uv_fs_stat(nullptr, &req, pathName, nullptr); 993 if (ret < 0) { 994 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 995 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 996 uv_fs_req_cleanup(&req); 997 WRITE_LOG(LOG_FATAL, "ReadBinFile uv_fs_stat %s error %s", pathName, buffer); 998 return -1; 999 } 1000 size_t nFileSize = req.statbuf.st_size; 1001 size_t readMax = 0; 1002 uint8_t dynamicBuf = 0; 1003 ret = -3; // -3:error for ReadBinFile 1004 if (bufLen == 0) { 1005 dynamicBuf = 1; 1006 pDst = new uint8_t[nFileSize + 1](); // tail \0 1007 if (!pDst) { 1008 return -1; 1009 } 1010 readMax = nFileSize; 1011 } else { 1012 if (nFileSize > bufLen) { 1013 return -2; // -2:error for bufLen 1014 } 1015 readMax = nFileSize; 1016 pDst = reinterpret_cast<uint8_t *>(buf); // The first address of the static array is the array address 1017 } 1018 1019 string srcPath(pathName); 1020 string resolvedPath = CanonicalizeSpecPath(srcPath); 1021 uv_buf_t rbf = uv_buf_init((char *)pDst, readMax); 1022 uv_fs_req_cleanup(&req); 1023 int fd = uv_fs_open(nullptr, &req, resolvedPath.c_str(), O_RDONLY, 0, nullptr); 1024 if (fd < 0) { 1025 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1026 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1027 WRITE_LOG(LOG_FATAL, "ReadBinFile uv_fs_open %s error %s", resolvedPath.c_str(), buffer); 1028 goto ReadFileFromPath_Finish; 1029 } 1030 uv_fs_req_cleanup(&req); 1031 byteIO = uv_fs_read(nullptr, &req, fd, &rbf, 1, 0, nullptr); 1032 uv_fs_close(nullptr, nullptr, fd, nullptr); 1033 if (byteIO != readMax) { 1034 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1035 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1036 WRITE_LOG(LOG_FATAL, "ReadBinFile uv_fs_read %s error %s byteIO:%llu readMax:%llu", 1037 resolvedPath.c_str(), buffer, byteIO, readMax); 1038 goto ReadFileFromPath_Finish; 1039 } 1040 ret = 0; 1041 ReadFileFromPath_Finish: 1042 if (ret) { 1043 if (dynamicBuf) { 1044 delete[] pDst; 1045 } 1046 } else { 1047 if (dynamicBuf) { 1048 *buf = pDst; 1049 } 1050 ret = byteIO; 1051 } 1052 return ret; 1053 } 1054 WriteBinFile(const char * pathName,const uint8_t * buf,const size_t bufLen,bool newFile)1055 int WriteBinFile(const char *pathName, const uint8_t *buf, const size_t bufLen, bool newFile) 1056 { 1057 string resolvedPath; 1058 string srcPath(pathName); 1059 int flags = 0; 1060 if (newFile) { 1061 flags = UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_TRUNC; 1062 // no std::fs supoort, else std::filesystem::canonical,-lstdc++fs 1063 if (srcPath.find("..") != string::npos) { 1064 return ERR_FILE_PATH_CHECK; 1065 } 1066 resolvedPath = srcPath.c_str(); 1067 } else { 1068 flags = UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_APPEND; 1069 resolvedPath = CanonicalizeSpecPath(srcPath); 1070 } 1071 uv_fs_t req; 1072 int fd = uv_fs_open(nullptr, &req, resolvedPath.c_str(), flags, S_IWUSR | S_IRUSR, nullptr); 1073 if (fd < 0) { 1074 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1075 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1076 uv_fs_req_cleanup(&req); 1077 WRITE_LOG(LOG_FATAL, "WriteBinFile uv_fs_open %s error %s", resolvedPath.c_str(), buffer); 1078 return ERR_FILE_OPEN; 1079 } 1080 uv_buf_t wbf = uv_buf_init((char *)buf, bufLen); 1081 uv_fs_req_cleanup(&req); 1082 size_t bytesDone = uv_fs_write(nullptr, &req, fd, &wbf, 1, 0, nullptr); 1083 uv_fs_close(nullptr, &req, fd, nullptr); 1084 if (bytesDone != bufLen) { 1085 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1086 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1087 uv_fs_req_cleanup(&req); 1088 WRITE_LOG(LOG_FATAL, "WriteBinFile uv_fs_write %s error %s bytesDone:%llu bufLen:%llu", 1089 resolvedPath.c_str(), buffer, bytesDone, bufLen); 1090 return ERR_BUF_SIZE; 1091 } 1092 return RET_SUCCESS; 1093 } 1094 CloseIdleCallback(uv_handle_t * handle)1095 void CloseIdleCallback(uv_handle_t *handle) 1096 { 1097 delete (uv_idle_t *)handle; 1098 }; 1099 CloseTimerCallback(uv_handle_t * handle)1100 void CloseTimerCallback(uv_handle_t *handle) 1101 { 1102 delete (uv_timer_t *)handle; 1103 }; 1104 1105 // return value: <0 error; 0 can start new server instance; >0 server already exists ProgramMutex(const char * procname,bool checkOrNew)1106 int ProgramMutex(const char *procname, bool checkOrNew) 1107 { 1108 char bufPath[BUF_SIZE_DEFAULT] = ""; 1109 char buf[BUF_SIZE_DEFAULT] = ""; 1110 char pidBuf[BUF_SIZE_TINY] = ""; 1111 size_t size = sizeof(buf); 1112 if (uv_os_tmpdir(buf, &size) < 0) { 1113 WRITE_LOG(LOG_FATAL, "Tmppath failed"); 1114 return ERR_API_FAIL; 1115 } 1116 if (snprintf_s(bufPath, sizeof(bufPath), sizeof(bufPath) - 1, "%s%c.%s.pid", buf, Base::GetPathSep(), procname) 1117 < 0) { 1118 return ERR_BUF_OVERFLOW; 1119 } 1120 int pid = static_cast<int>(getpid()); 1121 if (snprintf_s(pidBuf, sizeof(pidBuf), sizeof(pidBuf) - 1, "%d", pid) < 0) { 1122 return ERR_BUF_OVERFLOW; 1123 } 1124 // no need to CanonicalizeSpecPath, else not work 1125 umask(0); 1126 uv_fs_t req; 1127 int fd = uv_fs_open(nullptr, &req, bufPath, O_RDWR | O_CREAT, 0666, nullptr); // 0666:permission 1128 if (fd < 0) { 1129 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1130 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1131 uv_fs_req_cleanup(&req); 1132 WRITE_LOG(LOG_DEBUG, "Open mutex file %s failed!!! %s", bufPath, buffer); 1133 return ERR_FILE_OPEN; 1134 } 1135 #ifdef _WIN32 1136 if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "Global\\%s", procname) < 0) { 1137 uv_fs_close(nullptr, &req, fd, nullptr); 1138 return ERR_BUF_OVERFLOW; 1139 } 1140 if (checkOrNew) { 1141 // CheckOrNew is true means to confirm whether the service is running 1142 uv_fs_close(nullptr, &req, fd, nullptr); 1143 HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, buf); 1144 if (hMutex != nullptr) { 1145 CloseHandle(hMutex); 1146 WRITE_LOG(LOG_DEBUG, "Mutex \"%s\" locked. Server already exist.", procname); 1147 return 1; 1148 } else { 1149 WRITE_LOG(LOG_DEBUG, "Server is not exist"); 1150 return 0; 1151 } 1152 } else { 1153 HANDLE hMutex = CreateMutex(nullptr, TRUE, buf); 1154 DWORD dwError = GetLastError(); 1155 if (ERROR_ALREADY_EXISTS == dwError || ERROR_ACCESS_DENIED == dwError) { 1156 uv_fs_close(nullptr, &req, fd, nullptr); 1157 WRITE_LOG(LOG_DEBUG, "Creat mutex, \"%s\" locked. proc already exit!!!\n", procname); 1158 return 1; 1159 } 1160 } 1161 #else 1162 struct flock fl; 1163 fl.l_type = F_WRLCK; 1164 fl.l_start = 0; 1165 fl.l_whence = SEEK_SET; 1166 fl.l_len = 0; 1167 int retChild = fcntl(fd, F_SETLK, &fl); 1168 if (retChild == -1) { 1169 WRITE_LOG(LOG_DEBUG, "File \"%s\" locked. proc already exit!!!\n", bufPath); 1170 uv_fs_close(nullptr, &req, fd, nullptr); 1171 return 1; 1172 } 1173 #endif 1174 int rc = 0; 1175 uv_fs_req_cleanup(&req); 1176 rc = uv_fs_ftruncate(nullptr, &req, fd, 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, "ftruncate file %s failed!!! %s", bufPath, buffer); 1182 return ERR_FILE_STAT; 1183 } 1184 uv_buf_t wbf = uv_buf_init(pidBuf, strlen(pidBuf)); 1185 uv_fs_req_cleanup(&req); 1186 rc = uv_fs_write(nullptr, &req, fd, &wbf, 1, 0, nullptr); 1187 if (rc == -1) { 1188 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1189 uv_strerror_r((int)req.result, buffer, BUF_SIZE_DEFAULT); 1190 uv_fs_close(nullptr, &req, fd, nullptr); 1191 WRITE_LOG(LOG_FATAL, "write file %s failed!!! %s", bufPath, buffer); 1192 return ERR_FILE_WRITE; 1193 } 1194 WRITE_LOG(LOG_DEBUG, "Write mutext to %s, pid:%s", bufPath, pidBuf); 1195 if (checkOrNew) { 1196 // close it for check only 1197 uv_fs_close(nullptr, &req, fd, nullptr); 1198 } 1199 // Do not close the file descriptor, the process will be mutext effect under no-Win32 OS 1200 return RET_SUCCESS; 1201 } 1202 SplitString(const string & origString,const string & seq,vector<string> & resultStrings)1203 void SplitString(const string &origString, const string &seq, vector<string> &resultStrings) 1204 { 1205 string::size_type p1 = 0; 1206 string::size_type p2 = origString.find(seq); 1207 1208 while (p2 != string::npos) { 1209 if (p2 == p1) { 1210 ++p1; 1211 p2 = origString.find(seq, p1); 1212 continue; 1213 } 1214 resultStrings.push_back(origString.substr(p1, p2 - p1)); 1215 p1 = p2 + seq.size(); 1216 p2 = origString.find(seq, p1); 1217 } 1218 1219 if (p1 != origString.size()) { 1220 resultStrings.push_back(origString.substr(p1)); 1221 } 1222 } 1223 GetShellPath()1224 string GetShellPath() 1225 { 1226 struct stat filecheck; 1227 string shellPath = "/bin/sh"; 1228 if (stat(shellPath.c_str(), &filecheck) < 0) { 1229 shellPath = "/system/bin/sh"; 1230 if (stat(shellPath.c_str(), &filecheck) < 0) { 1231 shellPath = "sh"; 1232 } 1233 } 1234 return shellPath; 1235 } 1236 1237 // Not supported on some platforms, Can only be achieved manually HostToNet(uint64_t val)1238 uint64_t HostToNet(uint64_t val) 1239 { 1240 if (htonl(1) == 1) { 1241 return val; 1242 } 1243 int offset = 32; 1244 return ((static_cast<uint64_t>(htonl(val))) << offset) + htonl(val >> offset); 1245 } 1246 NetToHost(uint64_t val)1247 uint64_t NetToHost(uint64_t val) 1248 { 1249 if (htonl(1) == 1) { 1250 return val; 1251 } 1252 int offset = 32; 1253 return ((static_cast<uint64_t>(ntohl(val))) << offset) + ntohl(val >> offset); 1254 } 1255 GetPathSep()1256 char GetPathSep() 1257 { 1258 #ifdef _WIN32 1259 const char sep = '\\'; 1260 #else 1261 const char sep = '/'; 1262 #endif 1263 return sep; 1264 } 1265 GetFullFilePath(string & s)1266 string GetFullFilePath(string &s) 1267 { // cannot use s.rfind(std::filesystem::path::preferred_separator 1268 // remove last sep, and update input 1269 while (s.back() == GetPathSep()) { 1270 s.pop_back(); 1271 } 1272 1273 size_t i = s.rfind(GetPathSep(), s.length()); 1274 if (i != string::npos) { 1275 return (s.substr(i + 1, s.length() - i)); 1276 } 1277 return s; 1278 } 1279 GetPathWithoutFilename(const string & s)1280 string GetPathWithoutFilename(const string &s) 1281 { 1282 size_t i = s.rfind(GetPathSep(), s.length()); 1283 if (i != string::npos) { 1284 return (s.substr(0, i + 1)); 1285 } 1286 return s; 1287 } 1288 GetHdcAbsolutePath()1289 string GetHdcAbsolutePath() 1290 { 1291 char path[BUF_SIZE_DEFAULT4] = { 0 }; 1292 size_t nPathSize = sizeof(path); 1293 int ret = uv_exepath(path, &nPathSize); 1294 if (ret < 0) { 1295 char buf[BUF_SIZE_DEFAULT] = { 0 }; 1296 uv_err_name_r(ret, buf, BUF_SIZE_DEFAULT); 1297 WRITE_LOG(LOG_WARN, "uvexepath ret:%d error:%s", ret, buf); 1298 return ""; 1299 } 1300 1301 return string(path); 1302 } 1303 CreateSocketPair(int * fds)1304 int CreateSocketPair(int *fds) 1305 { 1306 #ifndef _WIN32 1307 #ifdef HOST_MAC 1308 int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 1309 if (ret == 0) { 1310 for (auto i = 0; i < STREAM_SIZE; ++i) { 1311 if (fcntl(fds[i], F_SETFD, FD_CLOEXEC) == -1) { 1312 CloseFd(fds[0]); 1313 CloseFd(fds[1]); 1314 constexpr int bufSize = 1024; 1315 char buf[bufSize] = { 0 }; 1316 strerror_r(errno, buf, bufSize); 1317 WRITE_LOG(LOG_WARN, "fcntl failed to set FD_CLOEXEC: %s", buf); 1318 return -1; 1319 } 1320 } 1321 } 1322 return ret; 1323 #else 1324 return socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds); 1325 #endif 1326 #else 1327 struct sockaddr_in addr; 1328 socklen_t addrlen = sizeof(addr); 1329 int reuse = 1; 1330 if (fds == 0) { 1331 return -1; 1332 } 1333 int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 1334 if (listener == -1) { 1335 return -2; // -2:sockets error 1336 } 1337 Base::ZeroStruct(addr); 1338 addr.sin_family = AF_INET; 1339 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1340 addr.sin_port = 0; 1341 fds[0] = fds[1] = (int)-1; 1342 do { 1343 if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, (socklen_t)sizeof(reuse))) { 1344 break; 1345 } 1346 if (::bind(listener, (struct sockaddr *)&addr, sizeof(addr))) { 1347 break; 1348 } 1349 if (getsockname(listener, (struct sockaddr *)&addr, &addrlen)) { 1350 break; 1351 } 1352 if (listen(listener, 1)) { 1353 break; 1354 } 1355 fds[0] = socket(AF_INET, SOCK_STREAM, 0); 1356 if (fds[0] == -1) { 1357 break; 1358 } 1359 if (connect(fds[0], (struct sockaddr *)&addr, sizeof(addr)) == -1) { 1360 break; 1361 } 1362 fds[1] = accept(listener, nullptr, nullptr); 1363 if (fds[1] == -1) { 1364 break; 1365 } 1366 closesocket(listener); 1367 return 0; 1368 } while (0); 1369 1370 closesocket(listener); 1371 closesocket(fds[0]); 1372 closesocket(fds[1]); 1373 return -1; 1374 #endif 1375 } 1376 CloseSocketPair(int * fds)1377 void CloseSocketPair(int *fds) 1378 { 1379 #ifndef _WIN32 1380 CloseFd(fds[0]); 1381 CloseFd(fds[1]); 1382 #else 1383 closesocket(fds[0]); 1384 closesocket(fds[1]); 1385 #endif 1386 } 1387 StringEndsWith(string s,string sub)1388 int StringEndsWith(string s, string sub) 1389 { 1390 return s.rfind(sub) == (s.length() - sub.length()) ? 1 : 0; 1391 } 1392 GetFileType(mode_t mode)1393 const char *GetFileType(mode_t mode) 1394 { 1395 switch (mode & S_IFMT) { 1396 case S_IFDIR: 1397 return "directory"; 1398 case S_IFLNK: 1399 return "symlink"; 1400 case S_IFREG: 1401 return "regular file"; 1402 #ifndef _WIN32 1403 case S_IFBLK: 1404 return "block device"; 1405 case S_IFCHR: 1406 return "character device"; 1407 case S_IFIFO: 1408 return "FIFO/pipe"; 1409 case S_IFSOCK: 1410 return "socket"; 1411 #endif 1412 default: 1413 return "Unknown"; 1414 } 1415 } 1416 BuildErrorString(const char * localPath,const char * op,const char * err,string & str)1417 void BuildErrorString(const char *localPath, const char *op, const char *err, string &str) 1418 { 1419 // avoid to use stringstream 1420 str = op; 1421 str += " "; 1422 str += localPath; 1423 str += " failed, "; 1424 str += err; 1425 } 1426 1427 // Both absolute and relative paths support CheckDirectoryOrPath(const char * localPath,bool pathOrDir,bool readWrite,string & errStr,mode_t & fm)1428 bool CheckDirectoryOrPath(const char *localPath, bool pathOrDir, bool readWrite, string &errStr, mode_t &fm) 1429 { 1430 if (pathOrDir) { // filepath 1431 uv_fs_t req; 1432 mode_t mode; 1433 fm = mode_t(~S_IFMT); 1434 int r = uv_fs_lstat(nullptr, &req, localPath, nullptr); 1435 if (r) { 1436 constexpr int bufSize = 1024; 1437 char buf[bufSize] = { 0 }; 1438 uv_strerror_r((int)req.result, buf, bufSize); 1439 BuildErrorString(localPath, "lstat", buf, errStr); 1440 } 1441 1442 mode = req.statbuf.st_mode; 1443 uv_fs_req_cleanup(&req); 1444 1445 if ((r == 0) && (mode & S_IFDIR)) { 1446 fm = S_IFDIR; 1447 } else if ((r == 0) && (mode & S_IFREG)) { // is file 1448 uv_fs_access(nullptr, &req, localPath, readWrite ? R_OK : W_OK, nullptr); 1449 if (req.result) { 1450 const char *op = readWrite ? "access R_OK" : "access W_OK"; 1451 constexpr int bufSize = 1024; 1452 char buf[bufSize] = { 0 }; 1453 uv_strerror_r((int)req.result, buf, bufSize); 1454 BuildErrorString(localPath, op, buf, errStr); 1455 } 1456 uv_fs_req_cleanup(&req); 1457 if (req.result == 0) { 1458 return true; 1459 } 1460 } else if (r == 0) { 1461 const char *type = GetFileType(mode); 1462 errStr = "Not support "; 1463 errStr += type; 1464 errStr += ": "; 1465 errStr += localPath; 1466 } 1467 } else { // dir 1468 errStr = "Not support dir: "; 1469 errStr += localPath; 1470 } 1471 return false; 1472 } 1473 TryCreateDirectory(const string & path,string & err)1474 bool TryCreateDirectory(const string &path, string &err) 1475 { 1476 uv_fs_t req; 1477 int r = uv_fs_lstat(nullptr, &req, path.c_str(), nullptr); 1478 mode_t mode = req.statbuf.st_mode; 1479 uv_fs_req_cleanup(&req); 1480 if (r < 0) { 1481 WRITE_LOG(LOG_DEBUG, "path not exist create dir = %s", path.c_str()); 1482 r = uv_fs_mkdir(nullptr, &req, path.c_str(), DEF_FILE_PERMISSION, nullptr); 1483 uv_fs_req_cleanup(&req); 1484 if (r < 0) { 1485 constexpr int bufSize = 1024; 1486 char buf[bufSize] = { 0 }; 1487 uv_strerror_r((int)req.result, buf, bufSize); 1488 WRITE_LOG(LOG_WARN, "create dir %s failed %s", path.c_str(), buf); 1489 err = "Error create directory, path:"; 1490 err += path.c_str(); 1491 return false; 1492 } 1493 } else { 1494 if (!((mode & S_IFMT) == S_IFDIR)) { 1495 WRITE_LOG(LOG_WARN, "%s exist, not directory", path.c_str()); 1496 err = "File exists, path:"; 1497 err += path.c_str(); 1498 return false; 1499 } 1500 } 1501 return true; 1502 } 1503 CheckDirectoryOrPath(const char * localPath,bool pathOrDir,bool readWrite)1504 bool CheckDirectoryOrPath(const char *localPath, bool pathOrDir, bool readWrite) 1505 { 1506 string strUnused; 1507 mode_t mode = mode_t(~S_IFMT); 1508 return CheckDirectoryOrPath(localPath, pathOrDir, readWrite, strUnused, mode); 1509 } 1510 1511 // Using openssl encryption and decryption method, high efficiency; when encrypting more than 64 bytes, 1512 // the carriage return will not be added, and the tail padding 00 is removed when decrypting 1513 // The return value is the length of the string after Base64 Base64EncodeBuf(const uint8_t * input,const int length,uint8_t * bufOut)1514 int Base64EncodeBuf(const uint8_t *input, const int length, uint8_t *bufOut) 1515 { 1516 return EVP_EncodeBlock(bufOut, input, length); 1517 } 1518 Base64Encode(const uint8_t * input,const int length)1519 vector<uint8_t> Base64Encode(const uint8_t *input, const int length) 1520 { 1521 vector<uint8_t> retVec; 1522 uint8_t *pBuf = nullptr; 1523 while (true) { 1524 if (static_cast<uint32_t>(length) > HDC_BUF_MAX_BYTES) { 1525 break; 1526 } 1527 int base64Size = length * 1.4 + 256; 1528 if (!(pBuf = new uint8_t[base64Size]())) { 1529 break; 1530 } 1531 int childRet = Base64EncodeBuf(input, length, pBuf); 1532 if (childRet <= 0) { 1533 break; 1534 } 1535 retVec.insert(retVec.begin(), pBuf, pBuf + childRet); 1536 break; 1537 } 1538 if (pBuf) { 1539 delete[] pBuf; 1540 } 1541 1542 return retVec; 1543 } 1544 CalcDecodeLength(const uint8_t * b64input)1545 inline int CalcDecodeLength(const uint8_t *b64input) 1546 { 1547 int len = strlen(reinterpret_cast<char *>(const_cast<uint8_t *>(b64input))); 1548 if (!len) { 1549 return 0; 1550 } 1551 int padding = 0; 1552 if (b64input[len - 1] == '=' && b64input[len - LAST_EQUAL_NUM] == '=') { 1553 // last two chars are = 1554 padding = 2; // 2 : last two chars 1555 } else if (b64input[len - 1] == '=') { 1556 // last char is = 1557 padding = 1; 1558 } 1559 return static_cast<int>(len * DECODE_SCALE - padding); 1560 } 1561 1562 // return -1 error; >0 decode size Base64DecodeBuf(const uint8_t * input,const int length,uint8_t * bufOut)1563 int Base64DecodeBuf(const uint8_t *input, const int length, uint8_t *bufOut) 1564 { 1565 int nRetLen = CalcDecodeLength(input); 1566 if (!nRetLen) { 1567 return 0; 1568 } 1569 1570 if (EVP_DecodeBlock(bufOut, input, length) > 0) { 1571 return nRetLen; 1572 } 1573 return 0; 1574 } 1575 Base64Decode(const uint8_t * input,const int length)1576 string Base64Decode(const uint8_t *input, const int length) 1577 { 1578 string retString; 1579 uint8_t *pBuf = nullptr; 1580 while (true) { 1581 if (static_cast<uint32_t>(length) > HDC_BUF_MAX_BYTES) { 1582 break; 1583 } 1584 // must less than length 1585 if (!(pBuf = new uint8_t[length]())) { 1586 break; 1587 } 1588 int childRet = Base64DecodeBuf(input, length, pBuf); 1589 if (childRet <= 0) { 1590 break; 1591 } 1592 retString = (reinterpret_cast<char *>(pBuf)); 1593 break; 1594 } 1595 if (pBuf) { 1596 delete[] pBuf; 1597 } 1598 return retString; 1599 } 1600 ReverseBytes(void * start,int size)1601 void ReverseBytes(void *start, int size) 1602 { 1603 uint8_t *istart = (uint8_t *)start; 1604 uint8_t *iend = istart + size; 1605 std::reverse(istart, iend); 1606 } 1607 Convert2HexStr(uint8_t arr[],int length)1608 string Convert2HexStr(uint8_t arr[], int length) 1609 { 1610 std::stringstream ss; 1611 const int byteHexStrLen = 2; 1612 for (int i = 0; i < length; i++) { 1613 ss << std::hex << std::setw(byteHexStrLen) << std::setfill('0') 1614 << static_cast<int>(arr[i]); 1615 if (i < length - 1) { 1616 ss << ":"; 1617 } 1618 } 1619 string result = ss.str(); 1620 transform(result.begin(), result.end(), result.begin(), ::toupper); 1621 return result; 1622 } 1623 1624 // clang-format off StringFormat(const char * const formater,...)1625 const string StringFormat(const char * const formater, ...) 1626 { 1627 va_list vaArgs; 1628 va_start(vaArgs, formater); 1629 string ret = StringFormat(formater, vaArgs); 1630 va_end(vaArgs); 1631 return ret; 1632 } 1633 StringFormat(const char * const formater,va_list & vaArgs)1634 const string StringFormat(const char * const formater, va_list &vaArgs) 1635 { 1636 std::vector<char> args(GetMaxBufSizeStable()); 1637 const int retSize = vsnprintf_s( 1638 args.data(), GetMaxBufSizeStable(), (args.size() >= 1) ? (args.size() - 1) : 0, formater, vaArgs); 1639 if (retSize < 0) { 1640 return std::string(""); 1641 } else { 1642 return std::string(args.data(), retSize); 1643 } 1644 } 1645 // clang-format on 1646 GetVersion()1647 string GetVersion() 1648 { 1649 const uint8_t a = 'a'; 1650 uint8_t major = (HDC_VERSION_NUMBER >> 28) & 0xff; 1651 uint8_t minor = (HDC_VERSION_NUMBER << 4 >> 24) & 0xff; 1652 uint8_t version = (HDC_VERSION_NUMBER << 12 >> 24) & 0xff; 1653 uint8_t fix = (HDC_VERSION_NUMBER << 20 >> 28) & 0xff; // max 16, tail is p 1654 string ver = StringFormat("%x.%x.%x%c", major, minor, version, a + fix); 1655 return "Ver: " + ver; 1656 } 1657 IdleUvTask(uv_loop_t * loop,void * data,uv_idle_cb cb)1658 bool IdleUvTask(uv_loop_t *loop, void *data, uv_idle_cb cb) 1659 { 1660 uv_idle_t *idle = new(std::nothrow) uv_idle_t(); 1661 if (idle == nullptr) { 1662 return false; 1663 } 1664 idle->data = data; 1665 uv_idle_init(loop, idle); 1666 uv_idle_start(idle, cb); 1667 // delete by callback 1668 return true; 1669 } 1670 TimerUvTask(uv_loop_t * loop,void * data,uv_timer_cb cb,int repeatTimeout)1671 bool TimerUvTask(uv_loop_t *loop, void *data, uv_timer_cb cb, int repeatTimeout) 1672 { 1673 uv_timer_t *timer = new(std::nothrow) uv_timer_t(); 1674 if (timer == nullptr) { 1675 return false; 1676 } 1677 timer->data = data; 1678 uv_timer_init(loop, timer); 1679 uv_timer_start(timer, cb, 0, repeatTimeout); 1680 // delete by callback 1681 return true; 1682 } 1683 1684 // 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)1685 bool DelayDo(uv_loop_t *loop, const int delayMs, const uint8_t flag, string msg, void *data, 1686 std::function<void(const uint8_t, string &, const void *)> cb) 1687 { 1688 struct DelayDoParam { 1689 uv_timer_t handle; 1690 uint8_t flag; 1691 string msg; 1692 void *data; 1693 std::function<void(const uint8_t, string &, const void *)> cb; 1694 }; 1695 auto funcDelayDo = [](uv_timer_t *handle) -> void { 1696 DelayDoParam *st = (DelayDoParam *)handle->data; 1697 st->cb(st->flag, st->msg, st->data); 1698 uv_close((uv_handle_t *)handle, [](uv_handle_t *handle) { 1699 DelayDoParam *st = (DelayDoParam *)handle->data; 1700 delete st; 1701 }); 1702 }; 1703 DelayDoParam *st = new(std::nothrow) DelayDoParam(); 1704 if (st == nullptr) { 1705 return false; 1706 } 1707 st->cb = cb; 1708 st->flag = flag; 1709 st->msg = msg; 1710 st->data = data; 1711 st->handle.data = st; 1712 uv_timer_init(loop, &st->handle); 1713 uv_timer_start(&st->handle, funcDelayDo, delayMs, 0); 1714 return true; 1715 } 1716 ReplaceAll(string str,const string from,const string to)1717 string ReplaceAll(string str, const string from, const string to) 1718 { 1719 string::size_type startPos = 0; 1720 while ((startPos = str.find(from, startPos)) != string::npos) { 1721 str.replace(startPos, from.length(), to); 1722 startPos += to.length(); // Handles case where 'to' is a substring of 'from' 1723 } 1724 return str; 1725 } 1726 CanonicalizeSpecPath(string & src)1727 string CanonicalizeSpecPath(string &src) 1728 { 1729 char resolvedPath[PATH_MAX] = { 0 }; 1730 #if defined(_WIN32) 1731 if (!_fullpath(resolvedPath, src.c_str(), PATH_MAX)) { 1732 WRITE_LOG(LOG_FATAL, "_fullpath %s failed", src.c_str()); 1733 return ""; 1734 } 1735 #else 1736 if (realpath(src.c_str(), resolvedPath) == nullptr) { 1737 WRITE_LOG(LOG_FATAL, "realpath %s failed", src.c_str()); 1738 return ""; 1739 } 1740 #endif 1741 string res(resolvedPath); 1742 return res; 1743 } 1744 UnicodeToUtf8(const char * src,bool reverse)1745 string UnicodeToUtf8(const char *src, bool reverse) 1746 { 1747 #if defined(_WIN32) 1748 UINT from = CP_ACP; 1749 UINT to = CP_UTF8; 1750 int count = 0; 1751 if (reverse) { 1752 from = CP_UTF8; 1753 to = CP_ACP; 1754 } 1755 count = MultiByteToWideChar(from, 0, src, -1, nullptr, 0); 1756 if (count <= 0) { 1757 DWORD err = GetLastError(); 1758 WRITE_LOG(LOG_FATAL, "MultiByteToWideChar failed %s error:%lu", src, err); 1759 return ""; 1760 } 1761 wchar_t *wstr = new(std::nothrow) wchar_t[count + 1](); 1762 if (wstr == nullptr) { 1763 WRITE_LOG(LOG_FATAL, "new wstr failed count:%d", count); 1764 return ""; 1765 } 1766 count = MultiByteToWideChar(from, 0, src, -1, wstr, count); 1767 if (count <= 0) { 1768 DWORD err = GetLastError(); 1769 WRITE_LOG(LOG_FATAL, "MultiByteToWideChar failed to wstr %s error:%lu", src, err); 1770 delete[] wstr; 1771 return ""; 1772 } 1773 count = WideCharToMultiByte(to, 0, wstr, -1, nullptr, 0, nullptr, nullptr); 1774 if (count <= 0) { 1775 DWORD err = GetLastError(); 1776 WRITE_LOG(LOG_FATAL, "WideCharToMultiByte failed %s error:%lu", wstr, err); 1777 delete[] wstr; 1778 return ""; 1779 } 1780 char *ustr = new(std::nothrow) char[count + 1](); 1781 if (ustr == nullptr) { 1782 WRITE_LOG(LOG_FATAL, "new ustr failed count:%d", count); 1783 delete[] wstr; 1784 return ""; 1785 } 1786 count = WideCharToMultiByte(to, 0, wstr, -1, ustr, count, nullptr, nullptr); 1787 if (count <= 0) { 1788 DWORD err = GetLastError(); 1789 WRITE_LOG(LOG_FATAL, "WideCharToMultiByte failed to ustr %s error:%lu", wstr, err); 1790 delete[] wstr; 1791 delete[] ustr; 1792 return ""; 1793 } 1794 string rc(ustr); 1795 delete[] wstr; 1796 delete[] ustr; 1797 return rc; 1798 #else 1799 string rc(src); 1800 return rc; 1801 #endif 1802 } 1803 CalcCheckSum(const uint8_t * data,int len)1804 uint8_t CalcCheckSum(const uint8_t *data, int len) 1805 { 1806 uint8_t ret = 0; 1807 for (int i = 0; i < len; ++i) { 1808 ret += data[i]; 1809 } 1810 return ret; 1811 } 1812 DuplicateUvSocket(uv_tcp_t * tcp)1813 uv_os_sock_t DuplicateUvSocket(uv_tcp_t *tcp) 1814 { 1815 uv_os_sock_t dupFd = -1; 1816 #ifdef _WIN32 1817 WSAPROTOCOL_INFO info; 1818 ZeroStruct(info); 1819 if (WSADuplicateSocketA(tcp->socket, GetCurrentProcessId(), &info) < 0) { 1820 return dupFd; 1821 } 1822 dupFd = WSASocketA(0, 0, 0, &info, 0, 0); 1823 #else 1824 uv_os_fd_t fdOs; 1825 if (uv_fileno((const uv_handle_t *)tcp, &fdOs) < 0) { 1826 return ERR_API_FAIL; 1827 } 1828 #ifdef HDC_HOST 1829 dupFd = dup(uv_open_osfhandle(fdOs)); 1830 #else 1831 dupFd = fcntl(uv_open_osfhandle(fdOs), F_DUPFD_CLOEXEC, uv_open_osfhandle(fdOs)); 1832 #endif // HDC_HOST 1833 #endif 1834 return dupFd; 1835 } 1836 GetCwd()1837 string GetCwd() 1838 { 1839 int value = -1; 1840 char path[PATH_MAX] = ""; 1841 size_t size = sizeof(path); 1842 string res; 1843 value = uv_cwd(path, &size); 1844 if (value < 0) { 1845 constexpr int bufSize = 1024; 1846 char buf[bufSize] = { 0 }; 1847 uv_strerror_r(value, buf, bufSize); 1848 WRITE_LOG(LOG_FATAL, "get path failed: %s", buf); 1849 return res; 1850 } 1851 size_t len = 0; 1852 len = strlen(path); 1853 if (len < 1 || len >= PATH_MAX - 1) { 1854 WRITE_LOG(LOG_FATAL, "get path failed: buffer space max"); 1855 return res; 1856 } 1857 if (path[len - 1] != Base::GetPathSep()) { 1858 path[len] = Base::GetPathSep(); 1859 } 1860 res = path; 1861 return res; 1862 } 1863 GetTmpDir()1864 string GetTmpDir() 1865 { 1866 string res; 1867 #ifdef HDC_HOST 1868 int value = -1; 1869 char path[PATH_MAX] = ""; 1870 size_t size = sizeof(path); 1871 value = uv_os_tmpdir(path, &size); 1872 if (value < 0) { 1873 constexpr int bufSize = 1024; 1874 char buf[bufSize] = { 0 }; 1875 uv_strerror_r(value, buf, bufSize); 1876 WRITE_LOG(LOG_FATAL, "get tmppath failed: %s", buf); 1877 return res; 1878 } 1879 if (strlen(path) >= PATH_MAX - 1) { 1880 WRITE_LOG(LOG_FATAL, "get tmppath failed: buffer space max"); 1881 return res; 1882 } 1883 if (path[strlen(path) - 1] != Base::GetPathSep()) { 1884 path[strlen(path)] = Base::GetPathSep(); 1885 } 1886 res = path; 1887 #else 1888 res = "/data/local/tmp/"; 1889 #endif 1890 return res; 1891 } 1892 1893 #ifndef HDC_HILOG SetLogCache(bool enable)1894 void SetLogCache(bool enable) 1895 { 1896 g_logCache = enable; 1897 } 1898 RemoveLogFile()1899 void RemoveLogFile() 1900 { 1901 if (g_logCache) { 1902 string path = GetTmpDir() + LOG_FILE_NAME; 1903 string timeStr; 1904 GetTimeString(timeStr); 1905 string bakPath = GetTmpDir() + LOG_FILE_NAME_PREFIX + timeStr + ".log"; 1906 string cachePath = GetTmpDir() + LOG_CACHE_NAME; 1907 rename(path.c_str(), bakPath.c_str()); 1908 rename(cachePath.c_str(), path.c_str()); 1909 g_logCache = false; 1910 RemoveOlderLogFiles(); 1911 } 1912 } 1913 RemoveLogCache()1914 void RemoveLogCache() 1915 { 1916 string cachePath = GetTmpDir() + LOG_CACHE_NAME; 1917 unlink(cachePath.c_str()); 1918 } 1919 #endif 1920 IsRoot()1921 bool IsRoot() 1922 { 1923 #ifdef _WIN32 1924 // reserve 1925 return true; 1926 #else 1927 if (getuid() == 0) { 1928 return true; 1929 } 1930 #endif 1931 return false; 1932 } 1933 IsAbsolutePath(string & path)1934 bool IsAbsolutePath(string &path) 1935 { 1936 bool ret = false; 1937 #ifdef _WIN32 1938 // shlwapi.h PathIsRelativeA not link in harmony project 1939 // c:\ or UNC path '\\hostname\share\file' 1940 ret = path.find(":\\") == 1 || path.find("\\\\") == 0; 1941 #else 1942 ret = path[0] == '/'; 1943 #endif 1944 return ret; 1945 } 1946 CloseFd(int & fd)1947 int CloseFd(int &fd) 1948 { 1949 int rc = 0; 1950 if (fd > 0) { 1951 rc = close(fd); 1952 if (rc < 0) { 1953 char buffer[BUF_SIZE_DEFAULT] = { 0 }; 1954 #ifdef _WIN32 1955 strerror_s(buffer, BUF_SIZE_DEFAULT, errno); 1956 #else 1957 strerror_r(errno, buffer, BUF_SIZE_DEFAULT); 1958 #endif 1959 WRITE_LOG(LOG_WARN, "close fd: %d failed errno:%d %s", fd, errno, buffer); 1960 } else { 1961 fd = -1; 1962 } 1963 } 1964 return rc; 1965 } 1966 InitProcess(void)1967 void InitProcess(void) 1968 { 1969 #ifndef _WIN32 1970 umask(0); 1971 signal(SIGPIPE, SIG_IGN); 1972 signal(SIGCHLD, SIG_IGN); 1973 signal(SIGALRM, SIG_IGN); 1974 signal(SIGTTIN, SIG_IGN); 1975 signal(SIGTTOU, SIG_IGN); 1976 sigemptyset(&g_blockList); 1977 constexpr int crashSignal = 35; 1978 sigaddset(&g_blockList, crashSignal); 1979 sigprocmask(SIG_BLOCK, &g_blockList, NULL); 1980 #endif 1981 } 1982 DeInitProcess(void)1983 void DeInitProcess(void) 1984 { 1985 #ifndef _WIN32 1986 mode_t writePermission = 022; 1987 umask(writePermission); 1988 signal(SIGPIPE, SIG_DFL); 1989 signal(SIGCHLD, SIG_DFL); 1990 signal(SIGALRM, SIG_DFL); 1991 signal(SIGTTIN, SIG_DFL); 1992 signal(SIGTTOU, SIG_DFL); 1993 #endif 1994 } 1995 ReadFromFd(int fd,void * buf,size_t count)1996 int ReadFromFd(int fd, void *buf, size_t count) 1997 { 1998 #ifdef _WIN32 1999 DWORD bytesRead = 0; 2000 OVERLAPPED ov = {}; 2001 SOCKET s = fd; 2002 BOOL bWriteStat = ReadFile((HANDLE)s, buf, count, &bytesRead, &ov); 2003 if (bWriteStat) { 2004 return bytesRead; 2005 } else { 2006 return -1; 2007 } 2008 #else 2009 return TEMP_FAILURE_RETRY(read(fd, buf, count)); 2010 #endif 2011 } 2012 WriteToFd(int fd,const void * buf,size_t count)2013 int WriteToFd(int fd, const void *buf, size_t count) 2014 { 2015 #ifdef _WIN32 2016 DWORD bytesWrite = 0; 2017 OVERLAPPED ov = {}; 2018 SOCKET s = fd; 2019 BOOL bWriteStat = WriteFile((HANDLE)s, buf, count, &bytesWrite, &ov); 2020 if (bWriteStat) { 2021 return 1; 2022 } else { 2023 return -1; 2024 } 2025 #else 2026 return TEMP_FAILURE_RETRY(write(fd, buf, count)); 2027 #endif 2028 } 2029 2030 // Trim from both sides and paired ShellCmdTrim(string & cmd)2031 string &ShellCmdTrim(string &cmd) 2032 { 2033 const string pairedQuot("\"\""); 2034 if (cmd.empty()) { 2035 return cmd; 2036 } 2037 cmd = Trim(cmd); 2038 if (cmd.length() < pairedQuot.length()) { 2039 return cmd; 2040 } 2041 if (*cmd.begin() == '"' && cmd.back() == '"') { 2042 cmd.erase(cmd.begin()); 2043 cmd.pop_back(); 2044 } 2045 return cmd; 2046 } 2047 TrimSubString(string & str,string substr)2048 void TrimSubString(string &str, string substr) 2049 { 2050 std::string::size_type pos = 0; 2051 while ((pos = str.find(substr, pos)) != std::string::npos) { 2052 str.erase(pos, substr.length()); 2053 } 2054 } 2055 // first 16 bytes is tag 2056 // second 16 bytes is length 2057 // flow the value TlvAppend(string & tlv,string tag,string val)2058 bool TlvAppend(string &tlv, string tag, string val) 2059 { 2060 if (tag.empty()) { 2061 return false; 2062 } 2063 unsigned int tlen = tag.length(); 2064 if (tlen < TLV_TAG_LEN) { 2065 tag.append(TLV_TAG_LEN - tlen, ' '); 2066 } 2067 tlv.append(tag); 2068 string vallen = std::to_string(val.length()); 2069 unsigned int vlen = vallen.length(); 2070 if (vlen < TLV_VAL_LEN) { 2071 vallen.append(TLV_VAL_LEN - vlen, ' '); 2072 } 2073 tlv.append(vallen); 2074 tlv.append(val); 2075 return true; 2076 } TlvToStringMap(string tlv,std::map<string,string> & tlvmap)2077 bool TlvToStringMap(string tlv, std::map<string, string> &tlvmap) 2078 { 2079 if (tlv.length() < TLV_MIN_LEN) { 2080 return false; 2081 } 2082 while (tlv.length() >= TLV_MIN_LEN) { 2083 string tag = tlv.substr(0, TLV_TAG_LEN); 2084 TrimSubString(tag, " "); 2085 tlv.erase(0, TLV_TAG_LEN); 2086 2087 string vallen = tlv.substr(0, TLV_VAL_LEN); 2088 TrimSubString(vallen, " "); 2089 int len = atoi(vallen.c_str()); 2090 if (len < 0) { 2091 return false; 2092 } 2093 tlv.erase(0, TLV_VAL_LEN); 2094 2095 if (tlv.length() < static_cast<uint32_t>(len)) { 2096 return false; 2097 } 2098 string val = tlv.substr(0, len); 2099 tlv.erase(0, len); 2100 2101 tlvmap[tag] = val; 2102 } 2103 return true; 2104 } 2105 2106 // NOTE: This function relies on the caller to guarantee that 2107 // the input parameter is not null and to check the opened handle state. Fopen(const char * fileName,const char * mode)2108 FILE *Fopen(const char *fileName, const char *mode) 2109 { 2110 #ifdef _WIN32 2111 wchar_t resolvedPath[PATH_MAX + 1] = { 0 }; 2112 // windows platform open file with wide char 2113 std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; 2114 std::wstring wideFileName = converter.from_bytes(fileName); 2115 std::wstring wideMode = converter.from_bytes(mode); 2116 if (!_wfullpath(resolvedPath, wideFileName.c_str(), PATH_MAX + 1)) { 2117 WRITE_LOG(LOG_FATAL, "_wfullpath %s failed", wideFileName.c_str()); 2118 return nullptr; 2119 } 2120 return _wfopen(resolvedPath, wideMode.c_str()); 2121 #else 2122 // unix paltform open file with default char 2123 return fopen(fileName, mode); 2124 #endif 2125 } 2126 } 2127 } // namespace Hdc 2128