From 9a73cd094a43a8d04ecdd0a791b0ee016d7cd6df Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Fri, 5 Nov 2021 15:52:48 +0800 Subject: [PATCH 01/15] updater: add flashed Signed-off-by: xionglei6 --- ohos.build | 1 + services/BUILD.gn | 1 + services/diffpatch/diff/blocks_diff.cpp | 4 +- services/flashd/BUILD.gn | 2 - services/flashd/daemon/daemon_updater.cpp | 49 ++--- services/flashd/daemon/daemon_updater.h | 9 +- services/flashd/daemon/flashd_main.cpp | 6 +- services/flashd/flash_service.cpp | 69 ++++-- services/flashd/host/host_updater.cpp | 183 ++++++++++++---- services/flashd/host/host_updater.h | 30 ++- services/flashd/partition.cpp | 43 ++-- services/include/flashd/flashd.h | 12 +- services/include/updater/updater.h | 4 +- services/include/updater/updater_const.h | 2 + services/main.cpp | 31 ++- .../package/pkg_algorithm/pkg_algo_digest.cpp | 10 +- .../package/pkg_algorithm/pkg_algo_digest.h | 2 +- .../package/pkg_algorithm/pkg_algo_sign.cpp | 16 +- .../package/pkg_algorithm/pkg_algo_sign.h | 2 +- .../package/pkg_manager/pkg_managerImpl.cpp | 3 + services/package/pkg_package/pkg_lz4file.cpp | 1 - services/ui/updater_ui.cpp | 5 +- services/updater.cpp | 4 +- services/updater_main.cpp | 7 +- services/updater_utils.cpp | 33 ++- test/unittest/BUILD.gn | 21 ++ .../applypatch_test/imagepatch_unittest.h | 4 +- .../flashd_test/flash_host_unittest.cpp | 111 ++++++++-- .../flashd_test/flash_service_unittest.cpp | 198 +++++++++++++----- test/unittest/package/package_unittest.cpp | 103 +++++---- test/unittest/package/pkg_algo_unittest.cpp | 19 +- .../unittest/package/pkg_manager_unittest.cpp | 24 +-- .../unittest/package/pkg_package_unittest.cpp | 8 +- test/unittest/package/pkg_test.h | 6 +- .../test_data/src/rsa_private_key384.pem | 39 ++++ .../test_data/src/signing_cert384.crt | 26 +++ test/unittest/test_data/updater/test.img | 16 ++ test/unittest/test_data/updater/updater.zip | 4 +- test/unittest/unittest_comm.h | 19 +- .../updater_binary_unittest.cpp | 15 +- .../updater_main_unittest.cpp | 6 +- 41 files changed, 804 insertions(+), 344 deletions(-) create mode 100755 test/unittest/test_data/src/rsa_private_key384.pem create mode 100755 test/unittest/test_data/src/signing_cert384.crt create mode 100755 test/unittest/test_data/updater/test.img diff --git a/ohos.build b/ohos.build index 9ef224ed..010ef856 100644 --- a/ohos.build +++ b/ohos.build @@ -12,6 +12,7 @@ "//base/update/updater/services:updater", "//base/update/updater/services/applypatch:libapplypatch", "//base/update/updater/services/fs_manager:libfsmanager", + "//base/update/updater/services/flashd:updater_flashd", "//base/update/updater/utils:libutils", "//base/update/updater/utils:updater_reboot", "//base/update/updater/utils:write_updater", diff --git a/services/BUILD.gn b/services/BUILD.gn index a52c4d29..945f511d 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -95,6 +95,7 @@ ohos_executable("updater") { "//base/update/updater/interfaces/kits/packages:libpackageExt", "//base/update/updater/services/applypatch:libapplypatch", "//base/update/updater/services/diffpatch/patch:libpatch", + "//base/update/updater/services/flashd:libflashd", "//base/update/updater/services/fs_manager:libfsmanager", "//base/update/updater/services/log:libupdaterlog", "//base/update/updater/services/package:libupdaterpackage", diff --git a/services/diffpatch/diff/blocks_diff.cpp b/services/diffpatch/diff/blocks_diff.cpp index 2a68f28c..d579dbd9 100644 --- a/services/diffpatch/diff/blocks_diff.cpp +++ b/services/diffpatch/diff/blocks_diff.cpp @@ -237,7 +237,7 @@ void BlocksDiff::ComputeLength(const BlockBuffer &newInfo, int64_t i = 0; int64_t s = 0; int64_t tmp = 0; - for (; ((lastScan_ + i) < currentOffset_) && ((lastPos_ + i) < static_cast(oldInfo.length));) { + for (; ((lastScan_ + i) < currentOffset_) && ((lastPos_ + i) < static_cast(oldInfo.length)); ) { if (oldInfo.buffer[lastPos_ + i] == newInfo.buffer[lastScan_ + i]) { s++; } @@ -413,7 +413,7 @@ void SuffixArray::Init(const BlockBuffer &oldInfo) DataType len = 0; for (h = 1; suffixArray_[0] != -(static_cast(oldInfo.length) + 1); h += h) { len = 0; - for (i = 0; i < (static_cast(oldInfo.length) + 1);) { + for (i = 0; i < (static_cast(oldInfo.length) + 1); ) { if (suffixArray_[i] < 0) { len -= suffixArray_[i]; i -= suffixArray_[i]; diff --git a/services/flashd/BUILD.gn b/services/flashd/BUILD.gn index d484a64c..91407725 100755 --- a/services/flashd/BUILD.gn +++ b/services/flashd/BUILD.gn @@ -26,7 +26,6 @@ ohos_static_library("libflashd") { ] defines = [ - "HDC_DEBUG", "HDC_SUPPORT_FLASHD", "HARMONY_PROJECT", ] @@ -46,7 +45,6 @@ ohos_static_library("libflashd") { "//third_party/libuv:uv_static", "//third_party/lz4:liblz4_static", "//third_party/openssl:libcrypto_static", - "//third_party/openssl:ssl_source", "//third_party/zlib:libz", "//utils/native/base:utils", ] diff --git a/services/flashd/daemon/daemon_updater.cpp b/services/flashd/daemon/daemon_updater.cpp index 37dae05c..1cd520b7 100755 --- a/services/flashd/daemon/daemon_updater.cpp +++ b/services/flashd/daemon/daemon_updater.cpp @@ -29,14 +29,6 @@ DaemonUpdater::~DaemonUpdater() WRITE_LOG(LOG_DEBUG, "~DaemonUpdater refCount %d", refCount); } -bool DaemonUpdater::ReadyForRelease() -{ - if (!HdcTaskBase::ReadyForRelease()) { - return false; - } - return true; -} - bool DaemonUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) { #ifndef UPDATER_UT @@ -49,15 +41,17 @@ bool DaemonUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, co [&](uint32_t type, size_t dataLen, const void *context) { SendProgress(dataLen); }); - if (ret != 0) { - return false; - } + FLASHDAEMON_CHECK(ret == 0, AsyncUpdateFinish(command, -1, errorMsg_); + return false, "Faild to create flashd"); } switch (command) { case CMD_UPDATER_DATA: { string serialStrring((char *)payload, payloadPrefixReserve); - TransferPayload pld; + TransferPayload pld {}; SerialStruct::ParseFromString(pld, serialStrring); +#ifdef UPDATER_UT + pld.uncompressSize = pld.compressSize; +#endif SendProgress(pld.uncompressSize); break; } @@ -88,9 +82,7 @@ void DaemonUpdater::ProcessUpdateCheck(const uint8_t *payload, const int payload { uint64_t realSize = 0; int ret = memcpy_s(&realSize, sizeof(realSize), payload, sizeof(realSize)); - if (ret != 0) { - return; - } + FLASHDAEMON_CHECK(ret == 0, return, "Faild to memcpy"); string bufString((char *)payload + sizeof(realSize), payloadSize - sizeof(realSize)); SerialStruct::ParseFromString(ctxNow.transferConfig, bufString); ctxNow.master = false; @@ -117,6 +109,7 @@ void DaemonUpdater::ProcessUpdateCheck(const uint8_t *payload, const int payload } else { WRITE_LOG(LOG_FATAL, "ProcessUpdateCheck local function %s size %lu realSize %lu", ctxNow.transferConfig.functionName.c_str(), ctxNow.fileSize, realSize); + AsyncUpdateFinish(type, -1, "Invalid command"); return; } ctxNow.localPath = ctxNow.transferConfig.optionalName; @@ -124,34 +117,31 @@ void DaemonUpdater::ProcessUpdateCheck(const uint8_t *payload, const int payload if (ret == 0) { refCount++; WRITE_LOG(LOG_DEBUG, "ProcessUpdateCheck localPath %s", ctxNow.localPath.c_str()); +#ifndef UPDATER_UT uv_fs_open(loopTask, &ctxNow.fsOpenReq, ctxNow.localPath.c_str(), UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IRUSR, OnFileOpen); - } else { - AsyncUpdateFinish(type, ret, errorMsg_); +#endif } + FLASHDAEMON_CHECK(ret == 0, AsyncUpdateFinish(type, ret, errorMsg_), "Faild to prepare for %d", type); } void DaemonUpdater::RunUpdateShell(uint8_t type, const std::string &options, const std::string &package) { int ret = flashd::DoUpdaterFlash(flashHandle_, type, options, package); - if (ret != 0) { - WRITE_LOG(LOG_FATAL, errorMsg_.c_str()); - } AsyncUpdateFinish(type, ret, errorMsg_); } void DaemonUpdater::SendProgress(size_t dataLen) { currSize_ += dataLen; - int32_t percentage = (int32_t)(currSize_ * (flashd::PERCENT_FINISH - 1) / totalSize_); - if (percentage >= flashd::PERCENT_FINISH) { + int32_t percentage = static_cast(currSize_ * (flashd::PERCENT_FINISH - 1) / totalSize_); + if (static_cast(percentage) >= flashd::PERCENT_FINISH) { WRITE_LOG(LOG_DEBUG, "SendProgress %lf percentage %d", currSize_, percentage); return; } if (percentage_ < percentage) { percentage_ = percentage; WRITE_LOG(LOG_DEBUG, "SendProgress %lf percentage_ %d", currSize_, percentage_); - FLASHING_LOGI("SendProgress %lf percentage_ %d", currSize_, percentage_); SendToAnother(CMD_UPDATER_PROGRESS, (uint8_t *)&percentage, sizeof(uint32_t)); } } @@ -172,24 +162,21 @@ void DaemonUpdater::WhenTransferFinish(CtxFile *context) type = flashd::UPDATEMOD_FLASH; } AsyncUpdateFinish(type, ret, errorMsg_); - ret = flashd::DoUpdaterFinish(flashHandle_, type, ctxNow.localPath); - if (ret != 0) { - WRITE_LOG(LOG_FATAL, errorMsg_.c_str()); - } TaskFinish(); } -void DaemonUpdater::AsyncUpdateFinish(uint8_t type, int32_t ret, const string &result) +void DaemonUpdater::AsyncUpdateFinish(uint8_t type, int32_t retCode, const string &result) { - WRITE_LOG(LOG_DEBUG, "AsyncUpdateFinish ret %d result %s", ret, result.c_str()); - uint32_t percentage = (ret != 0) ? flashd::PERCENT_CLEAR : flashd::PERCENT_FINISH; + WRITE_LOG(LOG_DEBUG, "AsyncUpdateFinish retCode %d result %s", retCode, result.c_str()); + uint32_t percentage = (retCode != 0) ? flashd::PERCENT_CLEAR : flashd::PERCENT_FINISH; SendToAnother(CMD_UPDATER_PROGRESS, (uint8_t *)&percentage, sizeof(uint32_t)); + (void)flashd::DoUpdaterFinish(flashHandle_, type, ctxNow.localPath); string echo = result; echo = Base::ReplaceAll(echo, "\n", " "); vector vecBuf; vecBuf.push_back(type); - if (ret != 0) { + if (retCode != 0) { vecBuf.push_back(MSG_FAIL); } else { vecBuf.push_back(MSG_OK); diff --git a/services/flashd/daemon/daemon_updater.h b/services/flashd/daemon/daemon_updater.h index a7e35b67..6f7bb76f 100755 --- a/services/flashd/daemon/daemon_updater.h +++ b/services/flashd/daemon/daemon_updater.h @@ -20,12 +20,17 @@ #include "transfer.h" namespace Hdc { +#define FLASHDAEMON_CHECK(retCode, exper, ...) \ + if (!(retCode)) { \ + WRITE_LOG(LOG_FATAL, __VA_ARGS__); \ + exper; \ + } + class DaemonUpdater : public HdcTransferBase { public: explicit DaemonUpdater(HTaskInfo hTaskInfo); virtual ~DaemonUpdater(); bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) override; - bool ReadyForRelease(); #ifdef UPDATER_UT void DoTransferFinish(); #endif @@ -33,7 +38,7 @@ private: virtual void WhenTransferFinish(CtxFile *context) override; void ProcessUpdateCheck(const uint8_t *payload, const int payloadSize); void RunUpdateShell(uint8_t type, const std::string &options, const std::string &package); - void AsyncUpdateFinish(uint8_t type, int32_t ret, const string &result); + void AsyncUpdateFinish(uint8_t type, int32_t retCode, const string &result); void SendProgress(size_t dataLen); #ifdef UPDATER_UT bool SendToAnother(const uint16_t command, uint8_t *bufPtr, const int size) diff --git a/services/flashd/daemon/flashd_main.cpp b/services/flashd/daemon/flashd_main.cpp index 5d73fd8f..18d8ebd6 100755 --- a/services/flashd/daemon/flashd_main.cpp +++ b/services/flashd/daemon/flashd_main.cpp @@ -27,10 +27,8 @@ int flashd_main(int argc, char **argv) for (std::string arg : args) { if (arg.find("-l") != std::string::npos) { int logLevel = atoi(arg.c_str() + strlen("-l")); - if (logLevel < 0 || logLevel > LOG_LAST) { - WRITE_LOG(LOG_DEBUG, "Loglevel error!\n"); - return -1; - } + FLASHDAEMON_CHECK(!(logLevel < 0 || logLevel > LOG_LAST), + logLevel = LOG_LAST, "Loglevel error %d", logLevel); Base::SetLogLevel(logLevel); } else if (arg.find("-t") != std::string::npos) { enableTcp = true; diff --git a/services/flashd/flash_service.cpp b/services/flashd/flash_service.cpp index 1cd136b5..4b49ef7e 100755 --- a/services/flashd/flash_service.cpp +++ b/services/flashd/flash_service.cpp @@ -38,6 +38,7 @@ using namespace hpackage; using namespace updater; namespace flashd { +static std::atomic g_flashdRunning { false }; FlashService::~FlashService() { for (auto part : partitions_) { @@ -84,7 +85,12 @@ int FlashService::DoUpdate(const std::string &packageName) FLASHING_CHECK(ret == PKG_SUCCESS, PkgManager::ReleasePackageInstance(pkgManager); RecordMsg(updater::ERROR, "Can not load package %s", packageName.c_str()); return FLASHING_PACKAGE_INVALID, "Failed to load package %s", packageName.c_str()); -#ifndef LOCAL_SUPPORT + + ret = UpdatePreProcess(pkgManager, packageName); + FLASHING_CHECK(ret == PKG_SUCCESS, PkgManager::ReleasePackageInstance(pkgManager); + RecordMsg(updater::ERROR, "Invalid package %s", packageName.c_str()); + return FLASHING_PACKAGE_INVALID, "Invalid package %s", packageName.c_str()); +#ifndef UPDATER_UT ret = updater::ExecUpdate(pkgManager, 0, [&](const char *cmd, const char *content) { if (strncmp(cmd, "data", strlen(cmd)) == 0) { @@ -93,6 +99,9 @@ int FlashService::DoUpdate(const std::string &packageName) } }); #endif + FLASHING_CHECK(ret == PKG_SUCCESS, PkgManager::ReleasePackageInstance(pkgManager); + RecordMsg(updater::ERROR, "Failed to update package %s", packageName.c_str()); + return FLASHING_PACKAGE_INVALID, "Failed to update package %s", packageName.c_str()); FLASHING_LOGI("Load packageName %s success %llu", packageName.c_str(), pkgLen); PkgManager::ReleasePackageInstance(pkgManager); return ret; @@ -227,7 +236,7 @@ int FlashService::LoadBlockDevice(const std::string &fileDir) continue; } std::string devPath = fileDir + "/" + entry->d_name; - if (entry->d_type == 10) { // 10 link 文件 + if (entry->d_type == 10) { // 10 link file readlink(devPath.c_str(), buffer.data(), DEVICE_PATH_SIZE); devPath = fileDir + "/" + buffer.data(); memset_s(buffer.data(), DEVICE_PATH_SIZE, 0, DEVICE_PATH_SIZE); @@ -241,13 +250,13 @@ int FlashService::LoadBlockDevice(const std::string &fileDir) } ret = 0; if (SCSI_BLK_MAJOR(devMajor)) { - if ((devMinor % 0x10) == 0) { + if ((devMinor % 0x10) == 0) { // 0x10 scsi device ret = AddNewBlockDevice(DeviceType::DEVICE_SCSI, devPath); } else { partitionsName.push_back(devPath); } } else if (devMajor == SDMMC_MAJOR) { - if (devMinor % 0x08 == 0) { + if (devMinor % 0x08 == 0) { // 0x08 emmc ret = AddNewBlockDevice(DeviceType::DEVICE_EMMC, devPath); } else { partitionsName.push_back(devPath); @@ -343,19 +352,20 @@ int FlashService::ExecCommand(const std::vector &cmds) } extractedCmds.push_back(nullptr); pid_t pid = fork(); - if (pid < 0) { - FLASHING_CHECK(0, return -1, "Failed to fork %d error:%d", pid, errno); - return errno; - } if (pid == 0) { +#ifndef UPDATER_UT execv(extractedCmds[0], extractedCmds.data()); +#endif exit(0x7f); // 0x7f exit code } + FLASHING_CHECK(pid > 0, return -1, "Failed to fork %d error:%d", pid, errno); +#ifndef UPDATER_UT int status; waitpid(pid, &status, 0); if (WEXITSTATUS(status) != 0 || !WIFEXITED(status)) { return WEXITSTATUS(status); } +#endif return 0; } @@ -381,9 +391,7 @@ void FlashService::PostProgress(uint32_t type, size_t dataLen, const void *conte int FlashService::CheckOperationPermission(int type, const std::string &partition) const { - if (type >= UPDATEMOD_MAX) { - return 1; - } + FLASHING_CHECK(type < UPDATEMOD_MAX, return 1, "Invalid type %d", type); std::vector forbitPartName[] = { {}, // updater {"updater"}, // flash @@ -511,13 +519,19 @@ static int GetCmdParam(uint8_t type, const std::string &origString, int CreateFlashInstance(FlashHandle *handle, std::string &errorMsg, ProgressFunction progressor) { + int mode = BOOT_UPDATER; + int ret = updater::GetBootMode(mode); + FLASHING_CHECK(ret == 0 && mode == BOOT_FLASHD, errorMsg = "Boot mode is not in flashd"; + return FLASHING_SYSTEM_ERROR, "Boot mode error"); + + FLASHING_CHECK(!g_flashdRunning, errorMsg = "Flashd has been running"; + return FLASHING_SYSTEM_ERROR, "Flashd has been running"); + g_flashdRunning = true; + FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle"); flashd::FlashService *flash = new flashd::FlashService(errorMsg, progressor); - if (flash == nullptr) { - FLASHING_LOGE("Failed to create flash service"); - errorMsg = "Create instance fail"; - return FLASHING_SYSTEM_ERROR; - } + FLASHING_CHECK(flash != nullptr, errorMsg = "Failed to create flash service"; + return FLASHING_SYSTEM_ERROR, "Failed to create flash service"); *handle = static_cast(flash); return 0; } @@ -538,12 +552,12 @@ int DoUpdaterPrepare(FlashHandle handle, uint8_t type, const std::string &cmdPar // 检查剩余分区大小,扩展分区 const std::string root = flashd::FlashService::GetPathRoot(FLASHD_FILE_PATH); ret = MountForPath(root); - FLASHING_CHECK(ret == 0, + FLASHING_CHECK(ret == 0, g_flashdRunning = false; flash->RecordMsg(updater::ERROR, "Failed to mount data paratition for %s", filePath.c_str()); return FLASHING_INVALID_SPACE, "Failed to mount data paratition for %s", filePath.c_str()); ret = flash->DoResizeParatiton(root, MIN_BLOCKS_FOR_UPDATE); - FLASHING_CHECK(ret == 0, return ret, "Failed to resize partition"); + FLASHING_CHECK(ret == 0, g_flashdRunning = false; return ret, "Failed to resize partition"); if (access(FLASHD_FILE_PATH.c_str(), F_OK) == -1) { mkdir(FLASHD_FILE_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); } @@ -567,23 +581,24 @@ int DoUpdaterFlash(FlashHandle handle, uint8_t type, const std::string &cmdParam std::vector params {}; int ret = GetCmdParam(type, cmdParam, {"-f"}, params); - FLASHING_CHECK(ret == 0, + FLASHING_CHECK(ret == 0, g_flashdRunning = false; flash->RecordMsg(updater::ERROR, "Invalid param for %d", type); return FLASHING_ARG_INVALID, "Invalid param for %d", type); FLASHING_DEBUG("DoUpdaterFlash type: %d param %s filePath %s", type, cmdParam.c_str(), filePath.c_str()); switch (type) { case flashd::UPDATEMOD_UPDATE: { ret = flash->DoUpdate(filePath); - unlink(filePath.c_str()); break; } case flashd::UPDATEMOD_ERASE: - FLASHING_CHECK(params.size() > 1, return FLASHING_ARG_INVALID, "Invalid param size for erase"); + FLASHING_CHECK(params.size() > 1, g_flashdRunning = false; + return FLASHING_ARG_INVALID, "Invalid param size for erase"); ret = flash->DoErasePartition(params[1]); break; case flashd::UPDATEMOD_FORMAT: { std::string fsType = GetValueFromParam(params, "-t", "ext4"); - FLASHING_CHECK(params.size() > 1, return FLASHING_ARG_INVALID, "Invalid param size for format"); + FLASHING_CHECK(params.size() > 1, g_flashdRunning = false; + return FLASHING_ARG_INVALID, "Invalid param size for format"); ret = flash->DoFormatPartition(params[1], fsType); break; } @@ -598,15 +613,23 @@ int DoUpdaterFinish(FlashHandle handle, uint8_t type, const std::string &partiti { FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle for %d", type); FLASHING_DEBUG("DoUpdaterFinish type: %d %s", type, partition.c_str()); - updater::PostUpdater(); switch (type) { case flashd::UPDATEMOD_UPDATE: { +#ifndef UPDATER_UT + unlink(partition.c_str()); +#endif + updater::PostUpdater(true); utils::DoReboot(""); break; } + case flashd::UPDATEMOD_FLASH: { + updater::PostUpdater(false); + break; + } default: break; } + g_flashdRunning = false; return 0; } } // namespace flashd diff --git a/services/flashd/host/host_updater.cpp b/services/flashd/host/host_updater.cpp index 4de625d3..641af6ac 100755 --- a/services/flashd/host/host_updater.cpp +++ b/services/flashd/host/host_updater.cpp @@ -13,11 +13,18 @@ * limitations under the License. */ #include "host_updater.h" + +#include #include "common.h" #include "transfer.h" #include "serial_struct.h" namespace Hdc { +static const std::string helpCmd = "flash"; +static const std::string updateCmd = "update "; +static const std::string flashCmd = "flash "; +static const std::string eraseCmd = "erase "; +static const std::string formatCmd = "format "; static const int PERCENT_FINISH = 100; static const uint32_t PERCENT_CLEAR = ((uint32_t)-1); HostUpdater::HostUpdater(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo) @@ -41,24 +48,20 @@ bool HostUpdater::BeginTransfer(CtxFile &context, { int argc = 0; char **argv = Base::SplitCommandToArgs(payload, &argc); - if (argv == nullptr || argc < minParam || fileIndex >= argc) { - LogMsg(MSG_FAIL, "Invalid param for cmd \"%s\"", function.c_str()); - delete[]((char *)argv); - return false; - } + FLASHHOST_CHECK(!(argv == nullptr || argc < minParam || fileIndex >= argc), delete[]((char *)argv); + return false, "Invalid param for cmd \"%s\"", function.c_str()); + int maxParam = minParam; - if (strstr(payload, "-f") != nullptr) { + bool force = strstr(payload, "-f") != nullptr; + if (force) { maxParam += 1; } - if (argc != maxParam) { - LogMsg(MSG_FAIL, "Invalid param for cmd \"%s\"", function.c_str()); - delete[]((char *)argv); - return false; - } + FLASHHOST_CHECK(argc == maxParam, delete[]((char *)argv); + return false, "Invalid param for cmd \"%s\" %d", function.c_str(), maxParam); context.transferConfig.functionName = function; context.transferConfig.options = payload; - if (strcmp(argv[fileIndex], "-f") == 0) { + if (force && (fileIndex + 1 < argc) && strcmp(argv[fileIndex + 1], "-f") != 0) { context.localPath = argv[fileIndex + 1]; } else { context.localPath = argv[fileIndex]; @@ -66,27 +69,26 @@ bool HostUpdater::BeginTransfer(CtxFile &context, if (MatchPackageExtendName(context.localPath, ".img")) { context.transferConfig.compressType = COMPRESS_NONE; - } else if (function == CMDSTR_FLASH_PARTITION) { - context.transferConfig.compressType = COMPRESS_NONE; } else if (MatchPackageExtendName(context.localPath, ".bin")) { + const char *part = strstr(payload, "fastboot"); + FLASHHOST_CHECK(part != nullptr, delete[]((char *)argv); + return false, "Invalid image %s for cmd \"%s\"", context.localPath.c_str(), function.c_str()); context.transferConfig.compressType = COMPRESS_NONE; - } else if (!(MatchPackageExtendName(context.localPath, ".zip") || - MatchPackageExtendName(context.localPath, ".lz4") || - MatchPackageExtendName(context.localPath, ".gz2"))) { - LogMsg(MSG_FAIL, "Invaid file \"%s\" for cmd \"%s\"", context.localPath.c_str(), function.c_str()); - delete[]((char *)argv); - return false; + } else { + FLASHHOST_CHECK((MatchPackageExtendName(context.localPath, ".zip") || + MatchPackageExtendName(context.localPath, ".lz4") || + MatchPackageExtendName(context.localPath, ".gz2")), delete[]((char *)argv); + return false, + "Invaid extend name \"%s\" for cmd \"%s\"", context.localPath.c_str(), function.c_str()); } WRITE_LOG(LOG_DEBUG, "BeginTransfer function: %s localPath: %s command: %s ", context.transferConfig.functionName.c_str(), context.localPath.c_str(), payload); // check path bool ret = Base::CheckDirectoryOrPath(context.localPath.c_str(), true, true); - if (!ret) { - LogMsg(MSG_FAIL, "Invaid file \"%s\" for cmd \"%s\"", context.localPath.c_str(), function.c_str()); - delete[]((char *)argv); - return false; - } + FLASHHOST_CHECK(ret, delete[]((char *)argv); + return false, + "Invaid path \"%s\" for cmd \"%s\"", context.localPath.c_str(), function.c_str()); context.taskQueue.push_back(context.localPath); RunQueue(context); return true; @@ -95,7 +97,7 @@ bool HostUpdater::BeginTransfer(CtxFile &context, std::string HostUpdater::GetFileName(const std::string &fileName) const { int32_t pos = fileName.find_last_of('/'); - if (pos < 0) { + if (pos < 0) { // win32 pos = fileName.find_last_of('\\'); } return fileName.substr(pos + 1, fileName.size()); @@ -132,15 +134,10 @@ bool HostUpdater::CheckCmd(const std::string &function, const char *payload, int { int argc = 0; char **argv = Base::SplitCommandToArgs(payload, &argc); - if (argv == nullptr) { - LogMsg(MSG_FAIL, "Can not parser cmd \"%s\"", function.c_str()); - return false; - } + FLASHHOST_CHECK(argv != nullptr, return false, "Can not parser cmd \"%s\"", function.c_str()); delete[]((char *)argv); - if (argc < param) { - LogMsg(MSG_FAIL, "Invalid param for cmd \"%s\"", function.c_str()); - return false; - } + FLASHHOST_CHECK(argc >= param, return false, "Invalid param for cmd \"%s\" %d", function.c_str(), argc); + WRITE_LOG(LOG_DEBUG, "CheckCmd command: %s ", payload); int maxParam = param; if (strstr(payload, "-f") != nullptr) { @@ -150,10 +147,8 @@ bool HostUpdater::CheckCmd(const std::string &function, const char *payload, int maxParam += 1; maxParam += 1; } - if (argc != maxParam) { - LogMsg(MSG_FAIL, "Invalid param for cmd \"%s\"", function.c_str()); - return false; - } + FLASHHOST_CHECK(argc == maxParam, return false, + "Invalid param for cmd \"%s\" %d %d", function.c_str(), argc, maxParam); return true; } @@ -161,9 +156,11 @@ bool HostUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, cons { const int cmdFroErase = 2; const int cmdFroFormat = 2; +#ifndef UPDATER_UT if (!HdcTransferBase::CommandDispatch(command, payload, payloadSize)) { return false; } +#endif bool ret = true; switch (command) { case CMD_UPDATER_BEGIN: { @@ -226,9 +223,7 @@ void HostUpdater::ProcessProgress(uint32_t percentage) return; } int len = sprintf_s(buffer.data(), buffer.size() - 1, "%s Processing: %3d%%", backStr.c_str(), percentage); - if (len <= 0) { - return; - } + FLASHHOST_CHECK(len > 0, return, "Failed to format progress info "); SendRawData(reinterpret_cast(buffer.data()), len); if (percentage == PERCENT_FINISH) { SendRawData(reinterpret_cast(breakStr.data()), breakStr.size()); @@ -238,9 +233,8 @@ void HostUpdater::ProcessProgress(uint32_t percentage) bool HostUpdater::CheckUpdateContinue(const uint16_t command, const uint8_t *payload, int payloadSize) { - if (static_cast(payloadSize) < sizeof(uint16_t)) { - return false; - } + FLASHHOST_CHECK(static_cast(payloadSize) >= sizeof(uint16_t), + return false, "Failed to check payload size %d ", payloadSize); MessageLevel level = (MessageLevel)payload[1]; if ((level == MSG_OK) && bSendProgress) { ProcessProgress(PERCENT_FINISH); @@ -249,12 +243,109 @@ bool HostUpdater::CheckUpdateContinue(const uint16_t command, const uint8_t *pay if (!info.empty()) { LogMsg(level, "%s", info.c_str()); } - WRITE_LOG(LOG_DEBUG, "CheckUpdateContinue %d %s", level, info.c_str()); - ctxNow.taskQueue.pop_back(); + WRITE_LOG(LOG_DEBUG, "CheckUpdateContinue payloadSize %d %d %s", payloadSize, level, info.c_str()); + if (ctxNow.taskQueue.size() != 0) { + ctxNow.taskQueue.pop_back(); + } if (singalStop || !ctxNow.taskQueue.size()) { return false; } RunQueue(ctxNow); return true; } + +std::string HostUpdater::GetFlashdHelp() +{ + string help; + help = "\n---------------------------------flash commands:-------------------------------------\n" + "flash commands:\n" + " target boot [-flashd] - Reboot the device or boot into flashd\n" + " update packagename - Update system by package\n" + " flash [-f] partition imagename - Flash partition by image\n" + " erase [-f] partition - Erase partition\n" + " format [-f] partition -t fs_type - Format partition -t [ext4 | f2fs]\n"; + return help; +} + +bool HostUpdater::CheckMatchUpdate(const std::string &input, + std::string &stringError, uint16_t &cmdFlag, bool &bJumpDo) +{ + WRITE_LOG(LOG_DEBUG, "CheckMatchUpdate command:%s", input.c_str()); + if (!strcmp(input.c_str(), helpCmd.c_str())) { + cmdFlag = CMD_KERNEL_HELP; + stringError = HostUpdater::GetFlashdHelp(); + bJumpDo = true; + return true; + } + int cmdLen = updateCmd.size(); + if (!strncmp(input.c_str(), updateCmd.c_str(), updateCmd.size())) { + cmdFlag = CMD_UPDATER_UPDATE_INIT; + cmdLen = updateCmd.size(); + } else if (!strncmp(input.c_str(), flashCmd.c_str(), flashCmd.size())) { + cmdFlag = CMD_UPDATER_FLASH_INIT; + cmdLen = flashCmd.size(); + } else if (!strncmp(input.c_str(), eraseCmd.c_str(), eraseCmd.size())) { + cmdFlag = CMD_UPDATER_ERASE; + cmdLen = eraseCmd.size(); + } else if (!strncmp(input.c_str(), formatCmd.c_str(), formatCmd.size())) { + cmdFlag = CMD_UPDATER_FORMAT; + cmdLen = formatCmd.size(); + } else { + return false; + } + if (input.size() <= cmdLen) { + stringError = "Incorrect command"; + bJumpDo = true; + } + return true; +} + +bool HostUpdater::ConfirmCommand(const string &commandIn) +{ + bool needConfirm = false; + std::string tip = ""; + WRITE_LOG(LOG_DEBUG, "ConfirmCommand \"%s\" \n", commandIn.c_str()); + + if (!strncmp(commandIn.c_str(), flashCmd.c_str(), flashCmd.size())) { + tip = "Confirm flash partition"; + } else if (!strncmp(commandIn.c_str(), eraseCmd.c_str(), eraseCmd.size())) { + tip = "Confirm erase partition"; + } else if (!strncmp(commandIn.c_str(), formatCmd.c_str(), formatCmd.size())) { + tip = "Confirm format partition"; + } + if (tip.empty()) { + return true; + } + // check if -f + if (strstr(commandIn.c_str(), " -f") != nullptr) { + return true; + } + const size_t minLen = strlen("yes"); + do { + printf(" %s ? (Yes/No) ", tip.c_str()); + fflush(stdin); + std::string info = {}; + size_t i = 0; + while (1) { + char c = getchar(); + if (c == '\r' || c == '\n') { + break; + } + if (c == ' ') { + continue; + } + if (i < minLen && isprint(c)) { + info.append(1, std::tolower(c)); + i++; + } + } + if (info == "n" || info == "no") { + return false; + } + if (info == "y" || info == "yes") { + return true; + } + } while (1); + return true; +} } // namespace Hdc \ No newline at end of file diff --git a/services/flashd/host/host_updater.h b/services/flashd/host/host_updater.h index 08e5ec78..9329419a 100755 --- a/services/flashd/host/host_updater.h +++ b/services/flashd/host/host_updater.h @@ -18,12 +18,31 @@ #include "transfer.h" namespace Hdc { +#define FLASHHOST_CHECK(retCode, exper, ...) \ + if (!(retCode)) { \ + LogMsg(MSG_FAIL, __VA_ARGS__); \ + exper; \ + } +#define FLASHHOST_ONLY_CHECK(retCode, exper) \ + if (!(retCode)) { \ + exper; \ + } + class HostUpdater : public HdcTransferBase { public: explicit HostUpdater(HTaskInfo hTaskInfo); virtual ~HostUpdater(); bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) override; + static std::string GetFlashdHelp(); + static bool CheckMatchUpdate(const std::string &input, std::string &stringError, uint16_t &cmdFlag, bool &bJumpDo); + static bool ConfirmCommand(const string &commandIn); +#ifdef UPDATER_UT + void OpenFile() + { + CheckMaster(&ctxNow); + } +#endif private: void CheckMaster(CtxFile *context) override; @@ -36,20 +55,17 @@ private: #ifdef UPDATER_UT void LogMsg(MessageLevel level, const char *msg, ...) { - va_list vaArgs; - va_start(vaArgs, msg); - string log = Base::StringFormat(msg, vaArgs); - va_end(vaArgs); - WRITE_LOG(LOG_DEBUG, "LogMsg %d %s", level, log.c_str()); return; } void SendRawData(uint8_t *bufPtr, const int size) { - WRITE_LOG(LOG_DEBUG, "SendRawData %d", size); + std::string s((char *)bufPtr, size); + WRITE_LOG(LOG_DEBUG, "SendRawData %d %s", size, s.c_str()); } bool SendToAnother(const uint16_t command, uint8_t *bufPtr, const int size) { - WRITE_LOG(LOG_DEBUG, "SendToAnother command %d size %d", command, size); + std::string s((char *)bufPtr, size); + WRITE_LOG(LOG_DEBUG, "SendToAnother command %d size %d %s", command, size, s.c_str()); return true; } #endif diff --git a/services/flashd/partition.cpp b/services/flashd/partition.cpp index 75d0f1d8..aa4264f0 100755 --- a/services/flashd/partition.cpp +++ b/services/flashd/partition.cpp @@ -106,12 +106,16 @@ int Partition::DoErase() if (ret < 0) { range[0] = 0; range[1] = size; +#ifndef UPDATER_UT ret = ioctl(fd_, BLKDISCARD, &range); +#endif FLASHING_CHECK(ret >= 0, flash_->RecordMsg(updater::ERROR, "Failed to erase \"%s\" error: %s", partName_.c_str(), strerror(errno)); return ret, "Failed to erase %s error: %s", partName_.c_str(), strerror(errno)); std::vector buffer(BLOCK_SIZE, 0); +#ifndef UPDATER_UT ret = updater::utils::WriteFully(fd_, buffer.data(), buffer.size()); +#endif FLASHING_CHECK(ret == 0, return FLASHING_PART_WRITE_ERROR, "Failed to flash data errno %d", errno); fsync(fd_); } @@ -121,11 +125,9 @@ int Partition::DoErase() int Partition::DoFormat(const std::string &fsType) { - if (mountPoint_ == "/") { /* Can not format root */ - return 0; - } int ret = DoUmount(); FLASHING_CHECK(ret == 0, return FLASHING_PART_WRITE_ERROR, "Failed to umount partition"); + FLASHING_LOGI("DoFormat partition %s format %s", partName_.c_str(), fsType_.c_str()); std::vector formatCmds {}; ret = BuildCommandParam(fsType, formatCmds); @@ -150,15 +152,6 @@ int Partition::DoResize(uint32_t blocks) bool needResize = false; if (!mountPoint_.empty()) { needResize = FlashService::CheckFreeSpace(mountPoint_, blocks); - } else { - ret = Open(); - FLASHING_CHECK(ret == 0, return ret, "Can not open partiton %s for erase", partName_.c_str()); - uint64_t size = GetBlockDeviceSize(fd_); - FLASHING_LOGI("DoResise partition %s size %lu", partName_.c_str(), size); - close(fd_); - fd_ = -1; - uint64_t min = static_cast(DEFAULT_BLOCK_SIZE) * static_cast(blocks); - needResize = size < min; } if (!needResize) { FLASHING_LOGI("No need to resize partition %s", partName_.c_str()); @@ -184,10 +177,9 @@ int Partition::DoResize(uint32_t blocks) int Partition::Open() { - if (fd_ != -1) { - return 0; + if (fd_ <= 0) { + fd_ = open(partPath_.c_str(), O_RDWR); } - fd_ = open(partPath_.c_str(), O_RDWR); FLASHING_CHECK(fd_ > 0, flash_->RecordMsg(updater::ERROR, "Can not open partiton \"%s\" error: %s", partName_.c_str(), strerror(errno)); @@ -211,12 +203,9 @@ int Partition::WriteRowData(int inputFd, size_t fileSize, std::vector & totalWrite += writeLen; // continue read and write - ssize_t ret = read(inputFd, buffer.data(), buffer.size()); - if (ret <= 0) { - break; - } - - flash_->PostProgress(UPDATEMOD_FLASH, dataSize, nullptr); + ssize_t ret = read(inputFd, buffer.data(), dataSize); + FLASHING_CHECK(ret > 0, return -1, "Failed to read data %d %d", errno, buffer.size()); + flash_->PostProgress(UPDATEMOD_FLASH, writeLen, nullptr); dataLen = ret; } while (1); fsync(fd_); @@ -227,9 +216,7 @@ int Partition::IsBlockDevice(int fd) const { struct stat st {}; int ret = fstat(fd, &st); - if (ret < 0) { - return 0; - } + FLASHING_CHECK(ret >= 0, return 0, "Invalid get fstate %d", errno); return S_ISBLK(st.st_mode); } @@ -299,11 +286,13 @@ int Partition::DoUmount() if (mountPoint_.empty()) { return 0; } +#ifndef UPDATER_UT int ret = umount2(mountPoint_.c_str(), MNT_FORCE); FLASHING_CHECK(ret == 0, flash_->RecordMsg(updater::ERROR, "Failed to umount \"%s\" error: %s", partName_.c_str(), strerror(errno)); return FLASHING_PART_WRITE_ERROR, "Failed to umount \"%s\" error: %s", partName_.c_str(), strerror(errno)); - return ret; +#endif + return 0; } int Partition::DoMount() @@ -324,7 +313,11 @@ int Partition::DoMount() std::string data; uint32_t flags = GetMountFlags(mountFlags_, data); errno = 0; + while ((ret = mount(partPath_.c_str(), mountPoint_.c_str(), fsType_.c_str(), flags, data.c_str()) != 0)) { +#ifdef UPDATER_UT + ret = 0; +#endif if (errno == EAGAIN) { continue; } else { diff --git a/services/include/flashd/flashd.h b/services/include/flashd/flashd.h index 8eae9598..8d46b976 100755 --- a/services/include/flashd/flashd.h +++ b/services/include/flashd/flashd.h @@ -44,21 +44,19 @@ static constexpr uint16_t MAX_SIZE_BUF = 1024; static constexpr uint32_t PERCENT_FINISH = 100; static constexpr uint32_t PERCENT_CLEAR = (uint32_t)-1; -#ifndef LOCAL_SUPPORT const std::string FORMAT_TOOL_FOR_EXT4 = "/bin/mke2fs"; const std::string FORMAT_TOOL_FOR_F2FS = "/bin/make_f2fs"; const std::string RESIZE_TOOL = "/bin/resize2fs"; + +#ifndef UPDATER_UT const std::string FLASHD_FILE_PATH = "/data/updater/"; const std::string FLASHD_HDC_LOG_PATH = "/tmp/flashd_hdc.log"; #else -const std::string FORMAT_TOOL_FOR_EXT4 = "/usr/sbin/mke2fs"; -const std::string FORMAT_TOOL_FOR_F2FS = "/system/bin/make_f2fs"; -const std::string RESIZE_TOOL = "/bin/resize2fs"; -const std::string FLASHD_FILE_PATH = "/home/axw/develop/build/"; -const std::string FLASHD_HDC_LOG_PATH = "/home/axw/develop/build/hdc.log"; +const std::string FLASHD_FILE_PATH = "/data/updater/updater/"; +const std::string FLASHD_HDC_LOG_PATH = "/data/updater/flashd_hdc.log"; #endif static constexpr uint32_t MIN_BLOCKS_FOR_UPDATE = 1024 * 1024; -static constexpr uint32_t DEFAULT_BLOCK_SIZE = 4096; +static constexpr uint32_t DEFAULT_BLOCK_SIZE = 2048; static constexpr uint32_t DEFAULT_SIZE_UNIT = 1024 * 1024; using FlashHandle = void *; diff --git a/services/include/updater/updater.h b/services/include/updater/updater.h index 0d94c5ab..272c301a 100644 --- a/services/include/updater/updater.h +++ b/services/include/updater/updater.h @@ -52,8 +52,10 @@ int IsSpaceCapacitySufficient(const std::string &packagePath); bool IsSDCardExist(const std::string &sdcard_path); -void PostUpdater(); +void PostUpdater(bool clearMisc); std::vector ParseParams(int argc, char **argv); + +int GetBootMode(int &mode); } // updater #endif /* UPDATER_UPDATER_H */ diff --git a/services/include/updater/updater_const.h b/services/include/updater/updater_const.h index 88775927..6b447687 100644 --- a/services/include/updater/updater_const.h +++ b/services/include/updater/updater_const.h @@ -75,5 +75,7 @@ constexpr unsigned int UI_SHOW_DURATION = 2000; constexpr unsigned int INTERVAL_TIME = 300; constexpr float EPSINON = 0.00001; constexpr float FULL_EPSINON = 1; +constexpr int BOOT_FLASHD = 1; +constexpr int BOOT_UPDATER = 2; } // namespace updater #endif diff --git a/services/main.cpp b/services/main.cpp index bb29543f..6f5d5fe9 100644 --- a/services/main.cpp +++ b/services/main.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include "fs_manager/mount.h" +#include "flashd/flashd.h" #include "log/log.h" #include "misc_info/misc_info.h" #include "updater/updater_const.h" @@ -22,27 +23,19 @@ using namespace updater; int main(int argc, char **argv) { - struct UpdateMessage boot {}; - // read from misc - bool ret = ReadUpdaterMessage(MISC_FILE, boot); - if (!ret) { - printf("ReadUpdaterMessage MISC_FILE failed!\n"); + int mode = BOOT_UPDATER; + int ret = GetBootMode(mode); + if (ret != 0) { + printf("Failed to get boot mode, start updater mode \n"); + mode = BOOT_UPDATER; } - // if boot.update is empty, read from command.The Misc partition may have dirty data, - // so strlen(boot.update) is not used, which can cause system exceptions. - if (boot.update[0] == '\0' && !access(COMMAND_FILE.c_str(), 0)) { - ret = ReadUpdaterMessage(COMMAND_FILE, boot); - if (!ret) { - printf("ReadUpdaterMessage COMMAND_FILE failed!\n"); - } - } - const int flashBootLength = 10; - bool useFlash = memcmp(boot.command, "boot_flash", flashBootLength) == 0; - InitUpdaterLogger(useFlash ? "FLASHD" : "UPDATER", TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH); + + InitUpdaterLogger((mode == BOOT_FLASHD) ? "FLASHD" : "UPDATER", TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH); SetLogLevel(INFO); LoadFstab(); - STAGE(UPDATE_STAGE_OUT) << "Init Params: " << boot.update; - LOG(INFO) << "boot.command " << boot.command; - LOG(INFO) << "boot.update " << boot.update; + STAGE(UPDATE_STAGE_OUT) << "Start " << ((mode == BOOT_FLASHD) ? "flashd" : "updater"); + if (mode == BOOT_FLASHD) { + return flashd::flashd_main(argc, argv); + } return updater::UpdaterMain(argc, argv); } diff --git a/services/package/pkg_algorithm/pkg_algo_digest.cpp b/services/package/pkg_algorithm/pkg_algo_digest.cpp index 1855aa67..0c1b8934 100644 --- a/services/package/pkg_algorithm/pkg_algo_digest.cpp +++ b/services/package/pkg_algorithm/pkg_algo_digest.cpp @@ -39,7 +39,11 @@ size_t DigestAlgorithm::GetSignatureLen(int8_t digestMethod) uint8_t DigestAlgorithm::GetDigestMethod(std::string version) { - return PKG_DIGEST_TYPE_SHA256; + if (version == "3") { + return PKG_DIGEST_TYPE_SHA384; + } else { + return PKG_DIGEST_TYPE_SHA256; + } } int32_t Crc32Algorithm::Init() @@ -120,7 +124,7 @@ int32_t Sha384Algorithm::Update(const PkgBuffer &buffer, size_t size) int32_t Sha384Algorithm::Final(PkgBuffer &result) { - PKG_CHECK(result.buffer != nullptr && result.length == DIGEST_SHA384_LEN, + PKG_CHECK(result.buffer != nullptr && result.length == 64, // 64 length return PKG_INVALID_PARAM, "Param context null!"); SHA384_Final(result.buffer, &shaCtx_); return PKG_SUCCESS; @@ -128,7 +132,7 @@ int32_t Sha384Algorithm::Final(PkgBuffer &result) int32_t Sha384Algorithm::Calculate(PkgBuffer &result, const PkgBuffer &buffer, size_t size) { - PKG_CHECK(result.buffer != nullptr && result.length == DIGEST_SHA384_LEN, + PKG_CHECK(result.buffer != nullptr && result.length == 64, // 64 length return PKG_INVALID_PARAM, "Param context null!"); PKG_CHECK(buffer.buffer != nullptr, return PKG_INVALID_PARAM, "Param null!"); SHA512_Init(&shaCtx_); diff --git a/services/package/pkg_algorithm/pkg_algo_digest.h b/services/package/pkg_algorithm/pkg_algo_digest.h index 4b08139d..a83c1328 100644 --- a/services/package/pkg_algorithm/pkg_algo_digest.h +++ b/services/package/pkg_algorithm/pkg_algo_digest.h @@ -21,7 +21,7 @@ namespace hpackage { constexpr uint32_t DIGEST_CRC_LEN = 4; constexpr uint32_t DIGEST_SHA256_LEN = 32; -constexpr uint32_t DIGEST_SHA384_LEN = 64; +constexpr uint32_t DIGEST_SHA384_LEN = 48; constexpr uint32_t SIGN_SHA256_LEN = 256; constexpr uint32_t SIGN_SHA384_LEN = 384; constexpr uint32_t SIGN_TOTAL_LEN = 384 + 256; diff --git a/services/package/pkg_algorithm/pkg_algo_sign.cpp b/services/package/pkg_algorithm/pkg_algo_sign.cpp index fd258ded..b0f9d9cc 100644 --- a/services/package/pkg_algorithm/pkg_algo_sign.cpp +++ b/services/package/pkg_algorithm/pkg_algo_sign.cpp @@ -85,14 +85,20 @@ int32_t SignAlgorithmEcc::SignBuffer(const PkgBuffer &buffer, std::vector &digest, const int hashNid = NID_sha1; if (certs.hashLen == SHA256_DIGEST_LENGTH) { hashNid = NID_sha256; + } else if (certs.hashLen == SHA384_DIGEST_LENGTH) { + hashNid = NID_sha384; } int ret = 0; if (certs.keyType == KEY_TYPE_RSA) { diff --git a/services/package/pkg_algorithm/pkg_algo_sign.h b/services/package/pkg_algorithm/pkg_algo_sign.h index eb0900fd..f8c6a68c 100644 --- a/services/package/pkg_algorithm/pkg_algo_sign.h +++ b/services/package/pkg_algorithm/pkg_algo_sign.h @@ -75,7 +75,7 @@ public: private: bool CheckEccKey(const EC_KEY *eccKey) const; - bool CheckRsaKey(const RSA *rsakey) const; + bool CheckRsaKey(const RSA *rsakey, int &hashLen) const; bool LoadPubKey(const std::string &filename, struct CertKeySt &certs) const; }; diff --git a/services/package/pkg_manager/pkg_managerImpl.cpp b/services/package/pkg_manager/pkg_managerImpl.cpp index 684536c0..aa895157 100644 --- a/services/package/pkg_manager/pkg_managerImpl.cpp +++ b/services/package/pkg_manager/pkg_managerImpl.cpp @@ -104,6 +104,7 @@ int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string if (pkgFile == nullptr) { return PKG_INVALID_FILE; } + offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset; ret = Sign(pkgFile->GetPkgStream(), offset, header); delete pkgFile; return ret; @@ -120,6 +121,7 @@ int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string if (pkgFile == nullptr) { return PKG_INVALID_FILE; } + offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset; ret = Sign(pkgFile->GetPkgStream(), offset, header); delete pkgFile; return ret; @@ -136,6 +138,7 @@ int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string if (pkgFile == nullptr) { return PKG_INVALID_FILE; } + offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset; ret = Sign(pkgFile->GetPkgStream(), offset, header); delete pkgFile; return ret; diff --git a/services/package/pkg_package/pkg_lz4file.cpp b/services/package/pkg_package/pkg_lz4file.cpp index 372c9cdc..96d8f4ca 100644 --- a/services/package/pkg_package/pkg_lz4file.cpp +++ b/services/package/pkg_package/pkg_lz4file.cpp @@ -130,7 +130,6 @@ int32_t Lz4PkgFile::AddEntry(const PkgManager::FileInfoPtr file, const PkgStream PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail Pack for %s", file->identity.c_str()); currentOffset_ += encodeLen; PKG_LOGI("offset:%zu ", currentOffset_); - pkgStream_->Flush(currentOffset_); return PKG_SUCCESS; } diff --git a/services/ui/updater_ui.cpp b/services/ui/updater_ui.cpp index bf15c482..edcbc93c 100644 --- a/services/ui/updater_ui.cpp +++ b/services/ui/updater_ui.cpp @@ -162,7 +162,7 @@ void OnKeyEvent(int viewId) ClearText(); if (viewId == g_textLabel0->GetViewId() && g_textLabel0->IsVisiable()) { HideDialog(); - PostUpdater(); + PostUpdater(true); utils::DoReboot(""); } else if (viewId == g_textLabel2->GetViewId() && g_textLabel2->IsVisiable()) { ShowDialog(); @@ -174,7 +174,7 @@ void OnKeyEvent(int viewId) ShowMenu(); return; } - PostUpdater(); + PostUpdater(true); utils::DoReboot(""); } else if (viewId == g_dialogCancalBtn->GetViewId() && g_dialogCancalBtn->IsVisiable()) { HideDialog(); @@ -439,6 +439,7 @@ void UpdaterUiInit() g_anmimationLabel->SetBackgroundColor(&bgColor); LoadImgs(); g_progressBar = new ProgressBar(START_X3, START_Y3, WIDTH3, HEIGHT3, g_updateFrame); + g_progressBar->Hide(); g_updateInfoLabel = new TextLabel(START_X5, START_Y5, screenW, HEIGHT5, g_updateFrame); g_updateInfoLabel->SetOutLineBold(false, false); diff --git a/services/updater.cpp b/services/updater.cpp index caccbbfe..3aa34d74 100644 --- a/services/updater.cpp +++ b/services/updater.cpp @@ -153,9 +153,7 @@ UpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, cons // Only handle UPATE_ERROR and UPDATE_SUCCESS here. // If it returns UPDATE_CORRUPT, which means something wrong with package manager. // Let package verify handle this. - if (ret == UPDATE_SPACE_NOTENOUGH) { - ShowText(GetUpdateInfoLabel(), "Free space is not enough"); - } else if (ret == UPDATE_ERROR) { + if (ret == UPDATE_SPACE_NOTENOUGH || ret == UPDATE_ERROR) { return ret; } else if (ret == UPDATE_SUCCESS) { pkgManager = PkgManager::GetPackageInstance(); diff --git a/services/updater_main.cpp b/services/updater_main.cpp index c4b40a2c..9b393a6d 100644 --- a/services/updater_main.cpp +++ b/services/updater_main.cpp @@ -170,7 +170,8 @@ static UpdaterStatus InstallUpdaterPackage(UpdaterParams &upParams, const std::v status = DoInstallUpdaterPackage(manager, upParams.updatePackage, upParams.retryCount); if (status != UPDATE_SUCCESS) { std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION)); - g_logLabel->SetText("update failed!"); + std::string errMsg = ((status == UPDATE_SPACE_NOTENOUGH) ? "Free space is not enough" : "Update failed!"); + g_logLabel->SetText(errMsg.c_str()); STAGE(UPDATE_STAGE_FAIL) << "Install failed"; if (status == UPDATE_RETRY && upParams.retryCount < MAX_RETRY_COUNT) { upParams.retryCount += 1; @@ -222,7 +223,7 @@ static UpdaterStatus StartUpdaterEntry(PkgManager::PkgManagerPtr manager, g_logResultLabel->SetText("Wipe data failed"); } else { g_logResultLabel->SetText("Wipe data finished"); - PostUpdater(); + PostUpdater(true); std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION)); } } @@ -297,7 +298,7 @@ int UpdaterMain(int argc, char **argv) return 0; } #endif - PostUpdater(); + PostUpdater(true); utils::DoReboot(""); return 0; } diff --git a/services/updater_utils.cpp b/services/updater_utils.cpp index 0abd3ca1..bd4e7927 100755 --- a/services/updater_utils.cpp +++ b/services/updater_utils.cpp @@ -196,7 +196,7 @@ void PostUpdaterForSdcard(std::string &updaterLogPath, std::string &stageLogPath return; } -void PostUpdater() +void PostUpdater(bool clearMisc) { STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater"; std::string updaterLogPath = "/data/updater/log/updater_log"; @@ -204,7 +204,9 @@ void PostUpdater() std::string errorCodePath = "/data/updater/log/error_code.log"; PostUpdaterForSdcard(updaterLogPath, stageLogPath, errorCodePath); // clear update misc partition. - UPDATER_ERROR_CHECK_NOT_RETURN(ClearMisc() == true, "PostUpdater clear misc failed"); + if (clearMisc) { + UPDATER_ERROR_CHECK_NOT_RETURN(ClearMisc() == true, "PostUpdater clear misc failed"); + } if (!access(COMMAND_FILE.c_str(), 0)) { UPDATER_ERROR_CHECK_NOT_RETURN(unlink(COMMAND_FILE.c_str()) == 0, "Delete command failed"); } @@ -287,4 +289,31 @@ std::vector ParseParams(int argc, char **argv) parseParams.insert(parseParams.end(), parseParams1.begin(), parseParams1.end()); return parseParams; } + +int GetBootMode(int &mode) +{ +#ifndef UPDATER_UT + mode = BOOT_UPDATER; +#else + mode = BOOT_FLASHD; +#endif + struct UpdateMessage boot {}; + // read from misc + bool ret = ReadUpdaterMessage(MISC_FILE, boot); + if (!ret) { + return -1; + } + // if boot.update is empty, read from command.The Misc partition may have dirty data, + // so strlen(boot.update) is not used, which can cause system exceptions. + if (boot.update[0] == '\0' && !access(COMMAND_FILE.c_str(), 0)) { + ret = ReadUpdaterMessage(COMMAND_FILE, boot); + if (!ret) { + return -1; + } + } + if (memcmp(boot.command, "boot_flash", strlen("boot_flash")) == 0) { + mode = BOOT_FLASHD; + } + return 0; +} } // namespace updater diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 14ec0f0f..5a7a54c8 100755 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -44,6 +44,8 @@ ohos_unittest("updater_unittest") { "applypatch_test/transfer_manager_unittest.cpp", "diffpatch/bzip2_unittest.cpp", "diffpatch/diffpatch_unittest.cpp", + "flashd_test/flash_host_unittest.cpp", + "flashd_test/flash_service_unittest.cpp", "fs_manager/do_partition_unittest.cpp", "log_test/log_unittest.cpp", "misc_info_test/misc_info_unittest.cpp", @@ -91,6 +93,12 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/diffpatch/patch/blocks_patch.cpp", "//base/update/updater/services/diffpatch/patch/image_patch.cpp", "//base/update/updater/services/diffpatch/patch/update_patch.cpp", + "//base/update/updater/services/flashd/blockdevice.cpp", + "//base/update/updater/services/flashd/daemon/daemon_updater.cpp", + "//base/update/updater/services/flashd/daemon/flashd_main.cpp", + "//base/update/updater/services/flashd/flash_service.cpp", + "//base/update/updater/services/flashd/host/host_updater.cpp", + "//base/update/updater/services/flashd/partition.cpp", "//base/update/updater/services/fs_manager/cmp_partition.cpp", "//base/update/updater/services/fs_manager/do_partition.cpp", "//base/update/updater/services/fs_manager/mount.cpp", @@ -156,6 +164,9 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/package/pkg_package", "//base/update/updater/services/updater_binary", "//base/update/updater/services/include/fs_manager", + "//base/update/updater/services/flashd", + "//base/update/updater/services/flashd/daemon", + "//base/update/updater/services/flashd/host", "//base/update/updater/services/fs_manager", "//base/update/updater/services/applypatch", "//base/update/updater/services/diffpatch", @@ -185,6 +196,11 @@ ohos_unittest("updater_unittest") { "//drivers/peripheral/input/hal/include", "//drivers/peripheral/input/interfaces/include", "//third_party/bounds_checking_function/include", + "//developtools/hdc_standard/src", + "//developtools/hdc_standard/src/daemon", + "//developtools/hdc_standard/src/common", + "//developtools/hdc_standard/src/host", + "//base/startup/init_lite/interfaces/innerkits/include", ] deps = [ "//base/startup/init_lite/interfaces/innerkits/fs_manager:libfsmanager_static", @@ -198,11 +214,13 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/package:libupdaterpackage", "//base/update/updater/services/ui:libui", "//base/update/updater/utils:libutils", + "//developtools/hdc_standard:hdc_deamon_flashd", "//third_party/bounds_checking_function:libsec_static", "//third_party/bzip2:libbz2", "//third_party/cJSON:cjson_static", "//third_party/googletest:gmock_main", "//third_party/googletest:gtest_main", + "//third_party/libuv:uv_static", "//third_party/lz4:liblz4_static", "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", @@ -219,6 +237,9 @@ ohos_unittest("updater_unittest") { defines = [ "UPDATER_UT", "BUILD_OHOS", + "HDC_DEBUG", + "HDC_SUPPORT_FLASHD", + "HARMONY_PROJECT", ] public_configs = [ ":utest_config" ] diff --git a/test/unittest/applypatch_test/imagepatch_unittest.h b/test/unittest/applypatch_test/imagepatch_unittest.h index e4cdc358..6da5f553 100755 --- a/test/unittest/applypatch_test/imagepatch_unittest.h +++ b/test/unittest/applypatch_test/imagepatch_unittest.h @@ -77,7 +77,9 @@ public: int fd = open(target.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY, mode); EXPECT_GE(fd, 0); BlockSet targetBlk; - targetBlk.ParserAndInsert({"2", "0", "1"}); + targetBlk.ParserAndInsert({ + "2", "0", "1" + }); std::unique_ptr writer = std::make_unique(fd, targetBlk); std::vector empty; int32_t ret = updatepatch::UpdatePatch::ApplyImagePatch(param, empty, diff --git a/test/unittest/flashd_test/flash_host_unittest.cpp b/test/unittest/flashd_test/flash_host_unittest.cpp index c4e6d023..fe97130e 100755 --- a/test/unittest/flashd_test/flash_host_unittest.cpp +++ b/test/unittest/flashd_test/flash_host_unittest.cpp @@ -29,8 +29,8 @@ using namespace Hdc; using namespace testing::ext; namespace { static std::string TEST_PARTITION_NAME = "data"; -static std::string TEST_UPDATER_PACKAGE_PATH = "/data/updater/src/updater.zip"; -static std::string TEST_FLASH_IMAGE_NAME = "/data/updater/src/image/userdata.img"; +static std::string TEST_UPDATER_PACKAGE_PATH = "/data/updater/updater/updater.zip"; +static std::string TEST_FLASH_IMAGE_NAME = "/data/updater/updater/test.img"; class FLashHostUnitTest : public testing::Test { public: @@ -51,54 +51,123 @@ public: HTaskInfo hTaskInfo = nullptr; std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } hTaskInfo = task.get(); hTaskInfo->channelId = 1; hTaskInfo->sessionId = 0; hTaskInfo->runLoop = &loopMain; hTaskInfo->serverOrDaemon = 0; std::shared_ptr flashHost = std::make_shared(hTaskInfo); + if (flashHost == nullptr) { + return -1; + } flashHost->CommandDispatch(command, const_cast(reinterpret_cast(cmd.data())), cmd.size()); return 0; } + + int TestFlashProgress(uint16_t command, const std::string &cmd, uint32_t progress) + { + uv_loop_t loopMain; + uv_loop_init(&loopMain); + + HTaskInfo hTaskInfo = nullptr; + std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } + hTaskInfo = task.get(); + hTaskInfo->channelId = 1; + hTaskInfo->sessionId = 0; + hTaskInfo->runLoop = &loopMain; + hTaskInfo->serverOrDaemon = 0; + std::shared_ptr flashHost = std::make_shared(hTaskInfo); + if (flashHost == nullptr) { + return -1; + } + flashHost->CommandDispatch(command, + const_cast(reinterpret_cast(cmd.data())), cmd.size()); + flashHost->OpenFile(); + + std::vector data(MAX_SIZE_IOBUF * 2); // 2 + flashHost->CommandDispatch(CMD_UPDATER_BEGIN, const_cast(data.data()), data.size()); + + std::string cmdInfo = ""; + flashHost->CommandDispatch(CMD_UPDATER_CHECK, + const_cast(reinterpret_cast(cmdInfo.data())), cmdInfo.size()); + + flashHost->CommandDispatch(CMD_UPDATER_DATA, const_cast(data.data()), data.size()); + + vector info = {0, 1, 's', 'u', 'c', 'c', 'e', 's', 's'}; + flashHost->CommandDispatch(CMD_UPDATER_FINISH, + const_cast(reinterpret_cast(info.data())), info.size()); + + uint32_t percentage = 30; // 30 progress + cmdInfo.resize(sizeof(percentage)); + (void)memcpy_s(cmdInfo.data(), cmdInfo.size(), &percentage, sizeof(percentage)); + flashHost->CommandDispatch(CMD_UPDATER_PROGRESS, + const_cast(reinterpret_cast(cmdInfo.data())), cmdInfo.size()); + + percentage = (uint32_t)progress; + cmdInfo.resize(sizeof(percentage)); + (void)memcpy_s(cmdInfo.data(), cmdInfo.size(), &percentage, sizeof(percentage)); + flashHost->CommandDispatch(CMD_UPDATER_PROGRESS, + const_cast(reinterpret_cast(cmdInfo.data())), cmdInfo.size()); + + return 0; + } }; HWTEST_F(FLashHostUnitTest, TestFlashHost, TestSize.Level1) { FLashHostUnitTest test; + Base::SetLogLevel(LOG_LAST); // debug log print - std::string cmdParam = "update "; - cmdParam += TEST_UPDATER_PACKAGE_PATH; + std::string cmdParam = TEST_UPDATER_PACKAGE_PATH; EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_UPDATE_INIT, cmdParam)); - cmdParam = "flash "; + cmdParam = " -f "; cmdParam += TEST_PARTITION_NAME + " "; cmdParam += TEST_FLASH_IMAGE_NAME; EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FLASH_INIT, cmdParam)); - cmdParam = ""; - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_CHECK, cmdParam)); - - cmdParam = ""; - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_BEGIN, cmdParam)); - - cmdParam = ""; - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_DATA, cmdParam)); - - cmdParam = ""; - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FINISH, cmdParam)); - cmdParam = "erase -f "; cmdParam += TEST_PARTITION_NAME; EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_ERASE, cmdParam)); cmdParam = "format -f "; cmdParam += TEST_PARTITION_NAME; + cmdParam += " -t ext4"; EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FORMAT, cmdParam)); +} + +HWTEST_F(FLashHostUnitTest, TestFlashProgress, TestSize.Level1) +{ + FLashHostUnitTest test; + Base::SetLogLevel(LOG_LAST); // debug log print + + std::string cmdParam = TEST_UPDATER_PACKAGE_PATH; + EXPECT_EQ(0, test.TestFlashProgress(CMD_UPDATER_UPDATE_INIT, cmdParam, -1)); - uint32_t percentage = 30; // 30 progress - cmdParam.resize(sizeof(percentage)); - memcpy_s(cmdParam.data(), cmdParam.size(), &percentage, sizeof(percentage)); - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_PROGRESS, cmdParam)); + cmdParam = " -f "; + cmdParam += TEST_PARTITION_NAME + " "; + cmdParam += TEST_FLASH_IMAGE_NAME; + EXPECT_EQ(0, test.TestFlashProgress(CMD_UPDATER_FLASH_INIT, cmdParam, -1)); +} + +HWTEST_F(FLashHostUnitTest, TestFlashProgressFinish, TestSize.Level1) +{ + FLashHostUnitTest test; + Base::SetLogLevel(LOG_LAST); // debug log print + + std::string cmdParam = TEST_UPDATER_PACKAGE_PATH; + EXPECT_EQ(0, test.TestFlashProgress(CMD_UPDATER_UPDATE_INIT, cmdParam, 100)); + + cmdParam = " -f "; + cmdParam += TEST_PARTITION_NAME + " "; + cmdParam += TEST_FLASH_IMAGE_NAME; + EXPECT_EQ(0, test.TestFlashProgress(CMD_UPDATER_FLASH_INIT, cmdParam, 100)); } } // namespace \ No newline at end of file diff --git a/test/unittest/flashd_test/flash_service_unittest.cpp b/test/unittest/flashd_test/flash_service_unittest.cpp index 64b37920..3a33c1cf 100755 --- a/test/unittest/flashd_test/flash_service_unittest.cpp +++ b/test/unittest/flashd_test/flash_service_unittest.cpp @@ -23,6 +23,7 @@ #include "daemon_updater.h" #include "flash_service.h" #include "flashd/flashd.h" +#include "fs_manager/mount.h" #include "serial_struct.h" #include "unittest_comm.h" @@ -30,10 +31,11 @@ using namespace std; using namespace flashd; using namespace Hdc; using namespace testing::ext; + namespace { static std::string TEST_PARTITION_NAME = "data"; -static std::string TEST_UPDATER_PACKAGE_PATH = "/home/axw/develop/updater.zip"; -static std::string TEST_FLASH_IMAGE_NAME = "/home/axw/develop/image/userdata.img"; +static std::string TEST_UPDATER_PACKAGE_PATH = "/data/updater/updater/updater.zip"; +static std::string TEST_FLASH_IMAGE_NAME = "/data/updater/updater/updater.zip"; class FLashServiceUnitTest : public testing::Test { public: @@ -49,6 +51,7 @@ public: public: int TestFindAllDevice() { + updater::LoadFstab(); std::string errorMsg; std::shared_ptr flash = std::make_shared(errorMsg); if (flash == nullptr) { @@ -69,6 +72,18 @@ public: return 0; } + int TestDoUpdater() + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + flash->DoUpdate(TEST_UPDATER_PACKAGE_PATH); + flash->PostProgress(UPDATEMOD_UPDATE, 1024 * 1024 * 4, nullptr); // 1024 * 1024 * 4 4M + return 0; + } + int TestDoErasePartition() { std::string errorMsg; @@ -80,14 +95,26 @@ public: return 0; } - int TestDoFormatPartition() + int TestDoFormatPartition(const std::string &part, const std::string &type) { std::string errorMsg; std::shared_ptr flash = std::make_shared(errorMsg); if (flash == nullptr) { return 1; } - flash->DoFormatPartition(TEST_PARTITION_NAME, "ext4"); + flash->DoFormatPartition(part, type); + return 0; + } + + int TestFlashServiceDoResizeParatiton() + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + flash->DoResizeParatiton("data", 4096); // 4096 partition size + flash->DoResizeParatiton("data", 1024); // 1024 partition size return 0; } @@ -131,12 +158,18 @@ public: HTaskInfo hTaskInfo = nullptr; std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } hTaskInfo = task.get(); hTaskInfo->channelId = 1; hTaskInfo->sessionId = 0; hTaskInfo->runLoop = &loopMain; hTaskInfo->serverOrDaemon = 1; std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); + if (hdcDamon == nullptr) { + return -1; + } // cmd: hdc updater packagename // check @@ -148,7 +181,6 @@ public: WRITE_LOG(LOG_DEBUG, "CheckMaster %s", transferConfig.functionName.c_str()); transferConfig.optionalName = "updater.zip"; std::string bufString = SerialStruct::SerializeToString(transferConfig); - // 当前升级包中总的文件的大小 const uint64_t realSize = static_cast(1024 * 1024 * 1024) * 5; std::vector buffer(sizeof(realSize) + bufString.size()); int ret = memcpy_s(buffer.data(), buffer.size(), &realSize, sizeof(realSize)); @@ -160,41 +192,80 @@ public: // begin hdcDamon->CommandDispatch(CMD_UPDATER_BEGIN, NULL, 0); - // data 写数据部分 - const uint32_t dataSize = 1024; // 1024 data size - HdcTransferBase::TransferPayload payloadHead {}; - payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; - payloadHead.uncompressSize = dataSize; - payloadHead.compressSize = dataSize; - payloadHead.index = 0; - std::string bufData = SerialStruct::SerializeToString(payloadHead); - hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); - - payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; - payloadHead.uncompressSize = dataSize; - payloadHead.compressSize = dataSize; - payloadHead.index = 1; - bufData = SerialStruct::SerializeToString(payloadHead); - hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); + for (int i = 0; i < 100; i++) { // 10 send time + HdcTransferBase::TransferPayload payloadHead {}; + payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; + payloadHead.uncompressSize = transferConfig.fileSize / 10; // 10 time + payloadHead.compressSize = transferConfig.fileSize / 10; // 10 time + payloadHead.index = 0; + std::string bufData = SerialStruct::SerializeToString(payloadHead); + hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); + } // end hdcDamon->DoTransferFinish(); return 0; } - int TestHdcDaemonFlash() + int TestHdcDaemonInvalid() { uv_loop_t loopMain; uv_loop_init(&loopMain); HTaskInfo hTaskInfo = nullptr; std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } hTaskInfo = task.get(); hTaskInfo->channelId = 2; // 2 channel id hTaskInfo->sessionId = 0; hTaskInfo->runLoop = &loopMain; hTaskInfo->serverOrDaemon = 1; std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); + if (hdcDamon == nullptr) { + return -1; + } + // cmd: hdc flash partition packagename + // check + HdcTransferBase::TransferConfig transferConfig {}; + transferConfig.functionName = "aaaa"; + transferConfig.options = TEST_PARTITION_NAME; + transferConfig.options += " "; + transferConfig.options += TEST_FLASH_IMAGE_NAME; + std::string localPath = TEST_FLASH_IMAGE_NAME; + transferConfig.fileSize = 1468006400; // 1468006400 file size + WRITE_LOG(LOG_DEBUG, "CheckMaster %s", transferConfig.functionName.c_str()); + transferConfig.optionalName = "userdata.img"; + std::string bufString = SerialStruct::SerializeToString(transferConfig); + const uint64_t realSize = static_cast(1024 * 1024 * 1024) * 5; + std::vector buffer(sizeof(realSize) + bufString.size()); + int ret = memcpy_s(buffer.data(), buffer.size(), &realSize, sizeof(realSize)); + EXPECT_EQ(0, ret); + ret = memcpy_s(buffer.data() + sizeof(realSize), buffer.size(), bufString.c_str(), bufString.size()); + EXPECT_EQ(0, ret); + hdcDamon->CommandDispatch(CMD_UPDATER_CHECK, buffer.data(), buffer.size()); + return 0; + } + int TestHdcDaemonFlash() + { + uv_loop_t loopMain; + uv_loop_init(&loopMain); + + HTaskInfo hTaskInfo = nullptr; + std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } + hTaskInfo = task.get(); + hTaskInfo->channelId = 2; // 2 channel id + hTaskInfo->sessionId = 0; + hTaskInfo->runLoop = &loopMain; + hTaskInfo->serverOrDaemon = 1; + std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); + if (hdcDamon == nullptr) { + return -1; + } // cmd: hdc flash partition packagename // check HdcTransferBase::TransferConfig transferConfig {}; @@ -207,8 +278,7 @@ public: WRITE_LOG(LOG_DEBUG, "CheckMaster %s", transferConfig.functionName.c_str()); transferConfig.optionalName = "userdata.img"; std::string bufString = SerialStruct::SerializeToString(transferConfig); - // 当前升级包中总的文件的大小 - const uint64_t realSize = static_cast(1024 * 1024 * 1024) * 5; + const uint64_t realSize = transferConfig.fileSize; std::vector buffer(sizeof(realSize) + bufString.size()); int ret = memcpy_s(buffer.data(), buffer.size(), &realSize, sizeof(realSize)); EXPECT_EQ(0, ret); @@ -219,22 +289,21 @@ public: // begin hdcDamon->CommandDispatch(CMD_UPDATER_BEGIN, NULL, 0); - // data 写数据部分 - const uint32_t dataSize = 1024; // 1024 data size HdcTransferBase::TransferPayload payloadHead {}; + for (int i = 0; i < 10; i++) { // 10 send data + payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; + payloadHead.uncompressSize = transferConfig.fileSize / 10; // 10 time + payloadHead.compressSize = transferConfig.fileSize / 10; // 10 time + payloadHead.index = 0; + std::string bufData = SerialStruct::SerializeToString(payloadHead); + hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); + } payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; - payloadHead.uncompressSize = dataSize; - payloadHead.compressSize = dataSize; + payloadHead.uncompressSize = transferConfig.fileSize / 10; // 10 time + payloadHead.compressSize = transferConfig.fileSize / 10; // 10 time payloadHead.index = 0; std::string bufData = SerialStruct::SerializeToString(payloadHead); hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); - - payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; - payloadHead.uncompressSize = dataSize; - payloadHead.compressSize = dataSize; - payloadHead.index = 1; - bufData = SerialStruct::SerializeToString(payloadHead); - hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); // end hdcDamon->DoTransferFinish(); return 0; @@ -247,20 +316,22 @@ public: HTaskInfo hTaskInfo = nullptr; std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } hTaskInfo = task.get(); hTaskInfo->channelId = 2; // 2 channel id hTaskInfo->sessionId = 0; hTaskInfo->runLoop = &loopMain; hTaskInfo->serverOrDaemon = 1; std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); - + if (hdcDamon == nullptr) { + return -1; + } // cmd: hdc erase partition // check - HdcTransferBase::TransferConfig transferConfig {}; - transferConfig.functionName = "erase"; - transferConfig.options = "erase -f "; - transferConfig.options += TEST_PARTITION_NAME; - std::string bufString = SerialStruct::SerializeToString(transferConfig); + std::string bufString = "erase -f "; + bufString += TEST_PARTITION_NAME; hdcDamon->CommandDispatch(CMD_UPDATER_ERASE, reinterpret_cast(bufString.data()), bufString.size()); return 0; } @@ -272,21 +343,24 @@ public: HTaskInfo hTaskInfo = nullptr; std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } hTaskInfo = task.get(); hTaskInfo->channelId = 2; // 2 channel id hTaskInfo->sessionId = 0; hTaskInfo->runLoop = &loopMain; hTaskInfo->serverOrDaemon = 1; std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); - + if (hdcDamon == nullptr) { + return -1; + } // cmd: hdc format partition // check - HdcTransferBase::TransferConfig transferConfig {}; - transferConfig.functionName = "format"; - transferConfig.options = "format -f "; - transferConfig.options += TEST_PARTITION_NAME; - std::string bufString = SerialStruct::SerializeToString(transferConfig); - hdcDamon->CommandDispatch(CMD_UPDATER_ERASE, reinterpret_cast(bufString.data()), bufString.size()); + std::string bufString = "format -f "; + bufString += TEST_PARTITION_NAME + " -t ext4"; + hdcDamon->CommandDispatch(CMD_UPDATER_FORMAT, reinterpret_cast(bufString.data()), bufString.size()); + return 0; } }; @@ -303,12 +377,24 @@ HWTEST_F(FLashServiceUnitTest, TestDaemonUpdater, TestSize.Level1) EXPECT_EQ(0, test.TestDaemonUpdater()); } +HWTEST_F(FLashServiceUnitTest, TestDoUpdater, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestDoUpdater()); +} + HWTEST_F(FLashServiceUnitTest, TestHdcDaemonFlash, TestSize.Level1) { FLashServiceUnitTest test; EXPECT_EQ(0, test.TestHdcDaemonFlash()); } +HWTEST_F(FLashServiceUnitTest, TestHdcDaemonInvalid, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestHdcDaemonInvalid()); +} + HWTEST_F(FLashServiceUnitTest, TestHdcDaemonErase, TestSize.Level1) { FLashServiceUnitTest test; @@ -336,7 +422,9 @@ HWTEST_F(FLashServiceUnitTest, TestDoFlashPartition, TestSize.Level1) HWTEST_F(FLashServiceUnitTest, TestDoFormatPartition, TestSize.Level1) { FLashServiceUnitTest test; - EXPECT_EQ(0, test.TestDoFormatPartition()); + EXPECT_EQ(0, test.TestDoFormatPartition("data", "ext4")); + EXPECT_EQ(0, test.TestDoFormatPartition("data", "f2fs")); + EXPECT_EQ(0, test.TestDoFormatPartition("boot", "f2fs")); } HWTEST_F(FLashServiceUnitTest, TestDoErasePartition, TestSize.Level1) @@ -345,6 +433,12 @@ HWTEST_F(FLashServiceUnitTest, TestDoErasePartition, TestSize.Level1) EXPECT_EQ(0, test.TestDoErasePartition()); } +HWTEST_F(FLashServiceUnitTest, TestFlashServiceDoResizeParatiton, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestFlashServiceDoResizeParatiton()); +} + HWTEST_F(FLashServiceUnitTest, TestFlashServiceDoPrepare, TestSize.Level1) { FLashServiceUnitTest test; @@ -361,7 +455,7 @@ HWTEST_F(FLashServiceUnitTest, TestFlashServiceDoPrepare, TestSize.Level1) EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_ERASE, cmdParam)); cmdParam = "format -f "; - cmdParam += TEST_PARTITION_NAME + " "; + cmdParam += TEST_PARTITION_NAME + " -t ext4"; EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_FORMAT, cmdParam)); EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_MAX, cmdParam)); @@ -382,11 +476,11 @@ HWTEST_F(FLashServiceUnitTest, TestFlashServiceDoFlash, TestSize.Level1) cmdParam += TEST_PARTITION_NAME + " "; EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_ERASE, cmdParam)); - cmdParam = "format -f ext4 "; + cmdParam = "format -f -t ext4 "; cmdParam += TEST_PARTITION_NAME + " "; EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_FORMAT, cmdParam)); - cmdParam = "format -f f2fs "; + cmdParam = "format -f -t f2fs "; cmdParam += TEST_PARTITION_NAME + " "; EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_FORMAT, cmdParam)); diff --git a/test/unittest/package/package_unittest.cpp b/test/unittest/package/package_unittest.cpp index 381c58f6..5031c3e0 100755 --- a/test/unittest/package/package_unittest.cpp +++ b/test/unittest/package/package_unittest.cpp @@ -38,7 +38,7 @@ public: PackageUnitTest() {} ~PackageUnitTest() override {} public: - int TestPackagePack() + int TestPackagePack(int type = PKG_DIGEST_TYPE_SHA256) { int32_t ret; uint32_t updateFileVersion = 1000; @@ -48,7 +48,7 @@ public: pkgInfo.time = strdup("21:23:49"); pkgInfo.productUpdateId = strdup("555.555.100.555"); pkgInfo.entryCount = testFileNames_.size(); - pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; + pkgInfo.digestMethod = type; pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo.pkgType = PKG_PACK_TYPE_UPGRADE; pkgInfo.updateFileVersion = updateFileVersion; @@ -74,7 +74,8 @@ public: } std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; - ret = CreatePackage(&pkgInfo, comp, packagePath.c_str(), GetTestPrivateKeyName().c_str()); + ret = CreatePackage(&pkgInfo, comp, packagePath.c_str(), + GetTestPrivateKeyName(pkgInfo.digestMethod).c_str()); EXPECT_EQ(ret, PKG_SUCCESS); for (size_t i = 0; i < testFileNames_.size(); i++) { free(comp[i].componentAddr); @@ -88,13 +89,13 @@ public: return ret; } - int TestPackageUnpack() + int TestPackageUnpack(int type) { pkgManager_ = static_cast(PkgManager::GetPackageInstance()); EXPECT_NE(pkgManager_, nullptr); std::vector components; // 使用上面打包的包进行解析 - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testPackageName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testPackageName, GetTestCertName(type), components); EXPECT_EQ(ret, PKG_SUCCESS); for (size_t i = 0; i < components.size(); i++) { @@ -104,17 +105,18 @@ public: return PKG_SUCCESS; } - int TestZipPkgCompress() + int TestZipPkgCompress(int digestMethod) { - return CreateZipPackage(testFileNames_, TEST_PATH_TO + testZipPackageName, TEST_PATH_FROM); + return CreateZipPackage(testFileNames_, TEST_PATH_TO + testZipPackageName, TEST_PATH_FROM, digestMethod); } - int TestZipPkgDecompress() + int TestZipPkgDecompress(int digestMethod) { pkgManager_ = static_cast(PkgManager::GetPackageInstance()); EXPECT_NE(pkgManager_, nullptr); std::vector components; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testZipPackageName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testZipPackageName, + GetTestCertName(digestMethod), components); EXPECT_EQ(ret, PKG_SUCCESS); for (size_t i = 0; i < components.size(); i++) { @@ -146,7 +148,8 @@ public: pkgInfo.pkgType = PKG_PACK_TYPE_LZ4; pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; - return pkgManager_->CreatePackage(TEST_PATH_TO + testLz4PackageName, GetTestPrivateKeyName(), &pkgInfo, files); + return pkgManager_->CreatePackage(TEST_PATH_TO + testLz4PackageName, + GetTestPrivateKeyName(pkgInfo.digestMethod), &pkgInfo, files); } int TestLz4PkgCompressBlock() @@ -170,7 +173,8 @@ public: pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; pkgInfo.pkgType = PKG_PACK_TYPE_LZ4; - return pkgManager_->CreatePackage(TEST_PATH_TO + testLz4PackageName, GetTestPrivateKeyName(), &pkgInfo, files); + return pkgManager_->CreatePackage(TEST_PATH_TO + testLz4PackageName, + GetTestPrivateKeyName(pkgInfo.digestMethod), &pkgInfo, files); } int TestLz4PkgDecompress() @@ -178,7 +182,7 @@ public: pkgManager_ = static_cast(PkgManager::GetPackageInstance()); EXPECT_NE(pkgManager_, nullptr); std::vector components; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testLz4PackageName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testLz4PackageName, GetTestCertName(0), components); EXPECT_EQ(ret, PKG_SUCCESS); for (size_t i = 0; i < components.size(); i++) { @@ -197,7 +201,7 @@ public: std::vector fileNames; fileNames.push_back(testZipPackageName); fileNames.push_back(testPackageName); - ret = CreateZipPackage(fileNames, TEST_PATH_TO + testCombinePkgName, TEST_PATH_TO); + ret = CreateZipPackage(fileNames, TEST_PATH_TO + testCombinePkgName, TEST_PATH_TO, PKG_DIGEST_TYPE_SHA256); EXPECT_EQ(ret, PKG_SUCCESS); return 0; } @@ -208,7 +212,7 @@ public: pkgManager_ = static_cast(PkgManager::GetPackageInstance()); EXPECT_NE(pkgManager_, nullptr); std::vector components; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(0), components); EXPECT_EQ(ret, PKG_SUCCESS); for (size_t i = 0; i < components.size(); i++) { @@ -228,30 +232,30 @@ public: std::vector digest(digestSize); BuildFileDigest(*digest.data(), digest.capacity(), TEST_PATH_TO + testPackageName); std::string path = TEST_PATH_TO + testPackageName; - ret = VerifyPackage(path.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.capacity()); + ret = VerifyPackage(path.c_str(), GetTestCertName(0).c_str(), "", digest.data(), digest.capacity()); EXPECT_EQ(0, ret); constexpr uint32_t digestLen = 10; digest[digestLen] = digestValue; - ret = VerifyPackage(path.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.capacity()); + ret = VerifyPackage(path.c_str(), GetTestCertName(0).c_str(), "", digest.data(), digest.capacity()); EXPECT_EQ(PKG_INVALID_SIGNATURE, ret); return 0; } int TestVerifyZipWithCallback() { - int32_t ret = TestVerifyZip(); + int32_t ret = TestVerifyZip(PKG_DIGEST_TYPE_SHA256); EXPECT_EQ(ret, 0); std::string path = GetCurrPath(); path = TEST_PATH_TO + testZipPackageName; - ret = VerifyPackageWithCallback(path.c_str(), GetTestCertName().c_str(), + ret = VerifyPackageWithCallback(path.c_str(), GetTestCertName(0).c_str(), [](int32_t result, uint32_t percent) { PKG_LOGI("current progress: %u\n", percent); }); EXPECT_EQ(PKG_INVALID_PARAM, ret); return 0; } - int TestVerifyZip() + int TestVerifyZip(int digestMethod) { - int32_t ret = TestZipPkgCompress(); + int32_t ret = TestZipPkgCompress(digestMethod); EXPECT_EQ(ret, 0); constexpr size_t digestSize = 32; uint8_t digestValue = 33; @@ -260,10 +264,12 @@ public: path = TEST_PATH_TO + testZipPackageName; std::vector digest(digestSize); BuildFileDigest(*digest.data(), digest.capacity(), path); - ret = VerifyPackage(path.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.capacity()); + ret = VerifyPackage(path.c_str(), GetTestCertName(digestMethod).c_str(), + std::to_string(digestMethod).c_str(), digest.data(), digest.capacity()); EXPECT_EQ(ret, 0); digest[index] = digestValue; - ret = VerifyPackage(path.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.capacity()); + ret = VerifyPackage(path.c_str(), GetTestCertName(0).c_str(), + std::to_string(digestMethod).c_str(), digest.data(), digest.capacity()); EXPECT_EQ(PKG_INVALID_SIGNATURE, ret); return 0; } @@ -279,10 +285,10 @@ public: path = TEST_PATH_TO + testLz4PackageName; std::vector digest(digestSize); BuildFileDigest(*digest.data(), digest.capacity(), path); - ret = VerifyPackage(path.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.capacity()); + ret = VerifyPackage(path.c_str(), GetTestCertName(0).c_str(), "", digest.data(), digest.capacity()); EXPECT_EQ(0, ret); digest[index] = digestValue; - ret = VerifyPackage(path.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.capacity()); + ret = VerifyPackage(path.c_str(), GetTestCertName(0).c_str(), "", digest.data(), digest.capacity()); EXPECT_EQ(PKG_INVALID_SIGNATURE, ret); return 0; } @@ -309,7 +315,8 @@ public: } std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; - int32_t ret = CreatePackage(&pkgInfo, comp, packagePath.c_str(), GetTestPrivateKeyName().c_str()); + int32_t ret = CreatePackage(&pkgInfo, comp, packagePath.c_str(), + GetTestPrivateKeyName(pkgInfo.digestMethod).c_str()); for (size_t i = 0; i < testFileNames_.size(); i++) { free(comp[i].componentAddr); free(comp[i].filePath); @@ -319,7 +326,7 @@ public: uint8_t digest[digestSize] = {0}; ret = BuildFileDigest(*digest, sizeof(digest), packagePath); EXPECT_EQ(ret, PKG_SUCCESS); - ret = VerifyPackage(packagePath.c_str(), GetTestCertName().c_str(), "", digest, digestSize); + ret = VerifyPackage(packagePath.c_str(), GetTestCertName(0).c_str(), "", digest, digestSize); return ret; } @@ -355,30 +362,30 @@ public: std::vector digest(digestSize); ret = BuildFileDigest(*digest.data(), digest.size(), packagePath.c_str()); EXPECT_EQ(ret, PKG_SUCCESS); - return VerifyPackage(packagePath.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.size()); + return VerifyPackage(packagePath.c_str(), GetTestCertName(0).c_str(), "", digest.data(), digest.size()); } int TestInvalidCreatePackage() const { ComponentInfoExt compInfo; uint8_t pkgType = 5; - int ret = CreatePackage(nullptr, &compInfo, nullptr, GetTestPrivateKeyName().c_str()); + int ret = CreatePackage(nullptr, &compInfo, nullptr, GetTestPrivateKeyName(0).c_str()); EXPECT_EQ(ret, PKG_INVALID_PARAM); UpgradePkgInfoExt pkgInfoExt; pkgInfoExt.pkgType = pkgType; - ret = CreatePackage(&pkgInfoExt, &compInfo, nullptr, GetTestPrivateKeyName().c_str()); + ret = CreatePackage(&pkgInfoExt, &compInfo, nullptr, GetTestPrivateKeyName(0).c_str()); EXPECT_EQ(ret, PKG_INVALID_PARAM); constexpr uint32_t digestLen = 32; - ret = VerifyPackage(nullptr, GetTestCertName().c_str(), nullptr, nullptr, digestLen); + ret = VerifyPackage(nullptr, GetTestCertName(0).c_str(), nullptr, nullptr, digestLen); EXPECT_EQ(ret, PKG_INVALID_PARAM); // 无效的类型 std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; pkgInfoExt.pkgType = pkgType; - ret = CreatePackage(&pkgInfoExt, &compInfo, packagePath.c_str(), GetTestPrivateKeyName().c_str()); + ret = CreatePackage(&pkgInfoExt, &compInfo, packagePath.c_str(), GetTestPrivateKeyName(0).c_str()); EXPECT_EQ(ret, PKG_INVALID_PARAM); return 0; } @@ -403,7 +410,8 @@ public: pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; pkgInfo.pkgType = PKG_PACK_TYPE_GZIP; - return pkgManager_->CreatePackage(TEST_PATH_TO + testGZipPackageName, GetTestPrivateKeyName(), &pkgInfo, files); + return pkgManager_->CreatePackage(TEST_PATH_TO + testGZipPackageName, + GetTestPrivateKeyName(pkgInfo.digestMethod), &pkgInfo, files); } int TestGZipPkgDecompress(const std::string& gzipPackageName) @@ -411,7 +419,7 @@ public: pkgManager_ = static_cast(PkgManager::GetPackageInstance()); EXPECT_NE(nullptr, pkgManager_); std::vector components; - int32_t ret = pkgManager_->LoadPackage(gzipPackageName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(gzipPackageName, GetTestCertName(0), components); EXPECT_EQ(ret, PKG_SUCCESS); for (size_t i = 0; i < components.size(); i++) { @@ -440,7 +448,7 @@ public: pkgManager_ = static_cast(PkgManager::GetPackageInstance()); EXPECT_NE(nullptr, pkgManager_); std::vector fileIds; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testPackageName, GetTestCertName(), fileIds); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testPackageName, GetTestCertName(0), fileIds); EXPECT_EQ(0, ret); // 在load其中的一个zip包 PkgManager::StreamPtr outStream = nullptr; @@ -451,7 +459,7 @@ public: EXPECT_EQ(ret, 0); pkgManager_->ClosePkgStream(outStream); std::vector secondFileIds; - ret = pkgManager_->LoadPackage(TEST_PATH_TO + secondFile, GetTestCertName(), secondFileIds); + ret = pkgManager_->LoadPackage(TEST_PATH_TO + secondFile, GetTestCertName(0), secondFileIds); EXPECT_EQ(0, ret); if (secondFileIds.size() != 1) { EXPECT_EQ(1, ret); @@ -563,15 +571,29 @@ public: HWTEST_F(PackageUnitTest, TestPackage, TestSize.Level1) { PackageUnitTest test; - EXPECT_EQ(0, test.TestPackagePack()); - EXPECT_EQ(0, test.TestPackageUnpack()); + EXPECT_EQ(0, test.TestPackagePack(PKG_DIGEST_TYPE_SHA256)); + EXPECT_EQ(0, test.TestPackageUnpack(PKG_DIGEST_TYPE_SHA256)); +} + +HWTEST_F(PackageUnitTest, TestPackage384, TestSize.Level1) +{ + PackageUnitTest test; + EXPECT_EQ(0, test.TestPackagePack(PKG_DIGEST_TYPE_SHA384)); + EXPECT_EQ(0, test.TestPackageUnpack(PKG_DIGEST_TYPE_SHA384)); } HWTEST_F(PackageUnitTest, TestZipPackage, TestSize.Level1) { PackageUnitTest test; - EXPECT_EQ(0, test.TestZipPkgCompress()); - EXPECT_EQ(0, test.TestZipPkgDecompress()); + EXPECT_EQ(0, test.TestZipPkgCompress(PKG_DIGEST_TYPE_SHA256)); + EXPECT_EQ(0, test.TestZipPkgDecompress(PKG_DIGEST_TYPE_SHA256)); +} + +HWTEST_F(PackageUnitTest, TestZipPackage384, TestSize.Level1) +{ + PackageUnitTest test; + EXPECT_EQ(0, test.TestZipPkgCompress(PKG_DIGEST_TYPE_SHA384)); + EXPECT_EQ(0, test.TestZipPkgDecompress(PKG_DIGEST_TYPE_SHA384)); } HWTEST_F(PackageUnitTest, TestLz4Package, TestSize.Level1) @@ -609,7 +631,8 @@ HWTEST_F(PackageUnitTest, TestVerifyZipWithCallback, TestSize.Level1) HWTEST_F(PackageUnitTest, TestVerifyZip, TestSize.Level1) { PackageUnitTest test; - EXPECT_EQ(0, test.TestVerifyZip()); + EXPECT_EQ(0, test.TestVerifyZip(PKG_DIGEST_TYPE_SHA384)); + EXPECT_EQ(0, test.TestVerifyZip(PKG_DIGEST_TYPE_SHA256)); } HWTEST_F(PackageUnitTest, TestVerifyLz4, TestSize.Level1) { diff --git a/test/unittest/package/pkg_algo_unittest.cpp b/test/unittest/package/pkg_algo_unittest.cpp index fbab4b1c..43836721 100755 --- a/test/unittest/package/pkg_algo_unittest.cpp +++ b/test/unittest/package/pkg_algo_unittest.cpp @@ -131,7 +131,7 @@ public: return 0; } - int TestSignVerify(int8_t signMethod, std::string privateKey, std::string certName) + int TestSignVerify(int8_t signMethod, std::string privateKey, std::string certName, uint8_t hashType) { PkgBuffer digest(DIGEST_LEN); std::string filePath = TEST_PATH_FROM; @@ -141,7 +141,7 @@ public: // 签名 filePath = TEST_PATH_FROM + privateKey; SignAlgorithm::SignAlgorithmPtr algorithm = PkgAlgorithmFactory::GetSignAlgorithm(filePath, - signMethod, PKG_DIGEST_TYPE_SHA256); + signMethod, hashType); EXPECT_NE(nullptr, algorithm); std::vector signature; size_t signLen = 0; @@ -152,7 +152,7 @@ public: EXPECT_EQ(ret, PKG_INVALID_SIGNATURE); filePath = TEST_PATH_FROM + certName; - algorithm = PkgAlgorithmFactory::GetVerifyAlgorithm(filePath, PKG_DIGEST_TYPE_SHA256); + algorithm = PkgAlgorithmFactory::GetVerifyAlgorithm(filePath, hashType); // 验证 ret = algorithm->SignBuffer(digest, signature, signLen); EXPECT_EQ(ret, PKG_INVALID_SIGNATURE); @@ -229,13 +229,22 @@ HWTEST_F(PkgAlgoUnitTest, TestHash256Digest, TestSize.Level1) HWTEST_F(PkgAlgoUnitTest, TestRsaSignVerify, TestSize.Level1) { PkgAlgoUnitTest test; - EXPECT_EQ(0, test.TestSignVerify(PKG_SIGN_METHOD_RSA, "rsa_private_key2048.pem", "signing_cert.crt")); + EXPECT_EQ(0, test.TestSignVerify(PKG_SIGN_METHOD_RSA, + "rsa_private_key2048.pem", "signing_cert.crt", PKG_DIGEST_TYPE_SHA256)); +} + +HWTEST_F(PkgAlgoUnitTest, TestRsaSignVerify384, TestSize.Level1) +{ + PkgAlgoUnitTest test; + EXPECT_EQ(0, test.TestSignVerify(PKG_SIGN_METHOD_RSA, + "rsa_private_key384.pem", "signing_cert384.crt", PKG_DIGEST_TYPE_SHA384)); } HWTEST_F(PkgAlgoUnitTest, TestEccSignVerify, TestSize.Level1) { PkgAlgoUnitTest test; - EXPECT_EQ(0, test.TestSignVerify(PKG_SIGN_METHOD_ECDSA, "ecc/prime256v1-key.pem", "ecc/signing_cert.crt")); + EXPECT_EQ(0, test.TestSignVerify(PKG_SIGN_METHOD_ECDSA, + "ecc/prime256v1-key.pem", "ecc/signing_cert.crt", PKG_DIGEST_TYPE_SHA256)); } HWTEST_F(PkgAlgoUnitTest, TestEccUserPackage, TestSize.Level1) diff --git a/test/unittest/package/pkg_manager_unittest.cpp b/test/unittest/package/pkg_manager_unittest.cpp index b7143e9f..dcbf120d 100755 --- a/test/unittest/package/pkg_manager_unittest.cpp +++ b/test/unittest/package/pkg_manager_unittest.cpp @@ -137,7 +137,7 @@ public: GetUpgradePkgInfo(pkgInfo, files); std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; - int32_t ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(), &pkgInfo.pkgInfo, files); + int32_t ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(0), &pkgInfo.pkgInfo, files); EXPECT_EQ(ret, PKG_SUCCESS); return 0; } @@ -153,7 +153,7 @@ public: // 修改成错误的路径 files[0].first = "sssssssssss"; - int32_t ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(), &pkgInfo.pkgInfo, files); + int32_t ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(0), &pkgInfo.pkgInfo, files); EXPECT_EQ(ret, PKG_INVALID_FILE); return 0; } @@ -164,7 +164,7 @@ public: std::vector> files; std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; - int32_t ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(), nullptr, files); + int32_t ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(0), nullptr, files); EXPECT_EQ(ret, PKG_INVALID_PARAM); return 0; } @@ -177,7 +177,7 @@ public: } PKG_LOGI("\n\n ************* TestCombinePkgUNpack %s \r\n", testCombinePkgName.c_str()); std::vector components; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(0), components); if (ret != PKG_SUCCESS) { PKG_LOGE("LoadPackage fail ret:%d", ret); return ret; @@ -258,7 +258,7 @@ public: } PKG_LOGI("\n\n ************* TestCombinePkgUNpack %s \r\n", testCombinePkgName.c_str()); std::vector components; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(0), components); if (ret != PKG_SUCCESS) { PKG_LOGI("LoadPackage fail ret:%d", ret); return ret; @@ -297,7 +297,7 @@ public: } PKG_LOGI("\n\n ************* TestCombinePkgUNpack %s \r\n", testCombinePkgName.c_str()); std::vector components; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(0), components); if (ret != PKG_SUCCESS) { PKG_LOGI("LoadPackage fail ret:%d", ret); return ret; @@ -404,7 +404,7 @@ public: std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; files.push_back(std::pair("/qqqqqq", info)); - int ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(), &pkgInfo.pkgInfo, files); + int ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(0), &pkgInfo.pkgInfo, files); EXPECT_EQ(ret, PKG_INVALID_FILE); return 0; } @@ -418,7 +418,7 @@ public: packagePath += testPackageName; uint8_t signMethodIndex = 10; pkgInfo.pkgInfo.signMethod = PKG_SIGN_METHOD_RSA + signMethodIndex; - int ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(), &pkgInfo.pkgInfo, files); + int ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(0), &pkgInfo.pkgInfo, files); EXPECT_NE(ret, 0); return 0; } @@ -440,7 +440,7 @@ public: pkgInfo.pkgType = PKG_PACK_TYPE_GZIP; std::string fileName = TEST_PATH_TO; fileName += testGZipPackageName; - int ret = pkgManager_->CreatePackage(fileName, GetTestPrivateKeyName(), &pkgInfo, files); + int ret = pkgManager_->CreatePackage(fileName, GetTestPrivateKeyName(0), &pkgInfo, files); EXPECT_EQ(ret, PKG_INVALID_FILE); return 0; } @@ -463,7 +463,7 @@ public: pkgInfo.pkgType = PKG_PACK_TYPE_GZIP + pkgTypeIndex; std::string fileName = TEST_PATH_TO; fileName += testGZipPackageName; - int ret = pkgManager_->CreatePackage(fileName, GetTestPrivateKeyName(), &pkgInfo, files); + int ret = pkgManager_->CreatePackage(fileName, GetTestPrivateKeyName(0), &pkgInfo, files); EXPECT_EQ(ret, PKG_INVALID_FILE); return 0; } @@ -487,7 +487,7 @@ public: pkgInfo.pkgType = PKG_PACK_TYPE_ZIP; std::string fileName = TEST_PATH_TO; fileName += testZipPackageName; - int ret = pkgManager_->CreatePackage(fileName, GetTestPrivateKeyName(), &pkgInfo, files); + int ret = pkgManager_->CreatePackage(fileName, GetTestPrivateKeyName(0), &pkgInfo, files); EXPECT_EQ(ret, PKG_INVALID_FILE); return 0; } @@ -499,7 +499,7 @@ public: std::vector components; std::string fileName = TEST_PATH_TO; fileName += "testZipPackageName.aaa"; - int32_t ret = pkgManager_->LoadPackage(fileName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(fileName, GetTestCertName(0), components); EXPECT_EQ(ret, PKG_INVALID_FILE); return 0; } diff --git a/test/unittest/package/pkg_package_unittest.cpp b/test/unittest/package/pkg_package_unittest.cpp index bdd92603..2880e5cd 100755 --- a/test/unittest/package/pkg_package_unittest.cpp +++ b/test/unittest/package/pkg_package_unittest.cpp @@ -38,8 +38,6 @@ namespace { constexpr uint32_t MAX_FILE_NAME = 256; constexpr uint32_t CENTRAL_SIGNATURE = 0x02014b50; constexpr uint32_t END_CENTRAL_SIGNATURE = 0x06054b50; -constexpr uint32_t ZIP_NODE_ID = 100; -constexpr size_t GIANT_NUMBER = 100000; class TestFile : public PkgFile { public: @@ -122,13 +120,14 @@ public: EXPECT_NE(pkgManager_, nullptr); PkgManager::StreamPtr stream = nullptr; std::string packagePath = TEST_PATH_TO; + uint32_t zipNodeId = 100; packagePath += testPackageName; pkgManager_->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read); EXPECT_NE(stream, nullptr); std::unique_ptr file = std::make_unique(pkgManager_, PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_NE(file, nullptr); - std::unique_ptr entry = std::make_unique(file.get(), ZIP_NODE_ID); + std::unique_ptr entry = std::make_unique(file.get(), zipNodeId); EXPECT_NE(entry, nullptr); string name = "TestBigZip"; @@ -162,7 +161,8 @@ public: EXPECT_EQ(ret, 0); WriteLE16(buff.data() + sizeof(CentralDirEntry) + name.length(), 1); WriteLE16(buff.data() + sizeof(CentralDirEntry) + name.length() + offsetHalfWord, offset4Words); - size_t size = UINT_MAX + GIANT_NUMBER; + size_t giantNumber = 100000; + size_t size = UINT_MAX + giantNumber; WriteLE64(buff.data() + sizeof(CentralDirEntry) + name.length() + offsetWord, size); WriteLE64(buff.data() + sizeof(CentralDirEntry) + name.length() + offset3Words, size); size_t decodeLen = 0; diff --git a/test/unittest/package/pkg_test.h b/test/unittest/package/pkg_test.h index 16a72a4d..e650d298 100755 --- a/test/unittest/package/pkg_test.h +++ b/test/unittest/package/pkg_test.h @@ -142,7 +142,7 @@ protected: } int CreateZipPackage(const std::vector &testFileNames, - const std::string packageName, const std::string &base) + const std::string packageName, const std::string &base, int digestMethod) { PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance(); EXPECT_NE(pkgManager, nullptr); @@ -159,9 +159,9 @@ protected: PkgInfo pkgInfo; pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; - pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; + pkgInfo.digestMethod = digestMethod; pkgInfo.pkgType = PKG_PACK_TYPE_ZIP; - int32_t ret = pkgManager->CreatePackage(packageName, GetTestPrivateKeyName(), &pkgInfo, files); + int32_t ret = pkgManager->CreatePackage(packageName, GetTestPrivateKeyName(digestMethod), &pkgInfo, files); EXPECT_EQ(ret, 0); return ret; } diff --git a/test/unittest/test_data/src/rsa_private_key384.pem b/test/unittest/test_data/src/rsa_private_key384.pem new file mode 100755 index 00000000..9ade6de3 --- /dev/null +++ b/test/unittest/test_data/src/rsa_private_key384.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG5QIBAAKCAYEA0mDyEBQc9A/z+la197GMMhFAkL/g1TNnGo5cIm+dclLom4sY +3MDTtxf/GfuNeVdGOIimUb2Zu1XqZaV+HSRh7bggqfwZ9RMgJkHlMpm8JFG9y0Nj +lon+HQdme4jU+p1r4ZycWw2P16PwTBv2pGhd0/yIas909H97nIldyPsfDiO4gxoQ +uVMpeVEK+32j0bFpelZzgn3sQdyXKRNFS8wCt64p3TMFVO1HZaGt+e7UQV6dqQgj +QOUwiEKMdgGI+Day9OGYu0Y5S13adltQKGbwE8J+KNNtTuzWaVZXJzGcNykDSZVi +r/pbVqhbMEPnpsMJ4zMwZY/bL3TYqwG2BbmRb+NJej0Uh7LurHNScxSP0/qEzbkm +tnVtTvIrvVlbLc6r2TebU4fDhFIi3obRGCBBar6epZM7Rz7e0v45MYlWEEyJcUqO +s0zlqccveBO+J4He3bUiHI0fdG2oAfYetgT3Mo/EwH6QEVDcUYazuJTnihDT478k +obZqTwwxRrIOECBrAgMBAAECggGBALR65M80Yg5jLTyDbQJ8t7gwIsLLSbe9rGMU +5CfKtzjftZvS/dZMOpTlqj0BGEKTw7M2T/DqBlu3fioLiqC3mKeWgbcyhpY//SG1 +AEqjpstFsNwTCPmZkn4W3i12mrgRmv5nG5/lh5RImRrCFpq+ylfVWra/GSezwjjt +g56rCN5ZeK5ICzbiCD+CbjiIdaSsXb/NMLUvECMEek2LsbQv5djsOhAA+D7+fHTM ++nLjGAaog/sB9zRyKmuLI/MMqBPA38GT80ufzA9wqjr08luTt+LBhEOWJgCwvn1U +O56SMXcCvBW2eVlXzh4nDTwipihj9+nBn9UXMn/l39tKLupIz1oQEbA7+/1CI3wA +gXK8BkBRbYuulGNZTBBZB9gq8HYy9zUl/RwNqE2p3E0nHhKlQtTPdUVq+z822Q/E +TJMOHzQzBJqj6oii5rRPGmjICXFFfgOVydBo0dYq+/2mMxDjGzpeDOaHQgq06tsj +IesCTyfqTKRrWuYW8IRl34mxoX6OYQKBwQDoKeOjRDkBBrkTRwfMHIYSuBlgAunr +0JG6rtZ3wYSKCweS/OQbviV7EpoVLCAmqjgPLbIIBmxK2+xfH8a/83SesW/Jwd2C +1umJPVu+N8Kwpc+XNeN3Pjwp3DSCsXBNb1rsOBw/vsolKWM5KxqG7qUa/CVtbJO+ +/5r87Rbw6A+cldNR383QeBKsPhdZYD5eh8g5btavV3knfG50TwfL0uNxKfu0l9Oq +jR9C+BC4DsZMBLBlUz/VrAtux8y5nsytibsCgcEA5/p36b7zYqD+2PHviqEVf007 +P7CqL8AZge7fDHi/hgMzSMIt+jgfvO+beNPcadqAeJ26/BZJZpL1lsU7+tUZYB3B +/h3TZp4/JVnT9Y24QB9y1aCLa+vZ60ItaGwOlltGhojIG3/YtslgG80e/4Ob1nMM +y/tSfUlzD2jVUqmUSNtpcTScAs14FAsYv7HRZskNfT11nKuVW5h5zVDmxb27FkK7 +m2lRPWAVHgwrvdAD9F0oUAAoH+Y5SXujYkz/3MERAoHBANIXJiJW2GbvWIfzXUD+ +Bu3ln0DdIiX9pgKTuQzCGFh7Rq1jIGFinrRSzxCdz7JtkzFZHqRYe6L6hVpHfSmy +/DOnSgv/3Z5LMSa6Wc021H3abpLddywvK26OEQ67126beGIPHLEqy+75Fwti0CyO +xOY4iv4MpV7QG8cKHhp/RbFje8m5h5xBLFSmE6cTix0sLqqafLhLph1vYtzpr5pp +Ct0bKuXwBuFtt3540VheNmAQVjg7L6cCe44STFclNv9LhQKBwQDiwsz6+gSyMcxM +x1qv+byo3xb+sDP8T1zfzV/Nsi8N0g0Mn3wQL1Ke/t3MY9T+yG9y+ERy7Vo84YUe +J5j1HeAbO5uJSyB+HEx/t2phi3JDhDpdpv0Ctt8jgGIgxBgSVBEBq61obDWsn/bJ +1l3pyX3JSFeHAhpljCnkM0br8gaYnZpZ5eJnPvCVLy+3GxwlzHzaIvzX9EYg7lCK +Kf4b59Z88Siwx2d5hnW+FImhlzh2Y6XnZe/TFtqDAU/55GjsIvECgcAXmPO1hSlz +nE1Pw5X7AJiF/PjeEYs210Ac1df01mcOa+tDBx+9+m05RjlpZ6bI8AO9606suViB +yPf9DYet+d4cI1FYqQl4B3qXdZl1upYqv4dsLxOztzMIYi7reg0YXVpj2Rhwybzd +onKc9j8KNb55TB1JKHqwvJBhgRpTB6ucxzJYLXal60O6R8Png56S51O3rz3qWh9J +Z48aTa06SIHhDyzDslYddTQ2QpRqWbkRcgOkUY+ZfCpDXjp4YU03Yzk= +-----END RSA PRIVATE KEY----- diff --git a/test/unittest/test_data/src/signing_cert384.crt b/test/unittest/test_data/src/signing_cert384.crt new file mode 100755 index 00000000..73e145b0 --- /dev/null +++ b/test/unittest/test_data/src/signing_cert384.crt @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEazCCAtOgAwIBAgIUWG5lzXTJz5lQ1X2BClMyzltqBhEwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTEwMjgxMTI2MjVaFw0yMjEw +MjgxMTI2MjVaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggGiMA0GCSqGSIb3DQEB +AQUAA4IBjwAwggGKAoIBgQDSYPIQFBz0D/P6VrX3sYwyEUCQv+DVM2cajlwib51y +UuibixjcwNO3F/8Z+415V0Y4iKZRvZm7VeplpX4dJGHtuCCp/Bn1EyAmQeUymbwk +Ub3LQ2OWif4dB2Z7iNT6nWvhnJxbDY/Xo/BMG/akaF3T/Ihqz3T0f3uciV3I+x8O +I7iDGhC5Uyl5UQr7faPRsWl6VnOCfexB3JcpE0VLzAK3rindMwVU7Udloa357tRB +Xp2pCCNA5TCIQox2AYj4NrL04Zi7RjlLXdp2W1AoZvATwn4o021O7NZpVlcnMZw3 +KQNJlWKv+ltWqFswQ+emwwnjMzBlj9svdNirAbYFuZFv40l6PRSHsu6sc1JzFI/T ++oTNuSa2dW1O8iu9WVstzqvZN5tTh8OEUiLehtEYIEFqvp6lkztHPt7S/jkxiVYQ +TIlxSo6zTOWpxy94E74ngd7dtSIcjR90bagB9h62BPcyj8TAfpARUNxRhrO4lOeK +ENPjvyShtmpPDDFGsg4QIGsCAwEAAaNTMFEwHQYDVR0OBBYEFMsre/vRH2jpNO5p +K2bpd6a2vxZMMB8GA1UdIwQYMBaAFMsre/vRH2jpNO5pK2bpd6a2vxZMMA8GA1Ud +EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggGBAKSsEIKEy+EDSUT6yoyR8PxK +omQh7BjoLnpBfDXOJZedBKvIyzFh3I5v93xvLknfPWqKrEwnjQorqfDKa6rIaj/o +UjhPFbzBdrB/EF/IYX1+g1t+fxFQLnu0twRr4F3PK/owno3bwE4A09ZBLub0lNws +NYacSTbrmMNaYMZfqhKWzNMkh+9ICx0bxmtRpBJlVyj6agQ9QQQoTz66qsTexe5e +0H4mSkJ0fIQG53jeHPMeOVb2A9Z558OtzlSiXz7H3LX1ca2i6Hn9rjH1axM6wChj +qeaYI9tVXDpXqT/O6tsMFzJ9Lksq3deguaIHx93kCSFsKVvEpYa3SeHcXnA48AaD +NwxS1fKhD/KEhFtBQ8sq6sPzY51hUJirF+pfRk9VBvQ+E6cGVDOgoDn79tPWjFN9 +KI9388+kVxYzQ4OuoxZC7HvrJUsHYZXDgtN7cp5vKcM9Y0rzkUAQh2BddBClAMHP +2LK6qOq0eMjnkeSl7L6f96B7/8ZW3mBT4CDaqcdYvA== +-----END CERTIFICATE----- diff --git a/test/unittest/test_data/updater/test.img b/test/unittest/test_data/updater/test.img new file mode 100755 index 00000000..ab7bd1d2 --- /dev/null +++ b/test/unittest/test_data/updater/test.img @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + test flashd \ No newline at end of file diff --git a/test/unittest/test_data/updater/updater.zip b/test/unittest/test_data/updater/updater.zip index 0ecd1ceb..eeae4e4b 100755 --- a/test/unittest/test_data/updater/updater.zip +++ b/test/unittest/test_data/updater/updater.zip @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14357f75170e22c61470c2cd0fe73ee4f4b1a3396ac5d386433e76c0e54d0cd9 -size 13387850 +oid sha256:ab06b6f2a1dbb8563f7da65e79a70a6550620428f7704cca6159e56481d4d1c1 +size 1785615 diff --git a/test/unittest/unittest_comm.h b/test/unittest/unittest_comm.h index 2c396bd0..5f75ad3b 100755 --- a/test/unittest/unittest_comm.h +++ b/test/unittest/unittest_comm.h @@ -23,21 +23,30 @@ #include #include +#include "package/package.h" + const std::string TEST_PATH_FROM = "/data/updater/src/"; const std::string TEST_PATH_TO = "/data/updater/dst/"; -inline std::string GetTestPrivateKeyName() +inline std::string GetTestPrivateKeyName(int type = 0) { std::string name = TEST_PATH_FROM; - name += "rsa_private_key2048.pem"; + if (type != PKG_DIGEST_TYPE_SHA384) { + name += "rsa_private_key2048.pem"; + } else { + name += "rsa_private_key384.pem"; + } return name; } -inline std::string GetTestCertName() +inline std::string GetTestCertName(int type = 0) { std::string name = TEST_PATH_FROM; - name += "signing_cert.crt"; + if (type != PKG_DIGEST_TYPE_SHA384) { + name += "signing_cert.crt"; + } else { + name += "signing_cert384.crt"; + } return name; } - #endif // UNITTEST_COMM diff --git a/test/unittest/updater_binary/updater_binary_unittest.cpp b/test/unittest/updater_binary/updater_binary_unittest.cpp index 65975e54..770adb21 100755 --- a/test/unittest/updater_binary/updater_binary_unittest.cpp +++ b/test/unittest/updater_binary/updater_binary_unittest.cpp @@ -112,25 +112,26 @@ protected: { int32_t ret; int32_t updateFileVersion = 1000; - int fileNameIndex = 3; - uint8_t componentType = 22; + PKG_LOGI("\n\n ************* CreatePackageBin %s \r\n", testPackageName.c_str()); UpgradePkgInfoExt pkgInfo; - ComponentInfoExt *comp = (ComponentInfoExt*)malloc( - sizeof(ComponentInfoExt) * (testFileNames_.size() + fileNameIndex)); - if (comp == nullptr) { - return -1; - } // C API, Cannot use c++ string class. pkgInfo.softwareVersion = strdup("100.100.100.100"); pkgInfo.date = strdup("2021-02-02"); pkgInfo.time = strdup("21:23:49"); pkgInfo.productUpdateId = strdup("555.555.100.555"); + int fileNameIndex = 3; + uint8_t componentType = 22; pkgInfo.entryCount = testFileNames_.size() + fileNameIndex; pkgInfo.updateFileVersion = updateFileVersion; pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo.pkgType = PKG_PACK_TYPE_UPGRADE; + ComponentInfoExt *comp = (ComponentInfoExt*)malloc( + sizeof(ComponentInfoExt) * (testFileNames_.size() + fileNameIndex)); + if (comp == nullptr) { + return -1; + } for (size_t i = 0; i < testFileNames_.size(); i++) { BuildCompnentInfo(comp[i], testFileNames_[i], testFileNames_[i], componentType); } diff --git a/test/unittest/updater_main_test/updater_main_unittest.cpp b/test/unittest/updater_main_test/updater_main_unittest.cpp index a3e33c78..743278c8 100755 --- a/test/unittest/updater_main_test/updater_main_unittest.cpp +++ b/test/unittest/updater_main_test/updater_main_unittest.cpp @@ -56,7 +56,7 @@ void UpdaterMainUnitTest::SetUpTestCase(void) if (MountForPath("/data") != 0) { cout << "MountForPath failed" << endl; } - PostUpdater(); + PostUpdater(true); } // end @@ -89,7 +89,7 @@ HWTEST_F(UpdaterMainUnitTest, updater_main_test_001, TestSize.Level1) std::vector args = ParseParams(argc, argv); EXPECT_EQ(args.size(), static_cast(argc)); - PostUpdater(); + PostUpdater(true); delete argv[0]; delete []argv; } @@ -106,7 +106,7 @@ HWTEST_F(UpdaterMainUnitTest, updater_main_test_002, TestSize.Level1) int fRet = FactoryReset(USER_WIPE_DATA, "/misc/factory_test"); EXPECT_EQ(fRet, 0); - PostUpdater(); + PostUpdater(true); } HWTEST_F(UpdaterMainUnitTest, updater_main_test_003, TestSize.Level1) -- Gitee From c5efa00b31e8aec4777aaeeab79ab4b68ea99f19 Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Fri, 5 Nov 2021 16:26:52 +0800 Subject: [PATCH 02/15] fix codestyle Signed-off-by: xionglei6 --- services/diffpatch/diff/blocks_diff.cpp | 4 ++-- .../applypatch_test/imagepatch_unittest.h | 4 +--- test/unittest/package/pkg_package_unittest.cpp | 7 ++++--- .../updater_binary/updater_binary_unittest.cpp | 15 +++++++-------- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/services/diffpatch/diff/blocks_diff.cpp b/services/diffpatch/diff/blocks_diff.cpp index d579dbd9..2a68f28c 100644 --- a/services/diffpatch/diff/blocks_diff.cpp +++ b/services/diffpatch/diff/blocks_diff.cpp @@ -237,7 +237,7 @@ void BlocksDiff::ComputeLength(const BlockBuffer &newInfo, int64_t i = 0; int64_t s = 0; int64_t tmp = 0; - for (; ((lastScan_ + i) < currentOffset_) && ((lastPos_ + i) < static_cast(oldInfo.length)); ) { + for (; ((lastScan_ + i) < currentOffset_) && ((lastPos_ + i) < static_cast(oldInfo.length));) { if (oldInfo.buffer[lastPos_ + i] == newInfo.buffer[lastScan_ + i]) { s++; } @@ -413,7 +413,7 @@ void SuffixArray::Init(const BlockBuffer &oldInfo) DataType len = 0; for (h = 1; suffixArray_[0] != -(static_cast(oldInfo.length) + 1); h += h) { len = 0; - for (i = 0; i < (static_cast(oldInfo.length) + 1); ) { + for (i = 0; i < (static_cast(oldInfo.length) + 1);) { if (suffixArray_[i] < 0) { len -= suffixArray_[i]; i -= suffixArray_[i]; diff --git a/test/unittest/applypatch_test/imagepatch_unittest.h b/test/unittest/applypatch_test/imagepatch_unittest.h index 6da5f553..e4cdc358 100755 --- a/test/unittest/applypatch_test/imagepatch_unittest.h +++ b/test/unittest/applypatch_test/imagepatch_unittest.h @@ -77,9 +77,7 @@ public: int fd = open(target.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY, mode); EXPECT_GE(fd, 0); BlockSet targetBlk; - targetBlk.ParserAndInsert({ - "2", "0", "1" - }); + targetBlk.ParserAndInsert({"2", "0", "1"}); std::unique_ptr writer = std::make_unique(fd, targetBlk); std::vector empty; int32_t ret = updatepatch::UpdatePatch::ApplyImagePatch(param, empty, diff --git a/test/unittest/package/pkg_package_unittest.cpp b/test/unittest/package/pkg_package_unittest.cpp index 2880e5cd..919e0fe6 100755 --- a/test/unittest/package/pkg_package_unittest.cpp +++ b/test/unittest/package/pkg_package_unittest.cpp @@ -38,6 +38,8 @@ namespace { constexpr uint32_t MAX_FILE_NAME = 256; constexpr uint32_t CENTRAL_SIGNATURE = 0x02014b50; constexpr uint32_t END_CENTRAL_SIGNATURE = 0x06054b50; +constexpr uint32_t ZIP_NODE_ID = 100; +constexpr size_t GIANT_NUMBER = 100000; class TestFile : public PkgFile { public: @@ -127,7 +129,7 @@ public: std::unique_ptr file = std::make_unique(pkgManager_, PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_NE(file, nullptr); - std::unique_ptr entry = std::make_unique(file.get(), zipNodeId); + std::unique_ptr entry = std::make_unique(file.get(), ZIP_NODE_ID); EXPECT_NE(entry, nullptr); string name = "TestBigZip"; @@ -161,8 +163,7 @@ public: EXPECT_EQ(ret, 0); WriteLE16(buff.data() + sizeof(CentralDirEntry) + name.length(), 1); WriteLE16(buff.data() + sizeof(CentralDirEntry) + name.length() + offsetHalfWord, offset4Words); - size_t giantNumber = 100000; - size_t size = UINT_MAX + giantNumber; + size_t size = UINT_MAX + GIANT_NUMBER; WriteLE64(buff.data() + sizeof(CentralDirEntry) + name.length() + offsetWord, size); WriteLE64(buff.data() + sizeof(CentralDirEntry) + name.length() + offset3Words, size); size_t decodeLen = 0; diff --git a/test/unittest/updater_binary/updater_binary_unittest.cpp b/test/unittest/updater_binary/updater_binary_unittest.cpp index 770adb21..65975e54 100755 --- a/test/unittest/updater_binary/updater_binary_unittest.cpp +++ b/test/unittest/updater_binary/updater_binary_unittest.cpp @@ -112,26 +112,25 @@ protected: { int32_t ret; int32_t updateFileVersion = 1000; - PKG_LOGI("\n\n ************* CreatePackageBin %s \r\n", testPackageName.c_str()); + int fileNameIndex = 3; + uint8_t componentType = 22; UpgradePkgInfoExt pkgInfo; + ComponentInfoExt *comp = (ComponentInfoExt*)malloc( + sizeof(ComponentInfoExt) * (testFileNames_.size() + fileNameIndex)); + if (comp == nullptr) { + return -1; + } // C API, Cannot use c++ string class. pkgInfo.softwareVersion = strdup("100.100.100.100"); pkgInfo.date = strdup("2021-02-02"); pkgInfo.time = strdup("21:23:49"); pkgInfo.productUpdateId = strdup("555.555.100.555"); - int fileNameIndex = 3; - uint8_t componentType = 22; pkgInfo.entryCount = testFileNames_.size() + fileNameIndex; pkgInfo.updateFileVersion = updateFileVersion; pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo.pkgType = PKG_PACK_TYPE_UPGRADE; - ComponentInfoExt *comp = (ComponentInfoExt*)malloc( - sizeof(ComponentInfoExt) * (testFileNames_.size() + fileNameIndex)); - if (comp == nullptr) { - return -1; - } for (size_t i = 0; i < testFileNames_.size(); i++) { BuildCompnentInfo(comp[i], testFileNames_[i], testFileNames_[i], componentType); } -- Gitee From 9887b959d587b2d87a8a3c8ee43adb973f11db50 Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Fri, 5 Nov 2021 16:30:32 +0800 Subject: [PATCH 03/15] fix codestyle Signed-off-by: xionglei6 --- test/unittest/package/pkg_package_unittest.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unittest/package/pkg_package_unittest.cpp b/test/unittest/package/pkg_package_unittest.cpp index 919e0fe6..bdd92603 100755 --- a/test/unittest/package/pkg_package_unittest.cpp +++ b/test/unittest/package/pkg_package_unittest.cpp @@ -122,7 +122,6 @@ public: EXPECT_NE(pkgManager_, nullptr); PkgManager::StreamPtr stream = nullptr; std::string packagePath = TEST_PATH_TO; - uint32_t zipNodeId = 100; packagePath += testPackageName; pkgManager_->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read); EXPECT_NE(stream, nullptr); -- Gitee From 529ca50e97a65594224a8dde242074e5296b97cf Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Fri, 5 Nov 2021 19:22:58 +0800 Subject: [PATCH 04/15] updater: fix bugs Signed-off-by: xionglei6 --- interfaces/kits/updaterkits/updaterkits.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interfaces/kits/updaterkits/updaterkits.cpp b/interfaces/kits/updaterkits/updaterkits.cpp index 60ac4c5e..bfc2a6a4 100755 --- a/interfaces/kits/updaterkits/updaterkits.cpp +++ b/interfaces/kits/updaterkits/updaterkits.cpp @@ -39,7 +39,7 @@ static bool WriteToMiscAndRebootToUpdater(const std::string &miscFile, int32_t propertyMaxSize = 92; char updateCmd[propertyMaxSize]; void(snprintf_s(updateCmd, propertyMaxSize, propertyMaxSize - 1, "reboot,updater:%s", updateMsg.update)); - bool bRet = OHOS::system::SetParameter("sys.powerctrl", updateCmd); + bool bRet = OHOS::system::SetParameter("ohos.startup.powerctrl", updateCmd); if (!bRet) { std::cout << "WriteToMiscAndRebootToUpdater SetParameter failed, errno: " << errno << std::endl; return false; -- Gitee From ecd1e2b595e0999f58fbe1afb26dc29c513a59e4 Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Fri, 5 Nov 2021 19:48:30 +0800 Subject: [PATCH 05/15] updater: fix test data Signed-off-by: xionglei6 --- test/unittest/test_data/updater/updater.zip | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unittest/test_data/updater/updater.zip b/test/unittest/test_data/updater/updater.zip index eeae4e4b..0ecd1ceb 100755 --- a/test/unittest/test_data/updater/updater.zip +++ b/test/unittest/test_data/updater/updater.zip @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab06b6f2a1dbb8563f7da65e79a70a6550620428f7704cca6159e56481d4d1c1 -size 1785615 +oid sha256:14357f75170e22c61470c2cd0fe73ee4f4b1a3396ac5d386433e76c0e54d0cd9 +size 13387850 -- Gitee From 56455d1fd076b5494bb50651d3377ebbb7123f29 Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Fri, 5 Nov 2021 20:10:58 +0800 Subject: [PATCH 06/15] updater: fix bugs Signed-off-by: xionglei6 --- services/flashd/host/host_updater.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/flashd/host/host_updater.cpp b/services/flashd/host/host_updater.cpp index 641af6ac..f2c610ac 100755 --- a/services/flashd/host/host_updater.cpp +++ b/services/flashd/host/host_updater.cpp @@ -302,7 +302,6 @@ bool HostUpdater::CheckMatchUpdate(const std::string &input, bool HostUpdater::ConfirmCommand(const string &commandIn) { - bool needConfirm = false; std::string tip = ""; WRITE_LOG(LOG_DEBUG, "ConfirmCommand \"%s\" \n", commandIn.c_str()); @@ -348,4 +347,4 @@ bool HostUpdater::ConfirmCommand(const string &commandIn) } while (1); return true; } -} // namespace Hdc \ No newline at end of file +} // namespace Hdc -- Gitee From 88cb15b59ffe716bf6d8feaf384ae475fdb215bd Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Mon, 8 Nov 2021 11:03:29 +0800 Subject: [PATCH 07/15] updater: fix flashed Signed-off-by: xionglei6 --- services/flashd/flash_service.cpp | 17 +++++++++++++---- services/flashd/host/host_updater.cpp | 2 +- services/include/flashd/flashd.h | 12 ++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/services/flashd/flash_service.cpp b/services/flashd/flash_service.cpp index 4b49ef7e..a1004b6f 100755 --- a/services/flashd/flash_service.cpp +++ b/services/flashd/flash_service.cpp @@ -214,7 +214,7 @@ PartitionPtr FlashService::GetPartition(const std::string &partition) const { const std::string partName = GetPartNameByAlias(partition); for (auto part : partitions_) { - if (partName.compare(part->GetPartitionName()) == 0) { + if (strcmp(partName.c_str(), part->GetPartitionName().c_str()) == 0) { return part; } } @@ -431,7 +431,7 @@ const std::string FlashService::GetPartNameByAlias(const std::string &alias) }; for (auto iter = partNameMap.begin(); iter != partNameMap.end(); iter++) { for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); iter2++) { - if (*iter2 == alias) { + if (strcmp(alias.c_str(), (*iter2).c_str()) == 0) { return iter->first; } } @@ -461,7 +461,7 @@ static std::string GetValueFromParam(const std::vector ¶ms, { std::string ret = defValue; for (size_t i = 0; i < params.size(); i++) { - if (paramType.compare(params[i]) == 0) { + if (strcmp(paramType.c_str(), params[i].c_str()) == 0) { if (i < (params.size() - 1)) { ret = params[i + 1]; } else { @@ -476,7 +476,7 @@ static bool FilterParam(const std::string ¶m, const std::vector { auto iter = filter.begin(); while (iter != filter.end()) { - if (param.compare(*iter) == 0) { + if (strcmp(param.c_str(), (*iter).c_str()) == 0) { return true; } iter++; @@ -632,4 +632,13 @@ int DoUpdaterFinish(FlashHandle handle, uint8_t type, const std::string &partiti g_flashdRunning = false; return 0; } + +int SetParameter(const char *key, const char *value) +{ + std::string sKey = key; + std::string sValue = value; + std::string sBuf = "param set " + sKey + " " + value; + system(sBuf.c_str()); + return 0; +} } // namespace flashd diff --git a/services/flashd/host/host_updater.cpp b/services/flashd/host/host_updater.cpp index f2c610ac..6a11cb3f 100755 --- a/services/flashd/host/host_updater.cpp +++ b/services/flashd/host/host_updater.cpp @@ -277,7 +277,7 @@ bool HostUpdater::CheckMatchUpdate(const std::string &input, bJumpDo = true; return true; } - int cmdLen = updateCmd.size(); + size_t cmdLen = updateCmd.size(); if (!strncmp(input.c_str(), updateCmd.c_str(), updateCmd.size())) { cmdFlag = CMD_UPDATER_UPDATE_INIT; cmdLen = updateCmd.size(); diff --git a/services/include/flashd/flashd.h b/services/include/flashd/flashd.h index 8d46b976..13af8557 100755 --- a/services/include/flashd/flashd.h +++ b/services/include/flashd/flashd.h @@ -67,5 +67,17 @@ int CreateFlashInstance(FlashHandle *handle, std::string &errorMsg, ProgressFunc int DoUpdaterPrepare(FlashHandle handle, uint8_t type, const std::string &cmdParam, std::string &filePath); int DoUpdaterFlash(FlashHandle handle, uint8_t type, const std::string &cmdParam, const std::string &filePath); int DoUpdaterFinish(FlashHandle handle, uint8_t type, const std::string &partition); + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +int SetParameter(const char *key, const char *value); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif } // namespace flashd #endif /* UPDATER_FLASHING_H */ -- Gitee From d24f51e87a7b9e3179f10de2d6a13f4c53d0d3ec Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Wed, 10 Nov 2021 19:33:03 +0800 Subject: [PATCH 08/15] flashd: fix cmd for updater_reboot Signed-off-by: xionglei6 --- services/diffpatch/diff/blocks_diff.cpp | 4 +- services/diffpatch/diff/blocks_diff.h | 4 +- services/flashd/flash_service.cpp | 3 +- services/flashd/host/host_updater.cpp | 60 +++++--- services/flashd/host/host_updater.h | 13 +- services/main.cpp | 2 + services/updater_binary/main.cpp | 3 +- test/unittest/BUILD.gn | 4 +- .../applypatch_test/imagepatch_unittest.h | 4 +- .../flashd_test/flash_host_unittest.cpp | 130 +++++++++++++++--- .../flashd_test/flash_service_unittest.cpp | 6 +- .../unittest/package/pkg_package_unittest.cpp | 8 +- test/unittest/test_data/updater/updater.zip | 4 +- .../updater_binary_unittest.cpp | 18 ++- utils/updater_reboot.cpp | 8 +- utils/utils.cpp | 2 +- 16 files changed, 187 insertions(+), 86 deletions(-) diff --git a/services/diffpatch/diff/blocks_diff.cpp b/services/diffpatch/diff/blocks_diff.cpp index 2a68f28c..d579dbd9 100644 --- a/services/diffpatch/diff/blocks_diff.cpp +++ b/services/diffpatch/diff/blocks_diff.cpp @@ -237,7 +237,7 @@ void BlocksDiff::ComputeLength(const BlockBuffer &newInfo, int64_t i = 0; int64_t s = 0; int64_t tmp = 0; - for (; ((lastScan_ + i) < currentOffset_) && ((lastPos_ + i) < static_cast(oldInfo.length));) { + for (; ((lastScan_ + i) < currentOffset_) && ((lastPos_ + i) < static_cast(oldInfo.length)); ) { if (oldInfo.buffer[lastPos_ + i] == newInfo.buffer[lastScan_ + i]) { s++; } @@ -413,7 +413,7 @@ void SuffixArray::Init(const BlockBuffer &oldInfo) DataType len = 0; for (h = 1; suffixArray_[0] != -(static_cast(oldInfo.length) + 1); h += h) { len = 0; - for (i = 0; i < (static_cast(oldInfo.length) + 1);) { + for (i = 0; i < (static_cast(oldInfo.length) + 1); ) { if (suffixArray_[i] < 0) { len -= suffixArray_[i]; i -= suffixArray_[i]; diff --git a/services/diffpatch/diff/blocks_diff.h b/services/diffpatch/diff/blocks_diff.h index dc682eac..5dd76fa9 100644 --- a/services/diffpatch/diff/blocks_diff.h +++ b/services/diffpatch/diff/blocks_diff.h @@ -89,7 +89,7 @@ public: private: std::unique_ptr CreateBZip2Adapter(size_t patchOffset) override; int32_t WritePatchHeader(int64_t controlSize, - int64_t diffDataSize, int64_t newSize, size_t &patchOffset) override; + int64_t diffDataSize, int64_t newSize, size_t &headerLen) override; std::fstream &stream_; size_t offset_ { 0 }; }; @@ -102,7 +102,7 @@ public: private: std::unique_ptr CreateBZip2Adapter(size_t patchOffset) override; int32_t WritePatchHeader(int64_t controlSize, - int64_t diffDataSize, int64_t newSize, size_t &patchOffset) override; + int64_t diffDataSize, int64_t newSize, size_t &headerLen) override; std::vector &patchData_; size_t offset_ { 0 }; }; diff --git a/services/flashd/flash_service.cpp b/services/flashd/flash_service.cpp index a1004b6f..c5050ba0 100755 --- a/services/flashd/flash_service.cpp +++ b/services/flashd/flash_service.cpp @@ -557,7 +557,8 @@ int DoUpdaterPrepare(FlashHandle handle, uint8_t type, const std::string &cmdPar return FLASHING_INVALID_SPACE, "Failed to mount data paratition for %s", filePath.c_str()); ret = flash->DoResizeParatiton(root, MIN_BLOCKS_FOR_UPDATE); - FLASHING_CHECK(ret == 0, g_flashdRunning = false; return ret, "Failed to resize partition"); + FLASHING_CHECK(ret == 0, g_flashdRunning = false; + return ret, "Failed to resize partition"); if (access(FLASHD_FILE_PATH.c_str(), F_OK) == -1) { mkdir(FLASHD_FILE_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); } diff --git a/services/flashd/host/host_updater.cpp b/services/flashd/host/host_updater.cpp index 6a11cb3f..00beb0f8 100755 --- a/services/flashd/host/host_updater.cpp +++ b/services/flashd/host/host_updater.cpp @@ -48,7 +48,7 @@ bool HostUpdater::BeginTransfer(CtxFile &context, { int argc = 0; char **argv = Base::SplitCommandToArgs(payload, &argc); - FLASHHOST_CHECK(!(argv == nullptr || argc < minParam || fileIndex >= argc), delete[]((char *)argv); + HOSTUPDATER_CHECK(!(argv == nullptr || argc < minParam || fileIndex >= argc), delete[]((char *)argv); return false, "Invalid param for cmd \"%s\"", function.c_str()); int maxParam = minParam; @@ -56,7 +56,7 @@ bool HostUpdater::BeginTransfer(CtxFile &context, if (force) { maxParam += 1; } - FLASHHOST_CHECK(argc == maxParam, delete[]((char *)argv); + HOSTUPDATER_CHECK(argc == maxParam, delete[]((char *)argv); return false, "Invalid param for cmd \"%s\" %d", function.c_str(), maxParam); context.transferConfig.functionName = function; @@ -71,11 +71,11 @@ bool HostUpdater::BeginTransfer(CtxFile &context, context.transferConfig.compressType = COMPRESS_NONE; } else if (MatchPackageExtendName(context.localPath, ".bin")) { const char *part = strstr(payload, "fastboot"); - FLASHHOST_CHECK(part != nullptr, delete[]((char *)argv); + HOSTUPDATER_CHECK(part != nullptr, delete[]((char *)argv); return false, "Invalid image %s for cmd \"%s\"", context.localPath.c_str(), function.c_str()); context.transferConfig.compressType = COMPRESS_NONE; } else { - FLASHHOST_CHECK((MatchPackageExtendName(context.localPath, ".zip") || + HOSTUPDATER_CHECK((MatchPackageExtendName(context.localPath, ".zip") || MatchPackageExtendName(context.localPath, ".lz4") || MatchPackageExtendName(context.localPath, ".gz2")), delete[]((char *)argv); return false, @@ -86,7 +86,7 @@ bool HostUpdater::BeginTransfer(CtxFile &context, context.transferConfig.functionName.c_str(), context.localPath.c_str(), payload); // check path bool ret = Base::CheckDirectoryOrPath(context.localPath.c_str(), true, true); - FLASHHOST_CHECK(ret, delete[]((char *)argv); + HOSTUPDATER_CHECK(ret, delete[]((char *)argv); return false, "Invaid path \"%s\" for cmd \"%s\"", context.localPath.c_str(), function.c_str()); context.taskQueue.push_back(context.localPath); @@ -134,9 +134,9 @@ bool HostUpdater::CheckCmd(const std::string &function, const char *payload, int { int argc = 0; char **argv = Base::SplitCommandToArgs(payload, &argc); - FLASHHOST_CHECK(argv != nullptr, return false, "Can not parser cmd \"%s\"", function.c_str()); + HOSTUPDATER_CHECK(argv != nullptr, return false, "Can not parser cmd \"%s\"", function.c_str()); delete[]((char *)argv); - FLASHHOST_CHECK(argc >= param, return false, "Invalid param for cmd \"%s\" %d", function.c_str(), argc); + HOSTUPDATER_CHECK(argc >= param, return false, "Invalid param for cmd \"%s\" %d", function.c_str(), argc); WRITE_LOG(LOG_DEBUG, "CheckCmd command: %s ", payload); int maxParam = param; @@ -147,7 +147,7 @@ bool HostUpdater::CheckCmd(const std::string &function, const char *payload, int maxParam += 1; maxParam += 1; } - FLASHHOST_CHECK(argc == maxParam, return false, + HOSTUPDATER_CHECK(argc == maxParam, return false, "Invalid param for cmd \"%s\" %d %d", function.c_str(), argc, maxParam); return true; } @@ -165,7 +165,7 @@ bool HostUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, cons switch (command) { case CMD_UPDATER_BEGIN: { std::string s(" Processing: 0%%"); - bSendProgress = true; + sendProgress = true; SendRawData(reinterpret_cast(s.data()), s.size()); break; } @@ -208,7 +208,7 @@ bool HostUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, cons void HostUpdater::ProcessProgress(uint32_t percentage) { - if (!bSendProgress) { + if (!sendProgress) { return; } std::string backStr = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"; @@ -219,24 +219,24 @@ void HostUpdater::ProcessProgress(uint32_t percentage) if (percentage == PERCENT_CLEAR) { // clear SendRawData(reinterpret_cast(backStr.data()), backStr.size()); SendRawData(reinterpret_cast(breakStr.data()), breakStr.size()); - bSendProgress = false; + sendProgress = false; return; } int len = sprintf_s(buffer.data(), buffer.size() - 1, "%s Processing: %3d%%", backStr.c_str(), percentage); - FLASHHOST_CHECK(len > 0, return, "Failed to format progress info "); + HOSTUPDATER_CHECK(len > 0, return, "Failed to format progress info "); SendRawData(reinterpret_cast(buffer.data()), len); if (percentage == PERCENT_FINISH) { SendRawData(reinterpret_cast(breakStr.data()), breakStr.size()); - bSendProgress = false; + sendProgress = false; } } bool HostUpdater::CheckUpdateContinue(const uint16_t command, const uint8_t *payload, int payloadSize) { - FLASHHOST_CHECK(static_cast(payloadSize) >= sizeof(uint16_t), + HOSTUPDATER_CHECK(static_cast(payloadSize) >= sizeof(uint16_t), return false, "Failed to check payload size %d ", payloadSize); MessageLevel level = (MessageLevel)payload[1]; - if ((level == MSG_OK) && bSendProgress) { + if ((level == MSG_OK) && sendProgress) { ProcessProgress(PERCENT_FINISH); } std::string info((char*)(payload + sizeof(uint16_t)), payloadSize - sizeof(uint16_t)); @@ -256,8 +256,7 @@ bool HostUpdater::CheckUpdateContinue(const uint16_t command, const uint8_t *pay std::string HostUpdater::GetFlashdHelp() { - string help; - help = "\n---------------------------------flash commands:-------------------------------------\n" + string help = "\n---------------------------------flash commands:-------------------------------------\n" "flash commands:\n" " target boot [-flashd] - Reboot the device or boot into flashd\n" " update packagename - Update system by package\n" @@ -300,13 +299,22 @@ bool HostUpdater::CheckMatchUpdate(const std::string &input, return true; } -bool HostUpdater::ConfirmCommand(const string &commandIn) +#ifdef UPDATER_UT +static std::string g_input = "yes"; +void HostUpdater::SetInput(const std::string &input) +{ + g_input = input; +} +#endif +bool HostUpdater::ConfirmCommand(const string &commandIn, bool &closeInput) { std::string tip = ""; WRITE_LOG(LOG_DEBUG, "ConfirmCommand \"%s\" \n", commandIn.c_str()); - - if (!strncmp(commandIn.c_str(), flashCmd.c_str(), flashCmd.size())) { + if (!strncmp(commandIn.c_str(), updateCmd.c_str(), updateCmd.size())) { + closeInput = true; + } else if (!strncmp(commandIn.c_str(), flashCmd.c_str(), flashCmd.size())) { tip = "Confirm flash partition"; + closeInput = true; } else if (!strncmp(commandIn.c_str(), eraseCmd.c_str(), eraseCmd.size())) { tip = "Confirm erase partition"; } else if (!strncmp(commandIn.c_str(), formatCmd.c_str(), formatCmd.size())) { @@ -320,13 +328,19 @@ bool HostUpdater::ConfirmCommand(const string &commandIn) return true; } const size_t minLen = strlen("yes"); + int retryCount = 0; do { printf(" %s ? (Yes/No) ", tip.c_str()); fflush(stdin); std::string info = {}; size_t i = 0; while (1) { +#ifndef UPDATER_UT char c = getchar(); +#else + char c = '\n'; + info = g_input; +#endif if (c == '\r' || c == '\n') { break; } @@ -344,7 +358,11 @@ bool HostUpdater::ConfirmCommand(const string &commandIn) if (info == "y" || info == "yes") { return true; } - } while (1); + retryCount++; + } while (retryCount < 3); // 3 retry max count + if (retryCount >= 3) { // 3 retry max count + return false; + } return true; } } // namespace Hdc diff --git a/services/flashd/host/host_updater.h b/services/flashd/host/host_updater.h index 9329419a..2e627782 100755 --- a/services/flashd/host/host_updater.h +++ b/services/flashd/host/host_updater.h @@ -18,15 +18,11 @@ #include "transfer.h" namespace Hdc { -#define FLASHHOST_CHECK(retCode, exper, ...) \ +#define HOSTUPDATER_CHECK(retCode, exper, ...) \ if (!(retCode)) { \ LogMsg(MSG_FAIL, __VA_ARGS__); \ exper; \ } -#define FLASHHOST_ONLY_CHECK(retCode, exper) \ - if (!(retCode)) { \ - exper; \ - } class HostUpdater : public HdcTransferBase { public: @@ -36,16 +32,16 @@ public: static std::string GetFlashdHelp(); static bool CheckMatchUpdate(const std::string &input, std::string &stringError, uint16_t &cmdFlag, bool &bJumpDo); - static bool ConfirmCommand(const string &commandIn); + static bool ConfirmCommand(const string &commandIn, bool &closeInput); #ifdef UPDATER_UT void OpenFile() { CheckMaster(&ctxNow); } + static void SetInput(const std::string &input); #endif private: void CheckMaster(CtxFile *context) override; - bool BeginTransfer(CtxFile &context, const std::string &function, const char *payload, int minParam, int fileIndex); bool CheckUpdateContinue(const uint16_t command, const uint8_t *payload, int payloadSize); @@ -71,8 +67,7 @@ private: #endif private: bool CheckCmd(const std::string &function, const char *payload, int param); - - bool bSendProgress = false; + bool sendProgress = false; }; } #endif \ No newline at end of file diff --git a/services/main.cpp b/services/main.cpp index 6f5d5fe9..d6a5e6da 100644 --- a/services/main.cpp +++ b/services/main.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include "fs_manager/mount.h" +#include "fs_manager/fs_manager_log.h" #include "flashd/flashd.h" #include "log/log.h" #include "misc_info/misc_info.h" @@ -32,6 +33,7 @@ int main(int argc, char **argv) InitUpdaterLogger((mode == BOOT_FLASHD) ? "FLASHD" : "UPDATER", TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH); SetLogLevel(INFO); + FsManagerLogInit(LOG_TO_FILE, TMP_LOG.c_str()); LoadFstab(); STAGE(UPDATE_STAGE_OUT) << "Start " << ((mode == BOOT_FLASHD) ? "flashd" : "updater"); if (mode == BOOT_FLASHD) { diff --git a/services/updater_binary/main.cpp b/services/updater_binary/main.cpp index 775c17c1..62542a9b 100644 --- a/services/updater_binary/main.cpp +++ b/services/updater_binary/main.cpp @@ -18,6 +18,7 @@ #include #include #include "fs_manager/mount.h" +#include "fs_manager/fs_manager_log.h" #include "log.h" #include "updater/updater_const.h" #include "update_processor.h" @@ -32,7 +33,7 @@ int main(int argc, char **argv) LOG(ERROR) << "Invalid arguments."; return EXIT_INVALID_ARGS; } - + FsManagerLogInit(LOG_TO_FILE, TMP_LOG.c_str()); bool retry = false; int pipeFd = static_cast(std::strtol(argv[1], nullptr, DECIMAL)); if (argc >= BINARY_MAX_ARGS && strcmp(argv[BINARY_SECOND_ARG], "retry") == 0) { diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 5a7a54c8..9cd5a399 100755 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -44,8 +44,8 @@ ohos_unittest("updater_unittest") { "applypatch_test/transfer_manager_unittest.cpp", "diffpatch/bzip2_unittest.cpp", "diffpatch/diffpatch_unittest.cpp", - "flashd_test/flash_host_unittest.cpp", "flashd_test/flash_service_unittest.cpp", + "flashd_test/flash_host_unittest.cpp", "fs_manager/do_partition_unittest.cpp", "log_test/log_unittest.cpp", "misc_info_test/misc_info_unittest.cpp", @@ -96,8 +96,8 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/flashd/blockdevice.cpp", "//base/update/updater/services/flashd/daemon/daemon_updater.cpp", "//base/update/updater/services/flashd/daemon/flashd_main.cpp", - "//base/update/updater/services/flashd/flash_service.cpp", "//base/update/updater/services/flashd/host/host_updater.cpp", + "//base/update/updater/services/flashd/flash_service.cpp", "//base/update/updater/services/flashd/partition.cpp", "//base/update/updater/services/fs_manager/cmp_partition.cpp", "//base/update/updater/services/fs_manager/do_partition.cpp", diff --git a/test/unittest/applypatch_test/imagepatch_unittest.h b/test/unittest/applypatch_test/imagepatch_unittest.h index e4cdc358..6da5f553 100755 --- a/test/unittest/applypatch_test/imagepatch_unittest.h +++ b/test/unittest/applypatch_test/imagepatch_unittest.h @@ -77,7 +77,9 @@ public: int fd = open(target.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY, mode); EXPECT_GE(fd, 0); BlockSet targetBlk; - targetBlk.ParserAndInsert({"2", "0", "1"}); + targetBlk.ParserAndInsert({ + "2", "0", "1" + }); std::unique_ptr writer = std::make_unique(fd, targetBlk); std::vector empty; int32_t ret = updatepatch::UpdatePatch::ApplyImagePatch(param, empty, diff --git a/test/unittest/flashd_test/flash_host_unittest.cpp b/test/unittest/flashd_test/flash_host_unittest.cpp index fe97130e..0b9c580f 100755 --- a/test/unittest/flashd_test/flash_host_unittest.cpp +++ b/test/unittest/flashd_test/flash_host_unittest.cpp @@ -46,9 +46,6 @@ public: public: int TestFlashHost(uint16_t command, const std::string &cmd) { - uv_loop_t loopMain; - uv_loop_init(&loopMain); - HTaskInfo hTaskInfo = nullptr; std::shared_ptr task = std::make_shared(); if (task == nullptr) { @@ -57,21 +54,21 @@ public: hTaskInfo = task.get(); hTaskInfo->channelId = 1; hTaskInfo->sessionId = 0; - hTaskInfo->runLoop = &loopMain; + hTaskInfo->runLoop = uv_default_loop(); hTaskInfo->serverOrDaemon = 0; + hTaskInfo->ownerSessionClass = nullptr; std::shared_ptr flashHost = std::make_shared(hTaskInfo); if (flashHost == nullptr) { return -1; } flashHost->CommandDispatch(command, const_cast(reinterpret_cast(cmd.data())), cmd.size()); + return 0; } int TestFlashProgress(uint16_t command, const std::string &cmd, uint32_t progress) { - uv_loop_t loopMain; - uv_loop_init(&loopMain); HTaskInfo hTaskInfo = nullptr; std::shared_ptr task = std::make_shared(); @@ -81,8 +78,9 @@ public: hTaskInfo = task.get(); hTaskInfo->channelId = 1; hTaskInfo->sessionId = 0; - hTaskInfo->runLoop = &loopMain; + hTaskInfo->runLoop = uv_default_loop(); hTaskInfo->serverOrDaemon = 0; + hTaskInfo->ownerSessionClass = nullptr; std::shared_ptr flashHost = std::make_shared(hTaskInfo); if (flashHost == nullptr) { return -1; @@ -110,7 +108,7 @@ public: flashHost->CommandDispatch(CMD_UPDATER_PROGRESS, const_cast(reinterpret_cast(cmdInfo.data())), cmdInfo.size()); - percentage = (uint32_t)progress; + percentage = static_cast(progress); cmdInfo.resize(sizeof(percentage)); (void)memcpy_s(cmdInfo.data(), cmdInfo.size(), &percentage, sizeof(percentage)); flashHost->CommandDispatch(CMD_UPDATER_PROGRESS, @@ -120,30 +118,34 @@ public: } }; -HWTEST_F(FLashHostUnitTest, TestFlashHost, TestSize.Level1) +HWTEST_F(FLashHostUnitTest, TestFlashHostErase, TestSize.Level1) { FLashHostUnitTest test; Base::SetLogLevel(LOG_LAST); // debug log print - std::string cmdParam = TEST_UPDATER_PACKAGE_PATH; - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_UPDATE_INIT, cmdParam)); + std::string cmdParam = "erase -f "; + cmdParam += TEST_PARTITION_NAME; + EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_ERASE, cmdParam)); +} - cmdParam = " -f "; - cmdParam += TEST_PARTITION_NAME + " "; - cmdParam += TEST_FLASH_IMAGE_NAME; - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FLASH_INIT, cmdParam)); +HWTEST_F(FLashHostUnitTest, TestFlashHostFormat, TestSize.Level1) +{ + FLashHostUnitTest test; + Base::SetLogLevel(LOG_LAST); // debug log print - cmdParam = "erase -f "; + std::string cmdParam = "format -f "; cmdParam += TEST_PARTITION_NAME; - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_ERASE, cmdParam)); + cmdParam += " -t ext4"; + EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FORMAT, cmdParam)); - cmdParam = "format -f "; + + cmdParam = "format "; cmdParam += TEST_PARTITION_NAME; cmdParam += " -t ext4"; EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FORMAT, cmdParam)); } -HWTEST_F(FLashHostUnitTest, TestFlashProgress, TestSize.Level1) +HWTEST_F(FLashHostUnitTest, TestFlashHostUpdater, TestSize.Level1) { FLashHostUnitTest test; Base::SetLogLevel(LOG_LAST); // debug log print @@ -157,17 +159,103 @@ HWTEST_F(FLashHostUnitTest, TestFlashProgress, TestSize.Level1) EXPECT_EQ(0, test.TestFlashProgress(CMD_UPDATER_FLASH_INIT, cmdParam, -1)); } -HWTEST_F(FLashHostUnitTest, TestFlashProgressFinish, TestSize.Level1) +HWTEST_F(FLashHostUnitTest, TestFlashHostFlash, TestSize.Level1) { FLashHostUnitTest test; Base::SetLogLevel(LOG_LAST); // debug log print std::string cmdParam = TEST_UPDATER_PACKAGE_PATH; EXPECT_EQ(0, test.TestFlashProgress(CMD_UPDATER_UPDATE_INIT, cmdParam, 100)); - cmdParam = " -f "; cmdParam += TEST_PARTITION_NAME + " "; cmdParam += TEST_FLASH_IMAGE_NAME; EXPECT_EQ(0, test.TestFlashProgress(CMD_UPDATER_FLASH_INIT, cmdParam, 100)); } + +HWTEST_F(FLashHostUnitTest, TestFlashHostHelp, TestSize.Level1) +{ + std::string help = HostUpdater::GetFlashdHelp(); + printf("%s", help.c_str()); +} + +HWTEST_F(FLashHostUnitTest, TestFlashHostMatch, TestSize.Level1) +{ + std::string stringError; + uint16_t cmdFlag = 0; + bool bJumpDo = false; + bool ret = HostUpdater::CheckMatchUpdate("update updater.zip", stringError, cmdFlag, bJumpDo); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(cmdFlag, CMD_UPDATER_UPDATE_INIT); + EXPECT_EQ(bJumpDo == false, 1); + + ret = HostUpdater::CheckMatchUpdate("flash updater.zip", stringError, cmdFlag, bJumpDo); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(cmdFlag, CMD_UPDATER_FLASH_INIT); + EXPECT_EQ(bJumpDo == false, 1); + + ret = HostUpdater::CheckMatchUpdate("erase -f updater", stringError, cmdFlag, bJumpDo); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(cmdFlag, CMD_UPDATER_ERASE); + EXPECT_EQ(bJumpDo == false, 1); + + ret = HostUpdater::CheckMatchUpdate("format -f updater ", stringError, cmdFlag, bJumpDo); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(cmdFlag, CMD_UPDATER_FORMAT); + EXPECT_EQ(bJumpDo == false, 1); + + ret = HostUpdater::CheckMatchUpdate("flash", stringError, cmdFlag, bJumpDo); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(cmdFlag, CMD_KERNEL_HELP); + EXPECT_EQ(bJumpDo == true, 1); + + bJumpDo = false; + ret = HostUpdater::CheckMatchUpdate("install aaa.hap", stringError, cmdFlag, bJumpDo); + EXPECT_EQ(ret == false, 1); + EXPECT_EQ(bJumpDo == false, 1); +} + +HWTEST_F(FLashHostUnitTest, TestFlashHostConfirm, TestSize.Level1) +{ + bool closeInput = false; + bool ret = HostUpdater::ConfirmCommand("update updater.zip", closeInput); + EXPECT_EQ(ret == true, 1); + + HostUpdater::SetInput("yes"); + closeInput = false; + ret = HostUpdater::ConfirmCommand("flash updater.zip", closeInput); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(closeInput == true, 1); + + closeInput = false; + ret = HostUpdater::ConfirmCommand("erase updater", closeInput); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(closeInput == false, 1); + + closeInput = false; + ret = HostUpdater::ConfirmCommand("format updater", closeInput); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(closeInput == false, 1); + + closeInput = false; + ret = HostUpdater::ConfirmCommand("format -f updater", closeInput); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(closeInput == false, 1); + + closeInput = false; + ret = HostUpdater::ConfirmCommand("erase -f updater", closeInput); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(closeInput == false, 1); + + HostUpdater::SetInput("no"); + closeInput = false; + ret = HostUpdater::ConfirmCommand("format updater", closeInput); + EXPECT_EQ(ret == false, 1); + EXPECT_EQ(closeInput == false, 1); + + HostUpdater::SetInput("eeeeeeeee"); + closeInput = false; + ret = HostUpdater::ConfirmCommand("format updater", closeInput); + EXPECT_EQ(ret == false, 1); + EXPECT_EQ(closeInput == false, 1); +} } // namespace \ No newline at end of file diff --git a/test/unittest/flashd_test/flash_service_unittest.cpp b/test/unittest/flashd_test/flash_service_unittest.cpp index 3a33c1cf..3272f947 100755 --- a/test/unittest/flashd_test/flash_service_unittest.cpp +++ b/test/unittest/flashd_test/flash_service_unittest.cpp @@ -192,7 +192,7 @@ public: // begin hdcDamon->CommandDispatch(CMD_UPDATER_BEGIN, NULL, 0); - for (int i = 0; i < 100; i++) { // 10 send time + for (int i = 0; i < 10; i++) { // 10 send time HdcTransferBase::TransferPayload payloadHead {}; payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; payloadHead.uncompressSize = transferConfig.fileSize / 10; // 10 time @@ -298,10 +298,6 @@ public: std::string bufData = SerialStruct::SerializeToString(payloadHead); hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); } - payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; - payloadHead.uncompressSize = transferConfig.fileSize / 10; // 10 time - payloadHead.compressSize = transferConfig.fileSize / 10; // 10 time - payloadHead.index = 0; std::string bufData = SerialStruct::SerializeToString(payloadHead); hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); // end diff --git a/test/unittest/package/pkg_package_unittest.cpp b/test/unittest/package/pkg_package_unittest.cpp index bdd92603..2880e5cd 100755 --- a/test/unittest/package/pkg_package_unittest.cpp +++ b/test/unittest/package/pkg_package_unittest.cpp @@ -38,8 +38,6 @@ namespace { constexpr uint32_t MAX_FILE_NAME = 256; constexpr uint32_t CENTRAL_SIGNATURE = 0x02014b50; constexpr uint32_t END_CENTRAL_SIGNATURE = 0x06054b50; -constexpr uint32_t ZIP_NODE_ID = 100; -constexpr size_t GIANT_NUMBER = 100000; class TestFile : public PkgFile { public: @@ -122,13 +120,14 @@ public: EXPECT_NE(pkgManager_, nullptr); PkgManager::StreamPtr stream = nullptr; std::string packagePath = TEST_PATH_TO; + uint32_t zipNodeId = 100; packagePath += testPackageName; pkgManager_->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read); EXPECT_NE(stream, nullptr); std::unique_ptr file = std::make_unique(pkgManager_, PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_NE(file, nullptr); - std::unique_ptr entry = std::make_unique(file.get(), ZIP_NODE_ID); + std::unique_ptr entry = std::make_unique(file.get(), zipNodeId); EXPECT_NE(entry, nullptr); string name = "TestBigZip"; @@ -162,7 +161,8 @@ public: EXPECT_EQ(ret, 0); WriteLE16(buff.data() + sizeof(CentralDirEntry) + name.length(), 1); WriteLE16(buff.data() + sizeof(CentralDirEntry) + name.length() + offsetHalfWord, offset4Words); - size_t size = UINT_MAX + GIANT_NUMBER; + size_t giantNumber = 100000; + size_t size = UINT_MAX + giantNumber; WriteLE64(buff.data() + sizeof(CentralDirEntry) + name.length() + offsetWord, size); WriteLE64(buff.data() + sizeof(CentralDirEntry) + name.length() + offset3Words, size); size_t decodeLen = 0; diff --git a/test/unittest/test_data/updater/updater.zip b/test/unittest/test_data/updater/updater.zip index 0ecd1ceb..25795ea9 100755 --- a/test/unittest/test_data/updater/updater.zip +++ b/test/unittest/test_data/updater/updater.zip @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14357f75170e22c61470c2cd0fe73ee4f4b1a3396ac5d386433e76c0e54d0cd9 -size 13387850 +oid sha256:d42c282d8f74c3bde0243a39b94150b30f7273bed463a3eaae6a26454bb9eaec +size 1785455 diff --git a/test/unittest/updater_binary/updater_binary_unittest.cpp b/test/unittest/updater_binary/updater_binary_unittest.cpp index 65975e54..d6a48a4d 100755 --- a/test/unittest/updater_binary/updater_binary_unittest.cpp +++ b/test/unittest/updater_binary/updater_binary_unittest.cpp @@ -112,25 +112,26 @@ protected: { int32_t ret; int32_t updateFileVersion = 1000; - int fileNameIndex = 3; - uint8_t componentType = 22; + PKG_LOGI("\n\n ************* CreatePackageBin %s \r\n", testPackageName.c_str()); UpgradePkgInfoExt pkgInfo; - ComponentInfoExt *comp = (ComponentInfoExt*)malloc( - sizeof(ComponentInfoExt) * (testFileNames_.size() + fileNameIndex)); - if (comp == nullptr) { - return -1; - } // C API, Cannot use c++ string class. pkgInfo.softwareVersion = strdup("100.100.100.100"); pkgInfo.date = strdup("2021-02-02"); pkgInfo.time = strdup("21:23:49"); pkgInfo.productUpdateId = strdup("555.555.100.555"); + int fileNameIndex = 3; + uint8_t componentType = 22; pkgInfo.entryCount = testFileNames_.size() + fileNameIndex; pkgInfo.updateFileVersion = updateFileVersion; pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo.pkgType = PKG_PACK_TYPE_UPGRADE; + ComponentInfoExt *comp = (ComponentInfoExt*)malloc( + sizeof(ComponentInfoExt) * (testFileNames_.size() + fileNameIndex)); + if (comp == nullptr) { + return -1; + } for (size_t i = 0; i < testFileNames_.size(); i++) { BuildCompnentInfo(comp[i], testFileNames_[i], testFileNames_[i], componentType); } @@ -143,9 +144,6 @@ protected: std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; ret = CreatePackage(&pkgInfo, comp, packagePath.c_str(), GetTestPrivateKeyName().c_str()); - if (ret == 0) { - PKG_LOGI("CreatePackage success offset"); - } for (size_t i = 0; i < index; i++) { free(comp[i].componentAddr); free(comp[i].filePath); diff --git a/utils/updater_reboot.cpp b/utils/updater_reboot.cpp index 7c57ff61..42e189f8 100644 --- a/utils/updater_reboot.cpp +++ b/utils/updater_reboot.cpp @@ -32,12 +32,12 @@ int main(int argc, char **argv) std::string updaterStr = "updater"; if (!memcmp(argv[1], updaterStr.c_str(), updaterStr.length())) { updater::utils::DoReboot(argv[1]); - } else if (strcmp(argv[1], "flash") == 0) { + } else if (strcmp(argv[1], "flashd") == 0) { updater::utils::DoReboot(argv[1]); - } else if (strncmp(argv[1], "flash:", strlen("flash:")) == 0) { - updater::utils::DoReboot("flash", argv[1] + strlen("flash:")); + } else if (strncmp(argv[1], "flashd:", strlen("flashd:")) == 0) { + updater::utils::DoReboot("flashd", argv[1] + strlen("flashd:")); } else { - updater::LOG(updater::INFO) << "param must be updater/flash!"; + updater::LOG(updater::INFO) << "param must be updater/flashd!"; } } return 0; diff --git a/utils/utils.cpp b/utils/utils.cpp index 4f2ead20..fe205e4b 100644 --- a/utils/utils.cpp +++ b/utils/utils.cpp @@ -178,7 +178,7 @@ void DoReboot(const std::string& rebootTarget, const std::string &extData) if (rebootTarget == "updater" && strcmp(msg.command, "boot_updater") != 0) { result = strcpy_s(msg.command, maxCommandSize, "boot_updater"); msg.command[maxCommandSize] = 0; - } else if (rebootTarget == "flash" && strcmp(msg.command, "flash") != 0) { + } else if (rebootTarget == "flashd" && strcmp(msg.command, "flashd") != 0) { result = strcpy_s(msg.command, maxCommandSize, "boot_flash"); msg.command[maxCommandSize] = 0; } else if (rebootTarget == "bootloader" && strcmp(msg.command, "boot_loader") != 0) { -- Gitee From 6ecc28b980e744ff020b56ba4f6ad42b52807348 Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Thu, 11 Nov 2021 15:07:06 +0800 Subject: [PATCH 09/15] updater: fix gn format Signed-off-by: xionglei6 --- test/unittest/BUILD.gn | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 9cd5a399..5a7a54c8 100755 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -44,8 +44,8 @@ ohos_unittest("updater_unittest") { "applypatch_test/transfer_manager_unittest.cpp", "diffpatch/bzip2_unittest.cpp", "diffpatch/diffpatch_unittest.cpp", - "flashd_test/flash_service_unittest.cpp", "flashd_test/flash_host_unittest.cpp", + "flashd_test/flash_service_unittest.cpp", "fs_manager/do_partition_unittest.cpp", "log_test/log_unittest.cpp", "misc_info_test/misc_info_unittest.cpp", @@ -96,8 +96,8 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/flashd/blockdevice.cpp", "//base/update/updater/services/flashd/daemon/daemon_updater.cpp", "//base/update/updater/services/flashd/daemon/flashd_main.cpp", - "//base/update/updater/services/flashd/host/host_updater.cpp", "//base/update/updater/services/flashd/flash_service.cpp", + "//base/update/updater/services/flashd/host/host_updater.cpp", "//base/update/updater/services/flashd/partition.cpp", "//base/update/updater/services/fs_manager/cmp_partition.cpp", "//base/update/updater/services/fs_manager/do_partition.cpp", -- Gitee From 4e060b7fccc32849bbf12e998a1b23d15eef619c Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Tue, 16 Nov 2021 10:19:31 +0800 Subject: [PATCH 10/15] updater: add hdc to updater Signed-off-by: xionglei6 --- services/etc/init.cfg | 4 +- services/flashd/BUILD.gn | 184 ++- services/flashd/common/async_cmd.cpp | 189 +++ services/flashd/common/async_cmd.h | 64 + services/flashd/common/auth.cpp | 488 ++++++ services/flashd/common/auth.h | 37 + services/flashd/common/base.cpp | 1249 ++++++++++++++++ services/flashd/common/base.h | 146 ++ services/flashd/common/channel.cpp | 434 ++++++ services/flashd/common/channel.h | 76 + services/flashd/common/common.h | 79 + services/flashd/common/debug.cpp | 104 ++ services/flashd/common/debug.h | 28 + services/flashd/common/define.h | 98 ++ services/flashd/common/define_plus.h | 340 +++++ services/flashd/common/file.cpp | 195 +++ services/flashd/common/file.h | 39 + services/flashd/common/file_descriptor.cpp | 166 +++ services/flashd/common/file_descriptor.h | 58 + services/flashd/common/forward.cpp | 789 ++++++++++ services/flashd/common/forward.h | 107 ++ services/flashd/common/serial_struct.h | 88 ++ services/flashd/common/serial_struct_define.h | 1314 +++++++++++++++++ services/flashd/common/session.cpp | 1062 +++++++++++++ services/flashd/common/session.h | 183 +++ services/flashd/common/task.cpp | 99 ++ services/flashd/common/task.h | 57 + services/flashd/common/tcp.cpp | 98 ++ services/flashd/common/tcp.h | 43 + services/flashd/common/transfer.cpp | 417 ++++++ services/flashd/common/transfer.h | 114 ++ services/flashd/common/usb.cpp | 144 ++ services/flashd/common/usb.h | 41 + services/flashd/daemon/daemon.cpp | 346 +++++ services/flashd/daemon/daemon.h | 47 + services/flashd/daemon/daemon_app.cpp | 151 ++ services/flashd/daemon/daemon_app.h | 38 + services/flashd/daemon/daemon_common.h | 41 + services/flashd/daemon/daemon_forward.cpp | 82 + services/flashd/daemon/daemon_forward.h | 31 + services/flashd/daemon/daemon_tcp.cpp | 151 ++ services/flashd/daemon/daemon_tcp.h | 40 + services/flashd/daemon/daemon_unity.cpp | 305 ++++ services/flashd/daemon/daemon_unity.h | 48 + services/flashd/daemon/daemon_usb.cpp | 498 +++++++ services/flashd/daemon/daemon_usb.h | 62 + services/flashd/daemon/flashd_main.cpp | 9 +- services/flashd/daemon/jdwp.cpp | 279 ++++ services/flashd/daemon/jdwp.h | 59 + services/flashd/daemon/main.cpp | 197 +++ services/flashd/daemon/shell.cpp | 217 +++ services/flashd/daemon/shell.h | 47 + services/flashd/daemon/usb_ffs.h | 218 +++ services/flashd/host/client.cpp | 371 +++++ services/flashd/host/client.h | 59 + services/flashd/host/host_app.cpp | 177 +++ services/flashd/host/host_app.h | 34 + services/flashd/host/host_common.h | 37 + services/flashd/host/host_forward.cpp | 26 + services/flashd/host/host_forward.h | 29 + services/flashd/host/host_tcp.cpp | 166 +++ services/flashd/host/host_tcp.h | 38 + services/flashd/host/host_unity.cpp | 155 ++ services/flashd/host/host_unity.h | 51 + services/flashd/host/host_updater.cpp | 20 +- services/flashd/host/host_updater.h | 1 - services/flashd/host/host_usb.cpp | 550 +++++++ services/flashd/host/host_usb.h | 66 + services/flashd/host/main.cpp | 323 ++++ services/flashd/host/server.cpp | 795 ++++++++++ services/flashd/host/server.h | 64 + services/flashd/host/server_for_client.cpp | 674 +++++++++ services/flashd/host/server_for_client.h | 60 + services/flashd/host/translate.cpp | 248 ++++ services/flashd/host/translate.h | 31 + services/updater_binary/main.cpp | 2 +- test/unittest/BUILD.gn | 11 +- .../flashd_test/flash_host_unittest.cpp | 6 - utils/utils.cpp | 2 + 79 files changed, 15355 insertions(+), 41 deletions(-) create mode 100755 services/flashd/common/async_cmd.cpp create mode 100755 services/flashd/common/async_cmd.h create mode 100755 services/flashd/common/auth.cpp create mode 100755 services/flashd/common/auth.h create mode 100755 services/flashd/common/base.cpp create mode 100755 services/flashd/common/base.h create mode 100755 services/flashd/common/channel.cpp create mode 100755 services/flashd/common/channel.h create mode 100755 services/flashd/common/common.h create mode 100755 services/flashd/common/debug.cpp create mode 100755 services/flashd/common/debug.h create mode 100755 services/flashd/common/define.h create mode 100755 services/flashd/common/define_plus.h create mode 100755 services/flashd/common/file.cpp create mode 100755 services/flashd/common/file.h create mode 100755 services/flashd/common/file_descriptor.cpp create mode 100755 services/flashd/common/file_descriptor.h create mode 100755 services/flashd/common/forward.cpp create mode 100755 services/flashd/common/forward.h create mode 100755 services/flashd/common/serial_struct.h create mode 100755 services/flashd/common/serial_struct_define.h create mode 100755 services/flashd/common/session.cpp create mode 100755 services/flashd/common/session.h create mode 100755 services/flashd/common/task.cpp create mode 100755 services/flashd/common/task.h create mode 100755 services/flashd/common/tcp.cpp create mode 100755 services/flashd/common/tcp.h create mode 100755 services/flashd/common/transfer.cpp create mode 100755 services/flashd/common/transfer.h create mode 100755 services/flashd/common/usb.cpp create mode 100755 services/flashd/common/usb.h create mode 100755 services/flashd/daemon/daemon.cpp create mode 100755 services/flashd/daemon/daemon.h create mode 100755 services/flashd/daemon/daemon_app.cpp create mode 100755 services/flashd/daemon/daemon_app.h create mode 100755 services/flashd/daemon/daemon_common.h create mode 100755 services/flashd/daemon/daemon_forward.cpp create mode 100755 services/flashd/daemon/daemon_forward.h create mode 100755 services/flashd/daemon/daemon_tcp.cpp create mode 100755 services/flashd/daemon/daemon_tcp.h create mode 100755 services/flashd/daemon/daemon_unity.cpp create mode 100755 services/flashd/daemon/daemon_unity.h create mode 100755 services/flashd/daemon/daemon_usb.cpp create mode 100755 services/flashd/daemon/daemon_usb.h create mode 100755 services/flashd/daemon/jdwp.cpp create mode 100755 services/flashd/daemon/jdwp.h create mode 100755 services/flashd/daemon/main.cpp create mode 100755 services/flashd/daemon/shell.cpp create mode 100755 services/flashd/daemon/shell.h create mode 100755 services/flashd/daemon/usb_ffs.h create mode 100755 services/flashd/host/client.cpp create mode 100755 services/flashd/host/client.h create mode 100755 services/flashd/host/host_app.cpp create mode 100755 services/flashd/host/host_app.h create mode 100755 services/flashd/host/host_common.h create mode 100755 services/flashd/host/host_forward.cpp create mode 100755 services/flashd/host/host_forward.h create mode 100755 services/flashd/host/host_tcp.cpp create mode 100755 services/flashd/host/host_tcp.h create mode 100755 services/flashd/host/host_unity.cpp create mode 100755 services/flashd/host/host_unity.h create mode 100755 services/flashd/host/host_usb.cpp create mode 100755 services/flashd/host/host_usb.h create mode 100755 services/flashd/host/main.cpp create mode 100755 services/flashd/host/server.cpp create mode 100755 services/flashd/host/server.h create mode 100755 services/flashd/host/server_for_client.cpp create mode 100755 services/flashd/host/server_for_client.h create mode 100755 services/flashd/host/translate.cpp create mode 100755 services/flashd/host/translate.h diff --git a/services/etc/init.cfg b/services/etc/init.cfg index cefe21d4..a1f12f5d 100755 --- a/services/etc/init.cfg +++ b/services/etc/init.cfg @@ -14,9 +14,11 @@ "mkdir /system", "mkdir /vendor", "mkdir /tmp", + "mkdir /param", "mount tmpfs tmpfs /tmp", "chown 0 2000 /tmp", "chmod 0755 /tmp", + "chmod 0755 /param", "mkdir /dev/usb-ffs 0770 shell shell", "mkdir /dev/usb-ffs/hdc 0770 shell shell", "mkdir /dev/usb-ffs/hdc 0770 shell shell", @@ -40,6 +42,7 @@ "write /config/usb_gadget/g1/configs/b.1/MaxPower 500", "symlink /config/usb_gadget/g1/configs/b.1 /config/usb_gadget/g1/os_desc/b.1", "mount functionfs hdc /dev/usb-ffs/hdc uid=2000,gid=2000", + "load_persist_params ", "setparam sys.usb.controller 100e0000.hidwc3_0", "setparam sys.usb.config hdc", "setparam sys.usb.configfs 1" @@ -65,7 +68,6 @@ "path" : ["/bin/updater"], "uid" : 0, "gid" : 0, - "once" : 1, "importance" : 0, "caps" : [0, 1] }, { diff --git a/services/flashd/BUILD.gn b/services/flashd/BUILD.gn index 91407725..d0019f88 100755 --- a/services/flashd/BUILD.gn +++ b/services/flashd/BUILD.gn @@ -13,6 +13,84 @@ import("//build/ohos.gni") +FLASHD_HDC_PATH = "//base/update/updater/services/flashd" + +common_sources = [ + "${FLASHD_HDC_PATH}/common/async_cmd.cpp", + "${FLASHD_HDC_PATH}/common/auth.cpp", + "${FLASHD_HDC_PATH}/common/base.cpp", + "${FLASHD_HDC_PATH}/common/channel.cpp", + "${FLASHD_HDC_PATH}/common/debug.cpp", + "${FLASHD_HDC_PATH}/common/file.cpp", + "${FLASHD_HDC_PATH}/common/file_descriptor.cpp", + "${FLASHD_HDC_PATH}/common/forward.cpp", + "${FLASHD_HDC_PATH}/common/session.cpp", + "${FLASHD_HDC_PATH}/common/task.cpp", + "${FLASHD_HDC_PATH}/common/tcp.cpp", + "${FLASHD_HDC_PATH}/common/transfer.cpp", + "${FLASHD_HDC_PATH}/common/usb.cpp", +] + +config("flashd_hdc_config") { + include_dirs = [ "${FLASHD_HDC_PATH}/common" ] + cflags_cc = [ "-std=c++17" ] +} + +ohos_source_set("flashd_deamon") { + sources = [ + "${FLASHD_HDC_PATH}/daemon/daemon.cpp", + "${FLASHD_HDC_PATH}/daemon/daemon_app.cpp", + "${FLASHD_HDC_PATH}/daemon/daemon_forward.cpp", + "${FLASHD_HDC_PATH}/daemon/daemon_tcp.cpp", + "${FLASHD_HDC_PATH}/daemon/daemon_unity.cpp", + "${FLASHD_HDC_PATH}/daemon/daemon_usb.cpp", + "${FLASHD_HDC_PATH}/daemon/jdwp.cpp", + "${FLASHD_HDC_PATH}/daemon/shell.cpp", + ] + + sources += common_sources + + defines = [ + "HARMONY_PROJECT", + "HDC_SUPPORT_FLASHD", + ] + + configs = [ ":flashd_hdc_config" ] + + deps = [ + "//third_party/libuv:uv_static", + "//third_party/lz4:liblz4_static", + "//third_party/openssl:libcrypto_static", + "//utils/native/base:utils", + ] + + if (use_musl) { + deps += [ + "//base/startup/init_lite/interfaces/innerkits/reboot:libreboot_static", + "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", + ] + } + + include_dirs = [ + "${FLASHD_HDC_PATH}/daemon", + "//base/update/updater/services/flashd", + "//base/update/updater/services/flashd/daemon", + "//base/update/updater/services/flashd/common", + "//base/update/updater/services/flashd/host", + "//utils/native/base/include", + "//third_party/lz4/lib", + "//third_party/openssl/include", + "//third_party/libuv", + ] + + if (use_musl) { + include_dirs += [ + "//base/startup/syspara_lite/interfaces/innerkits/native/syspara/include", + "//base/startup/init_lite/interfaces/innerkits/include", + ] + } +} + ohos_static_library("libflashd") { sources = [ "//base/update/updater/services/flashd/blockdevice.cpp", @@ -31,6 +109,7 @@ ohos_static_library("libflashd") { ] deps = [ + ":flashd_deamon", "//base/update/updater/interfaces/kits/misc_info:libmiscinfo", "//base/update/updater/services/applypatch:libapplypatch", "//base/update/updater/services/diffpatch/patch:libpatch", @@ -39,7 +118,6 @@ ohos_static_library("libflashd") { "//base/update/updater/services/package:libupdaterpackage", "//base/update/updater/services/script:libupdaterscript", "//base/update/updater/utils:libutils", - "//developtools/hdc_standard:hdc_deamon_flashd", "//third_party/bzip2:libbz2", "//third_party/cJSON:cjson_static", "//third_party/libuv:uv_static", @@ -50,8 +128,8 @@ ohos_static_library("libflashd") { ] include_dirs = [ - "//developtools/hdc_standard/src/daemon", - "//developtools/hdc_standard/src/common", + "${FLASHD_HDC_PATH}/daemon", + "${FLASHD_HDC_PATH}/common", "//base/update/updater/services", "//base/update/updater/services/flashd", "//base/update/updater/services/flashd/daemon", @@ -73,6 +151,106 @@ ohos_static_library("libflashd") { part_name = "updater" } +ohos_executable("ohflash") { + libs = [] + configs = [ ":flashd_hdc_config" ] + defines = [ + "HDC_HOST", + "HARMONY_PROJECT", + ] + if (is_mac) { + defines += [ "HOST_MAC" ] + } + cflags_cc = [ + "-Wno-error", + "-Wno-error=unused-variable", + "-Wno-unused-variable", + ] + sources = [ + "${FLASHD_HDC_PATH}/host/client.cpp", + "${FLASHD_HDC_PATH}/host/host_app.cpp", + "${FLASHD_HDC_PATH}/host/host_forward.cpp", + "${FLASHD_HDC_PATH}/host/host_tcp.cpp", + "${FLASHD_HDC_PATH}/host/host_unity.cpp", + "${FLASHD_HDC_PATH}/host/host_usb.cpp", + "${FLASHD_HDC_PATH}/host/main.cpp", + "${FLASHD_HDC_PATH}/host/server.cpp", + "${FLASHD_HDC_PATH}/host/server_for_client.cpp", + "${FLASHD_HDC_PATH}/host/translate.cpp", + "${FLASHD_HDC_PATH}/host/host_updater.cpp", + ] + sources += common_sources + + deps = [ + "//third_party/libusb:libusb", + "//third_party/libuv:uv_static", + "//third_party/lz4:liblz4_static", + "//third_party/openssl:libcrypto_static", + "//utils/native/base:utilsecurec", + ] + + deps += [ + "//third_party/libusb:libusb", + ] + + include_dirs = [ + "${FLASHD_HDC_PATH}/host", + "//utils/native/base/include", + "//third_party/lz4/lib", + "//third_party/openssl/include", + "//third_party/libuv", + ] + + if(is_mingw) { + static_link = true + defines += [ "_WIN32" ] + defines += [ "WIN32_LEAN_AND_MEAN" ] + libs += [ "setupapi" ] + } + + if(is_linux) { + static_link = true + deps += [ "//third_party/openssl:libcrypto_static" ] + } + + subsystem_name = "updater" + part_name = "updater" +} + + +group("flashhost_target_standard") { + deps = [ + ":ohflash", + ] +} + +group("flashhost_target_standard_linux") { + deps = [ + ":ohflash(//build/toolchain/linux:clang_x64)", + ] +} + +group("flashhost_target_standard_mingw") { + deps = [ + ":ohflash(//build/toolchain/mingw:mingw_x86_64)", + ] +} + +group("flashhost_target_standard_all") { + deps = [ + ":flashhost_target_standard", + ":flashhost_target_standard_linux", + ":flashhost_target_standard_mingw", + ] +} + +group("flashhost_target_standard_windows") { + deps = [ + ":flashhost_target_standard", + ":flashhost_target_standard_mingw", + ] +} + group("updater_flashd") { deps = [ ":libflashd" ] } diff --git a/services/flashd/common/async_cmd.cpp b/services/flashd/common/async_cmd.cpp new file mode 100755 index 00000000..43d5f1a9 --- /dev/null +++ b/services/flashd/common/async_cmd.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "async_cmd.h" +#define PIPE_READ 0 +#define PIPE_WRITE 1 + +namespace Hdc { +// Do not add thread-specific init op in the following methods as it's running in child thread. +AsyncCmd::AsyncCmd() +{ + Base::ZeroStruct(stdinPipe); + Base::ZeroStruct(stdoutPipe); + Base::ZeroStruct(stderrPipe); + Base::ZeroStruct(proc); + Base::ZeroStruct(procOptions); + running = false; + loop = nullptr; +} + +AsyncCmd::~AsyncCmd() +{ + WRITE_LOG(LOG_DEBUG, "~AsyncCmd"); +}; + +bool AsyncCmd::ReadyForRelease() const +{ + return !running; +} + +// manual stop will not trigger ExitCallback, we call it +void AsyncCmd::DoRelease() +{ + if (hasStop || !running) { + return; + } + hasStop = true; // must set here to deny repeate release + uv_process_kill(&proc, SIGKILL); + WRITE_LOG(LOG_DEBUG, "AsyncCmd::DoRelease finish"); +} + +void AsyncCmd::ChildReadCallback(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) +{ + AsyncCmd *thisClass = (AsyncCmd *)stream->data; + if (nread <= 0) { // stdout and stderr + WRITE_LOG(LOG_DEBUG, "Read ShellChildProcess failed %s", uv_err_name(nread)); + } else { + if (thisClass->options & OPTION_READBACK_OUT) { + thisClass->cmdResult = buf->base; + if (!thisClass->resultCallback(false, 0, thisClass->cmdResult)) { + uv_process_kill(&thisClass->proc, SIGKILL); + uv_read_stop(stream); + } + thisClass->cmdResult = STRING_EMPTY; + } else { // output all when finish + thisClass->cmdResult += buf->base; + } + } + delete[] buf->base; +} + +void AsyncCmd::ExitCallback(uv_process_t *req, int64_t exitStatus, int tersignal) +{ + auto funcReqClose = [](uv_handle_t *handle) -> void { + AsyncCmd *thisClass = (AsyncCmd *)handle->data; + if (--thisClass->uvRef == 0) { + thisClass->running = false; + } + }; + AsyncCmd *thisClass = (AsyncCmd *)req->data; + thisClass->hasStop = true; // callback maybe call dorelease, so deny repeate ExitCallback + + thisClass->resultCallback(true, exitStatus, thisClass->cmdResult); + WRITE_LOG(LOG_DEBUG, "AsyncCmd::ExitCallback"); + thisClass->uvRef = 4; + Base::TryCloseHandle((uv_handle_t *)&thisClass->stdinPipe, true, funcReqClose); + Base::TryCloseHandle((uv_handle_t *)&thisClass->stdoutPipe, true, funcReqClose); + Base::TryCloseHandle((uv_handle_t *)&thisClass->stderrPipe, true, funcReqClose); + Base::TryCloseHandle((uv_handle_t *)req, true, funcReqClose); + thisClass->cmdResult = STRING_EMPTY; +} + +bool AsyncCmd::Initial(uv_loop_t *loopIn, const CmdResultCallback callback, uint32_t optionsIn) +{ + if (running) { + return false; + } + loop = loopIn; + resultCallback = callback; + options = optionsIn; + return true; +} + +bool AsyncCmd::ExecuteCommand(const string &command) +{ + string cmd = command; + Base::Trim(cmd, "\""); + if (!(options & OPTION_COMMAND_ONETIME)) { + if (StartProcess() < 0) { + return false; + } + if (options & OPTION_APPEND_NEWLINE) { + cmd += "\n"; + } + Base::SendToStream((uv_stream_t *)&stdinPipe, (uint8_t *)cmd.c_str(), cmd.size() + 1); + } else { + if (StartProcess(cmd) < 0) { + return false; + } + } + return true; +} + +int AsyncCmd::StartProcess(string command) +{ + constexpr auto countStdIOCount = 3; + char **ppShellArgs = nullptr; + string shellPath = Base::GetShellPath(); + uv_stdio_container_t stdioShellProc[countStdIOCount]; + while (true) { + uv_pipe_init(loop, &stdinPipe, 1); + uv_pipe_init(loop, &stdoutPipe, 1); + uv_pipe_init(loop, &stderrPipe, 1); + stdinPipe.data = this; + stdoutPipe.data = this; + stderrPipe.data = this; + procOptions.stdio = stdioShellProc; + procOptions.stdio[STDIN_FILENO].flags = (uv_stdio_flags)(UV_CREATE_PIPE | UV_READABLE_PIPE); + procOptions.stdio[STDIN_FILENO].data.stream = (uv_stream_t *)&stdinPipe; + procOptions.stdio[STDOUT_FILENO].flags = (uv_stdio_flags)(UV_CREATE_PIPE | UV_WRITABLE_PIPE); + procOptions.stdio[STDOUT_FILENO].data.stream = (uv_stream_t *)&stdoutPipe; + procOptions.stdio[STDERR_FILENO].flags = (uv_stdio_flags)(UV_CREATE_PIPE | UV_WRITABLE_PIPE); + procOptions.stdio[STDERR_FILENO].data.stream = (uv_stream_t *)&stderrPipe; + procOptions.stdio_count = countStdIOCount; + procOptions.file = shellPath.c_str(); + procOptions.exit_cb = ExitCallback; + + if (command.size() > 0) { + constexpr auto args = 4; + ppShellArgs = new char *[args]; + const string shellCommandFlag = "-c"; + ppShellArgs[0] = (char *)shellPath.c_str(); + ppShellArgs[1] = (char *)shellCommandFlag.c_str(); + ppShellArgs[args - CMD_ARG1_COUNT] = (char *)command.c_str(); + ppShellArgs[args - 1] = nullptr; + } else { + ppShellArgs = new char *[CMD_ARG1_COUNT]; + ppShellArgs[0] = (char *)shellPath.c_str(); + ppShellArgs[1] = nullptr; + } + procOptions.args = ppShellArgs; + proc.data = this; + + if (uv_spawn(loop, &proc, &procOptions)) { + WRITE_LOG(LOG_FATAL, "Spawn shell process failed"); + break; + } + if (uv_read_start((uv_stream_t *)&stdoutPipe, Base::AllocBufferCallback, ChildReadCallback)) { + break; + } + if (uv_read_start((uv_stream_t *)&stderrPipe, Base::AllocBufferCallback, ChildReadCallback)) { + break; + } + running = true; + break; + } + if (ppShellArgs) { + delete[] ppShellArgs; + } + if (!running) { + // failed + resultCallback(true, -1, "Start process failed"); + return -1; + } else { + return 0; + } +} +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/common/async_cmd.h b/services/flashd/common/async_cmd.h new file mode 100755 index 00000000..f7772282 --- /dev/null +++ b/services/flashd/common/async_cmd.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_ASYNC_CMD_H +#define HDC_ASYNC_CMD_H +#include "common.h" + +namespace Hdc { +class AsyncCmd { +public: + AsyncCmd(); + virtual ~AsyncCmd(); + enum AsyncCmdOption { + OPTION_APPEND_NEWLINE = 1, + OPTION_COMMAND_ONETIME = 2, + OPTION_READBACK_OUT = 4, + USB_OPTION_RESERVE8 = 8, + }; + // 1)is finish 2)exitStatus 3)resultString(maybe empty) + using CmdResultCallback = std::function; + static uint32_t GetDefaultOption() + { + return OPTION_APPEND_NEWLINE | OPTION_COMMAND_ONETIME; + } + // uv_loop_t loop is given to uv_spawn, which can't be const + bool Initial(uv_loop_t *loopIn, const CmdResultCallback callback, uint32_t optionsIn = GetDefaultOption()); + void DoRelease(); // Release process resources + bool ExecuteCommand(const string &command); + bool ReadyForRelease() const; + +private: + int StartProcess(string command = STRING_EMPTY); + // uv_read_cb callback 1st parameter can't be changed, const can't be added + static void ChildReadCallback(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); + // uv_exit_cb callback 1st parameter can't be changed, const can't be added + static void ExitCallback(uv_process_t *req, int64_t exitStatus, int tersignal); + + uv_loop_t *loop; + // loop is given to uv_spawn, which can't be const + uv_pipe_t stdinPipe; + uv_pipe_t stdoutPipe; + uv_pipe_t stderrPipe; + uv_process_t proc; + uv_process_options_t procOptions; + CmdResultCallback resultCallback; + string cmdResult; + bool running; + bool hasStop = false; + uint32_t options = 0; + uint8_t uvRef = 0; +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/common/auth.cpp b/services/flashd/common/auth.cpp new file mode 100755 index 00000000..50f148b4 --- /dev/null +++ b/services/flashd/common/auth.cpp @@ -0,0 +1,488 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "auth.h" +#include +#include +#include +#include +#include + +using namespace Hdc; +#define BIGNUMTOBIT 32 + +namespace HdcAuth { +// ---------------------------------------Cheat compiler--------------------------------------------------------- +#ifdef HDC_HOST + +bool AuthVerify(uint8_t *token, uint8_t *sig, int siglen) +{ + return false; +}; +bool PostUIConfirm(string publicKey) +{ + return false; +} + +#else // daemon + +bool GenerateKey(const char *file) +{ + return false; +}; +int AuthSign(void *rsa, const unsigned char *token, size_t tokenSize, void *sig) +{ + return 0; +}; +int GetPublicKeyFileBuf(unsigned char *data, size_t len) +{ + return 0; +} + +#endif +// ------------------------------------------------------------------------------------------------ + +const uint32_t RSANUMBYTES = 256; // 2048 bit key length +const uint32_t RSANUMWORDS = (RSANUMBYTES / sizeof(uint32_t)); +struct RSAPublicKey { + int wordModulusSize; // Length of n[] in number of uint32_t */ + uint32_t rsaN0inv; // -1 / n[0] mod 2^32 + uint32_t modulus[RSANUMWORDS]; // modulus as little endian array + uint32_t rr[RSANUMWORDS]; // R^2 as little endian array + int exponent; // 3 or 65537 +}; + +#ifdef HDC_HOST +// Convert OpenSSL RSA private key to pre-computed RSAPublicKey format +int RSA2RSAPublicKey(RSA *rsa, RSAPublicKey *publicKey) +{ + int result = 1; + unsigned int i; + BN_CTX *ctx = BN_CTX_new(); + BIGNUM *r32 = BN_new(); + BIGNUM *rsaRR = BN_new(); + BIGNUM *rsaR = BN_new(); + BIGNUM *rsaRem = BN_new(); + BIGNUM *rsaN0inv = BN_new(); +#ifdef OPENSSL_IS_BORINGSSL + // boringssl + BIGNUM *n = BN_new(); + BN_copy(n, rsa->n); + publicKey->exponent = BN_get_word(rsa->e); +#else + // openssl +#if OPENSSL_VERSION_NUMBER >= 0x10100005L + BIGNUM *n = (BIGNUM *)RSA_get0_n(rsa); + publicKey->exponent = BN_get_word(RSA_get0_e(rsa)); +#else + BIGNUM *n = BN_new(); + BN_copy(n, rsa->n); + publicKey->exponent = BN_get_word(rsa->e); +#endif + +#endif // OPENSSL_IS_BORINGSSL + while (true) { + if (RSA_size(rsa) != RSANUMBYTES) { + result = 0; + break; + } + + BN_set_bit(r32, BIGNUMTOBIT); + BN_set_bit(rsaR, RSANUMWORDS * BIGNUMTOBIT); + BN_mod_sqr(rsaRR, rsaR, n, ctx); + BN_div(nullptr, rsaRem, n, r32, ctx); + BN_mod_inverse(rsaN0inv, rsaRem, r32, ctx); + publicKey->wordModulusSize = RSANUMWORDS; + publicKey->rsaN0inv = 0 - BN_get_word(rsaN0inv); + for (i = 0; i < RSANUMWORDS; ++i) { + BN_div(rsaRR, rsaRem, rsaRR, r32, ctx); + publicKey->rr[i] = BN_get_word(rsaRem); + BN_div(n, rsaRem, n, r32, ctx); + publicKey->modulus[i] = BN_get_word(rsaRem); + } + break; + } + + BN_free(rsaR); + BN_free(rsaRR); + BN_free(n); + BN_free(r32); + BN_free(rsaN0inv); + BN_free(rsaRem); + BN_CTX_free(ctx); + return result; +} + +int GetUserInfo(char *buf, size_t len) +{ + char hostname[BUF_SIZE_DEFAULT]; + char username[BUF_SIZE_DEFAULT]; + uv_passwd_t pwd; + int ret = -1; + size_t bufSize = sizeof(hostname); + if (uv_os_gethostname(hostname, &bufSize) < 0 && EOK != strcpy_s(hostname, sizeof(hostname), "unknown")) { + return ERR_API_FAIL; + } + if (!uv_os_get_passwd(&pwd) && !strcpy_s(username, sizeof(username), pwd.username)) { + ret = 0; + } + uv_os_free_passwd(&pwd); + if (ret < 0 && EOK != strcpy_s(username, sizeof(username), "unknown")) { + return ERR_API_FAIL; + } + if (snprintf_s(buf, len, len - 1, " %s@%s", username, hostname) < 0) { + return ERR_BUF_OVERFLOW; + } + return RET_SUCCESS; +} + +int WritePublicKeyfile(RSA *private_key, const char *private_key_path) +{ + RSAPublicKey publicKey; + char info[BUF_SIZE_DEFAULT]; + int ret = 0; + string path = private_key_path + string(".pub"); + + ret = RSA2RSAPublicKey(private_key, &publicKey); + if (!ret) { + WRITE_LOG(LOG_DEBUG, "Failed to convert to publickey\n"); + return 0; + } + vector vec = Base::Base64Encode((const uint8_t *)&publicKey, sizeof(RSAPublicKey)); + if (!vec.size()) { + return 0; + } + GetUserInfo(info, sizeof(info)); + vec.insert(vec.end(), (uint8_t *)info, (uint8_t *)info + strlen(info)); + ret = Base::WriteBinFile(path.c_str(), vec.data(), vec.size(), true); + return ret >= 0 ? 1 : 0; +} + +bool GenerateKey(const char *file) +{ + EVP_PKEY *publicKey = EVP_PKEY_new(); + BIGNUM *exponent = BN_new(); + RSA *rsa = RSA_new(); + mode_t old_mask; + FILE *fKey = nullptr; + bool ret = false; + + while (true) { + WRITE_LOG(LOG_DEBUG, "generate_key '%s'\n", file); + if (!publicKey || !exponent || !rsa) { + WRITE_LOG(LOG_DEBUG, "Failed to allocate key"); + break; + } + + BN_set_word(exponent, RSA_F4); + RSA_generate_key_ex(rsa, 2048, exponent, nullptr); + EVP_PKEY_set1_RSA(publicKey, rsa); + old_mask = umask(077); // 077:permission + + fKey = fopen(file, "w"); + if (!fKey) { + WRITE_LOG(LOG_DEBUG, "Failed to open '%s'\n", file); + umask(old_mask); + break; + } + umask(old_mask); + if (!PEM_write_PrivateKey(fKey, publicKey, nullptr, nullptr, 0, nullptr, nullptr)) { + WRITE_LOG(LOG_DEBUG, "Failed to write key"); + break; + } + if (!WritePublicKeyfile(rsa, file)) { + WRITE_LOG(LOG_DEBUG, "Failed to write public key"); + break; + } + ret = true; + break; + } + + RSA_free(rsa); + EVP_PKEY_free(publicKey); + BN_free(exponent); + if (fKey) + fclose(fKey); + return ret; +} + +bool ReadKey(const char *file, list *listPrivateKey) +{ + FILE *f = nullptr; + bool ret = false; + + while (true) { + if (!(f = fopen(file, "r"))) { + break; + } + RSA *rsa = RSA_new(); + if (!PEM_read_RSAPrivateKey(f, &rsa, nullptr, nullptr)) { + RSA_free(rsa); + break; + } + listPrivateKey->push_back((void *)rsa); + ret = true; + break; + } + if (f) { + fclose(f); + } + return ret; +} + +int GetUserKeyPath(string &path) +{ + struct stat status; + const char harmoneyPath[] = ".harmony"; + const char hdcKeyFile[] = "hdckey"; + char buf[BUF_SIZE_DEFAULT]; + size_t len = BUF_SIZE_DEFAULT; + // $home + if (uv_os_homedir(buf, &len) < 0) + return false; + path = string(buf) + Base::GetPathSep() + string(harmoneyPath) + Base::GetPathSep(); + if (stat(path.c_str(), &status)) { + uv_fs_t req; + uv_fs_mkdir(nullptr, &req, path.c_str(), 0750, nullptr); // 0750:permission + uv_fs_req_cleanup(&req); + if (req.result < 0) { + WRITE_LOG(LOG_DEBUG, "Cannot mkdir '%s'", path.c_str()); + return false; + } + } + path += hdcKeyFile; + return true; +} + +bool LoadHostUserKey(list *listPrivateKey) +{ + struct stat status; + string path; + if (!GetUserKeyPath(path)) { + return false; + } + if (stat(path.c_str(), &status) == -1) { + if (!GenerateKey(path.c_str())) { + WRITE_LOG(LOG_DEBUG, "Failed to generate new key"); + return false; + } + } + if (!ReadKey(path.c_str(), listPrivateKey)) { + return false; + } + return true; +} + +int AuthSign(void *rsa, const unsigned char *token, size_t tokenSize, void *sig) +{ + unsigned int len; + if (!RSA_sign(NID_sha1, token, tokenSize, (unsigned char *)sig, &len, (RSA *)rsa)) { + return 0; + } + return (int)len; +} + +int GetPublicKeyFileBuf(unsigned char *data, size_t len) +{ + string path; + int ret; + + if (!GetUserKeyPath(path)) { + return 0; + } + path += ".pub"; + ret = Base::ReadBinFile(path.c_str(), (void **)data, len); + if (ret <= 0) { + return 0; + } + data[ret] = '\0'; + return ret + 1; +} + +#else // daemon + +bool RSAPublicKey2RSA(const uint8_t *keyBuf, RSA **key) +{ + const int pubKeyModulusSize = 256; + const int pubKeyModulusSizeWords = pubKeyModulusSize / 4; + + const RSAPublicKey *keyStruct = reinterpret_cast(keyBuf); + bool ret = false; + uint8_t modulusBuffer[pubKeyModulusSize]; + RSA *newKey = RSA_new(); + if (!newKey) { + goto cleanup; + } + if (keyStruct->wordModulusSize != pubKeyModulusSizeWords) { + goto cleanup; + } + if (memcpy_s(modulusBuffer, sizeof(modulusBuffer), keyStruct->modulus, sizeof(modulusBuffer)) != EOK) { + goto cleanup; + } + Base::ReverseBytes(modulusBuffer, sizeof(modulusBuffer)); + +#ifdef OPENSSL_IS_BORINGSSL + // boringssl + newKey->n = BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr); + newKey->e = BN_new(); + if (!newKey->e || !BN_set_word(newKey->e, keyStruct->exponent) || !newKey->n) { + goto cleanup; + } +#else + // openssl +#if OPENSSL_VERSION_NUMBER >= 0x10100005L + RSA_set0_key(newKey, BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr), BN_new(), BN_new()); +#else + newKey->n = BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr); + newKey->e = BN_new(); + if (!newKey->e || !BN_set_word(newKey->e, keyStruct->exponent) || !newKey->n) { + goto cleanup; + } +#endif +#endif + + *key = newKey; + ret = true; + +cleanup: + if (!ret && newKey) { + RSA_free(newKey); + } + return ret; +} + +void ReadDaemonKeys(const char *file, list *listPublicKey) +{ + char buf[BUF_SIZE_DEFAULT2]; + char *sep = nullptr; + int ret; + FILE *f = fopen(file, "re"); + if (!f) { + WRITE_LOG(LOG_DEBUG, "Can't open '%s'", file); + return; + } + while (fgets(buf, sizeof(buf), f)) { + RSAPublicKey *key = new RSAPublicKey(); + if (!key) { + break; + } + sep = strpbrk(buf, " \t"); + if (sep) { + *sep = '\0'; + } + ret = Base::Base64DecodeBuf(reinterpret_cast(buf), strlen(buf), (uint8_t *)key); + if (ret != sizeof(RSAPublicKey)) { + WRITE_LOG(LOG_DEBUG, "%s: Invalid base64 data ret=%d", file, ret); + delete key; + continue; + } + + if (key->wordModulusSize != RSANUMWORDS) { + WRITE_LOG(LOG_DEBUG, "%s: Invalid key len %d\n", file, key->wordModulusSize); + delete key; + continue; + } + listPublicKey->push_back(key); + } + fclose(f); +} + +bool AuthVerify(uint8_t *token, uint8_t *sig, int siglen) +{ + list listPublicKey; + uint8_t authKeyIndex = 0; + void *ptr = nullptr; + int ret = 0; + int childRet = 0; + while (KeylistIncrement(&listPublicKey, authKeyIndex, &ptr)) { + RSA *rsa = nullptr; + if (!RSAPublicKey2RSA((const uint8_t *)ptr, &rsa)) { + break; + } + childRet = RSA_verify(NID_sha1, (const unsigned char *)token, RSA_TOKEN_SIZE, (const unsigned char *)sig, + siglen, rsa); + RSA_free(rsa); + if (childRet) { + ret = 1; + break; + } + } + FreeKey(true, &listPublicKey); + return ret; +} + +void LoadDaemonKey(list *listPublicKey) +{ +#ifdef HDC_PCDEBUG + char keyPaths[][BUF_SIZE_SMALL] = { "/root/.harmony/hdckey.pub" }; +#else + char keyPaths[][BUF_SIZE_SMALL] = { "/hdc_keys", "/data/misc/hdc/hdc_keys" }; +#endif + int num = sizeof(keyPaths) / sizeof(keyPaths[0]); + struct stat buf; + + for (int i = 0; i < num; ++i) { + char *p = keyPaths[i]; + if (!stat(p, &buf)) { + WRITE_LOG(LOG_DEBUG, "Loading keys from '%s'", p); + ReadDaemonKeys(p, listPublicKey); + } + } +} + +bool PostUIConfirm(string publicKey) +{ + // Because the Hi3516 development board has no UI support for the time being, all public keys are received and + // By default, the system UI will record the public key /data/misc/hdc/hdckey/data/misc/hdc/hdckey + return true; +} +#endif // HDC_HOST + +// --------------------------------------common code------------------------------------------ +bool KeylistIncrement(list *listKey, uint8_t &authKeyIndex, void **out) +{ + if (!listKey->size()) { +#ifdef HDC_HOST + LoadHostUserKey(listKey); +#else + LoadDaemonKey(listKey); +#endif + } + if (authKeyIndex == listKey->size()) { + // all finish + return false; + } + auto listIndex = listKey->begin(); + std::advance(listIndex, ++authKeyIndex); + *out = *listIndex; + if (!*out) { + return false; + } + return true; +} + +void FreeKey(bool publicOrPrivate, list *listKey) +{ + for (auto &&v : *listKey) { + if (publicOrPrivate) { + delete (RSAPublicKey *)v; + v = nullptr; + } else { + RSA_free((RSA *)v); + v = nullptr; + } + } + listKey->clear(); +} +} diff --git a/services/flashd/common/auth.h b/services/flashd/common/auth.h new file mode 100755 index 00000000..1e2083b6 --- /dev/null +++ b/services/flashd/common/auth.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_AUTH_H +#define HDC_AUTH_H +#include "common.h" + +// If these functions occupy too high a load, you can consider placing them in a thread for execution, and perform +// subsequent processing in the callback directly after completion. +namespace HdcAuth { +const uint8_t RSA_TOKEN_SIZE = 20; // SHA_DIGEST_LENGTH +// in host out==RSA*, in daemon out=RSAPublicKey* +bool KeylistIncrement(list *listKey, uint8_t &authKeyIndex, void **out); +void FreeKey(bool publicOrPrivate, list *listKey); + +// host +bool GenerateKey(const char *file); +int AuthSign(void *rsa, const unsigned char *token, size_t tokenSize, void *sig); +int GetPublicKeyFileBuf(unsigned char *data, size_t len); + +// daemon +bool AuthVerify(uint8_t *token, uint8_t *sig, int siglen); +bool PostUIConfirm(string pkey); +} + +#endif \ No newline at end of file diff --git a/services/flashd/common/base.cpp b/services/flashd/common/base.cpp new file mode 100755 index 00000000..b0e7f153 --- /dev/null +++ b/services/flashd/common/base.cpp @@ -0,0 +1,1249 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "base.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __MUSL__ +extern "C" { +#include "parameter.h" +} +#endif +using namespace std::chrono; + +namespace Hdc { +namespace Base { + uint8_t g_logLevel = 0; + void SetLogLevel(const uint8_t logLevel) + { + g_logLevel = logLevel; + } + +// Commenting the code will optimize and tune all log codes, and the compilation volume will be greatly reduced +#define ENABLE_DEBUGLOG +#ifdef ENABLE_DEBUGLOG + void GetLogDebugFunctioname(string &debugInfo, int line, string &threadIdString) + { + string tmpString = GetFileNameAny(debugInfo); + debugInfo = StringFormat("%s:%d", tmpString.c_str(), line); + if (g_logLevel < LOG_FULL) { + debugInfo = ""; + threadIdString = ""; + } else { + debugInfo = "[" + debugInfo + "]"; + threadIdString = StringFormat("[%x]", std::hash {}(std::this_thread::get_id())); + } + } + + bool IsWindowsSupportAnsiColor() + { +#ifdef _WIN32 + // Set output mode to handle virtual terminal sequences + HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); + if (hOut == INVALID_HANDLE_VALUE) { + return false; + } + DWORD dwMode = 0; + if (!GetConsoleMode(hOut, &dwMode)) { + return false; + } + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if (!SetConsoleMode(hOut, dwMode)) { + return false; + } +#endif + return true; + } + + void GetLogLevelAndTime(uint8_t logLevel, string &logLevelString, string &timeString) + { + system_clock::time_point timeNow = system_clock::now(); // now time + system_clock::duration sinceUnix0 = timeNow.time_since_epoch(); // since 1970 + time_t sSinceUnix0 = duration_cast(sinceUnix0).count(); + std::tm tim = *std::localtime(&sSinceUnix0); + bool enableAnsiColor = false; +#ifdef _WIN32 + enableAnsiColor = IsWindowsSupportAnsiColor(); +#else + enableAnsiColor = true; +#endif + if (enableAnsiColor) { + switch (logLevel) { + case LOG_FATAL: + logLevelString = "\033[1;31mF\033[0m"; + break; + case LOG_INFO: + logLevelString = "\033[1;32mI\033[0m"; + break; + case LOG_WARN: + logLevelString = "\033[1;33mW\033[0m"; + break; + case LOG_DEBUG: + logLevelString = "\033[1;36mD\033[0m"; + break; + default: + logLevelString = "\033[1;36mD\033[0m"; + break; + } + } else { + logLevelString = std::to_string(logLevel); + } + string msTimeSurplus; + if (g_logLevel > LOG_DEBUG) { + const auto sSinceUnix0Rest = duration_cast(sinceUnix0).count() % (TIME_BASE * TIME_BASE); + msTimeSurplus = StringFormat(".%06llu", sSinceUnix0Rest); + } + timeString = StringFormat("%d:%d:%d%s", tim.tm_hour, tim.tm_min, tim.tm_sec, msTimeSurplus.c_str()); + } + + void PrintLogEx(const char *functionName, int line, uint8_t logLevel, const char *msg, ...) + { + if (logLevel > g_logLevel) { + return; + } + string debugInfo; + string logBuf; + string logLevelString; + string threadIdString; + string sep = "\n"; + string timeString; + + va_list vaArgs; + va_start(vaArgs, msg); + string logDetail = Base::StringFormat(msg, vaArgs); + va_end(vaArgs); + if (logDetail.back() == '\n') { + sep = "\r\n"; + } + debugInfo = functionName; + GetLogDebugFunctioname(debugInfo, line, threadIdString); + GetLogLevelAndTime(logLevel, logLevelString, timeString); + logBuf = StringFormat("[%s][%s]%s%s %s%s", logLevelString.c_str(), timeString.c_str(), threadIdString.c_str(), + debugInfo.c_str(), logDetail.c_str(), sep.c_str()); + + printf("%s", logBuf.c_str()); + fflush(stdout); + // logfile, not thread-safe +#ifdef HDC_SUPPORT_FLASHD + FILE *fp = fopen("/tmp/flashd_hdc.log", "a"); +#else + string path = GetTmpDir() + LOG_FILE_NAME; + FILE *fp = fopen(path.c_str(), "a"); +#endif + if (fp == nullptr) { + return; + } + if (fprintf(fp, "%s", logBuf.c_str()) > 0 && fflush(fp)) { + // make ci happy + } + fclose(fp); + return; + } +#else // else ENABLE_DEBUGLOG.If disabled, the entire output code will be optimized by the compiler + void PrintLogEx(uint8_t logLevel, char *msg, ...) + { + } +#endif // ENABLE_DEBUGLOG + + void PrintMessage(const char *fmt, ...) + { + va_list ap; + va_start(ap, fmt); + if (vfprintf(stdout, fmt, ap) > 0) { + fprintf(stdout, "\n"); + } + va_end(ap); + } + + // if can linkwith -lstdc++fs, use std::filesystem::path(path).filename(); + string GetFileNameAny(string &path) + { + string tmpString = path; + size_t tmpNum = tmpString.rfind('/'); + if (tmpNum == std::string::npos) { + tmpNum = tmpString.rfind('\\'); + if (tmpNum == std::string::npos) { + return tmpString; + } + } + tmpString = tmpString.substr(tmpNum + 1, tmpString.size() - tmpNum); + return tmpString; + } + + int GetMaxBufSize() + { + return MAX_SIZE_IOBUF; + } + + void SetTcpOptions(uv_tcp_t *tcpHandle) + { + constexpr int maxBufFactor = 10; + if (!tcpHandle) { + WRITE_LOG(LOG_WARN, "SetTcpOptions nullptr Ptr"); + return; + } + uv_tcp_keepalive(tcpHandle, 1, GLOBAL_TIMEOUT); + // if MAX_SIZE_IOBUF==5k,bufMaxSize at least 40k. It must be set to io 8 times is more appropriate, + // otherwise asynchronous IO is too fast, a lot of IO is wasted on IOloop, transmission speed will decrease + int bufMaxSize = GetMaxBufSize() * maxBufFactor; + uv_recv_buffer_size((uv_handle_t *)tcpHandle, &bufMaxSize); + uv_send_buffer_size((uv_handle_t *)tcpHandle, &bufMaxSize); + } + + void ReallocBuf(uint8_t **origBuf, int *nOrigSize, const int indexUsedBuf, int sizeWanted) + { + sizeWanted = GetMaxBufSize(); + int remainLen = *nOrigSize - indexUsedBuf; + // init:0, left less than expected + if (!*nOrigSize || (remainLen < sizeWanted && (*nOrigSize + sizeWanted < sizeWanted * 2))) { + // Memory allocation size is slightly larger than the maximum + int nNewLen = *nOrigSize + sizeWanted + EXTRA_ALLOC_SIZE; + uint8_t *bufPtrOrig = *origBuf; + *origBuf = new uint8_t[nNewLen](); + if (!*origBuf) { + *origBuf = bufPtrOrig; + } else { + *nOrigSize = nNewLen; + if (bufPtrOrig) { + if (memcpy_s(*origBuf, nNewLen, bufPtrOrig, *nOrigSize)) { + WRITE_LOG(LOG_FATAL, "ReallocBuf failed"); + } + delete[] bufPtrOrig; + } + } + uint8_t *buf = static_cast(*origBuf + indexUsedBuf); + Base::ZeroBuf(buf, nNewLen - indexUsedBuf); + } + } + + // As an uv_alloc_cb it must keep the same as prototype + void AllocBufferCallback(uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf) + { + const int size = GetMaxBufSize(); + buf->base = (char *)new uint8_t[size](); + if (buf->base) { + buf->len = size - 1; + } + } + + // As an uv_write_cb it must keep the same as prototype + void SendCallback(uv_write_t *req, int status) + { + delete[]((uint8_t *)req->data); + delete req; + } + + // xxx must keep sync with uv_loop_close/uv_walk etc. + bool TryCloseLoop(uv_loop_t *ptrLoop, const char *callerName) + { + // UV_RUN_DEFAULT: Runs the event loop until the reference count drops to zero. Always returns zero. + // UV_RUN_ONCE: Poll for new events once. Note that this function blocks if there are no pending events. + // Returns zero when done (no active handles or requests left), or non-zero if more events are + // expected meaning you should run the event loop again sometime in the future). + // UV_RUN_NOWAIT: Poll for new events once but don't block if there are no pending events. + uint8_t closeRetry = 0; + bool ret = false; + constexpr int maxRetry = 3; + for (closeRetry = 0; closeRetry < maxRetry; ++closeRetry) { + if (uv_loop_close(ptrLoop) == UV_EBUSY) { + if (closeRetry > 2) { // 2 try count + WRITE_LOG(LOG_WARN, "%s close busy,try:%d", callerName, closeRetry); + } + + if (ptrLoop->active_handles >= 2) { + WRITE_LOG(LOG_DEBUG, "TryCloseLoop issue"); + } + auto clearLoopTask = [](uv_handle_t *handle, void *arg) -> void { TryCloseHandle(handle); }; + uv_walk(ptrLoop, clearLoopTask, nullptr); + // If all processing ends, Then return0,this call will block + if (!ptrLoop->active_handles) { + ret = true; + break; + } + if (!uv_run(ptrLoop, UV_RUN_ONCE)) { + ret = true; + break; + } + } else { + ret = true; + break; + } + } + return ret; + } + + // Some handles may not be initialized or activated yet or have been closed, skip the closing process + void TryCloseHandle(const uv_handle_t *handle) + { + TryCloseHandle(handle, nullptr); + } + + void TryCloseHandle(const uv_handle_t *handle, uv_close_cb closeCallBack) + { + TryCloseHandle(handle, false, closeCallBack); + } + + void TryCloseHandle(const uv_handle_t *handle, bool alwaysCallback, uv_close_cb closeCallBack) + { + bool hasCallClose = false; + if (handle->loop && !uv_is_closing(handle)) { + uv_close((uv_handle_t *)handle, closeCallBack); + hasCallClose = true; + } + if (!hasCallClose && alwaysCallback) { + closeCallBack((uv_handle_t *)handle); + } + } + + int SendToStream(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen) + { + if (bufLen > static_cast(HDC_BUF_MAX_BYTES)) { + return ERR_BUF_ALLOC; + } + uint8_t *pDynBuf = new uint8_t[bufLen]; + if (!pDynBuf) { + return ERR_BUF_ALLOC; + } + if (memcpy_s(pDynBuf, bufLen, buf, bufLen)) { + delete[] pDynBuf; + return ERR_BUF_COPY; + } + return SendToStreamEx(handleStream, pDynBuf, bufLen, nullptr, (void *)SendCallback, (void *)pDynBuf); + } + + // handleSend is used for pipe thread sending, set nullptr for tcp, and dynamically allocated by malloc when buf + // is required + int SendToStreamEx(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen, uv_stream_t *handleSend, + const void *finishCallback, const void *pWriteReqData) + { + int ret = -1; + uv_write_t *reqWrite = new uv_write_t(); + if (!reqWrite) { + return 0; + } + uv_buf_t bfr; + while (true) { + reqWrite->data = (void *)pWriteReqData; + bfr.base = (char *)buf; + bfr.len = bufLen; + if (!uv_is_writable(handleStream)) { + delete reqWrite; + break; + } + // handleSend must be a TCP socket or pipe, which is a server or a connection (listening or + // connected state). Bound sockets or pipes will be assumed to be servers. + if (handleSend) { + uv_write2(reqWrite, handleStream, &bfr, 1, handleSend, (uv_write_cb)finishCallback); + } else { + uv_write(reqWrite, handleStream, &bfr, 1, (uv_write_cb)finishCallback); + } + ret = bufLen; + break; + } + return ret; + } + + uint64_t GetRuntimeMSec() + { + struct timespec times = { 0, 0 }; + long time; + clock_gettime(CLOCK_MONOTONIC, ×); + time = times.tv_sec * TIME_BASE + times.tv_nsec / (TIME_BASE * TIME_BASE); + return time; + } + + uint64_t GetRandom(const uint64_t min, const uint64_t max) + { +#ifdef HARMONY_PROJECT + uint64_t ret; + uv_random(nullptr, nullptr, &ret, sizeof(ret), 0, nullptr); +#else + uint64_t ret; + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(min, max); + ret = dis(gen); +#endif + return ret; + } + + string GetRandomString(const uint16_t expectedLen) + { + srand(static_cast(GetRandom())); + string ret = string(expectedLen, '0'); + std::stringstream val; + for (auto i = 0; i < expectedLen; ++i) { + val << std::hex << (rand() % BUF_SIZE_MICRO); + } + ret = val.str(); + return ret; + } + + int GetRandomNum(const int min, const int max) + { + return static_cast(GetRandom(min, max)); + } + + int ConnectKey2IPPort(const char *connectKey, char *outIP, uint16_t *outPort) + { + char bufString[BUF_SIZE_TINY] = ""; + if (memcpy_s(bufString, sizeof(bufString), connectKey, sizeof(bufString))) { + return ERR_BUF_COPY; + } + char *p = strchr(bufString, ':'); + if (!p) { + return ERR_PARM_FORMAT; + } + *p = '\0'; + if (!strlen(bufString) || strlen(bufString) > 16) { + return ERR_PARM_SIZE; + } + uint16_t wPort = static_cast(atoi(p + 1)); + if (EOK != strcpy_s(outIP, BUF_SIZE_TINY, bufString)) { + return ERR_BUF_COPY; + } + *outPort = wPort; + return RET_SUCCESS; + } + + // After creating the session worker thread, execute it on the main thread + void FinishWorkThread(uv_work_t *req, int status) + { + // This is operated in the main thread + delete req; + } + + // at the finsh of pFuncAfterThread must free uv_work_t* + // clang-format off + int StartWorkThread(uv_loop_t *loop, uv_work_cb pFuncWorkThread, + uv_after_work_cb pFuncAfterThread, void *pThreadData) + { + uv_work_t *workThread = new uv_work_t(); + if (!workThread) { + return -1; + } + workThread->data = pThreadData; + uv_queue_work(loop, workThread, pFuncWorkThread, pFuncAfterThread); + return 0; + } + // clang-format on + + char **SplitCommandToArgs(const char *cmdStringLine, int *slotIndex) + { + constexpr int extraBufSize = 2; + char **argv; + char *temp = nullptr; + int argc = 0; + char a = 0; + size_t i = 0; + size_t j = 0; + size_t len = 0; + bool isQuoted = false; + bool isText = false; + bool isSpace = false; + + len = strlen(cmdStringLine); + if (len < 1) { + return nullptr; + } + i = ((len + extraBufSize) / extraBufSize) * sizeof(void *) + sizeof(void *); + argv = reinterpret_cast(new char[i + (len + extraBufSize) * sizeof(char)]); + temp = reinterpret_cast((reinterpret_cast(argv)) + i); + argc = 0; + argv[argc] = temp; + isQuoted = false; + isText = false; + isSpace = true; + i = 0; + j = 0; + + while ((a = cmdStringLine[i]) != 0) { + if (isQuoted) { + if (a == '\"') { + isQuoted = false; + } else { + temp[j] = a; + ++j; + } + } else { + switch (a) { + case '\"': + isQuoted = true; + isText = true; + if (isSpace) { + argv[argc] = temp + j; + ++argc; + } + isSpace = false; + break; + case ' ': + case '\t': + case '\n': + case '\r': + if (isText) { + temp[j] = '\0'; + ++j; + } + isText = false; + isSpace = true; + break; + default: + isText = true; + if (isSpace) { + argv[argc] = temp + j; + ++argc; + } + temp[j] = a; + ++j; + isSpace = false; + break; + } + } + ++i; + } + temp[j] = '\0'; + argv[argc] = nullptr; + + (*slotIndex) = argc; + return argv; + } + + bool RunPipeComand(const char *cmdString, char *outBuf, uint16_t sizeOutBuf, bool ignoreTailLf) + { + FILE *pipeHandle = popen(cmdString, "r"); + if (pipeHandle == nullptr) { + return false; + } + int bytesRead = 0; + int bytesOnce = 0; + while (!feof(pipeHandle)) { + bytesOnce = fread(outBuf, 1, sizeOutBuf - bytesRead, pipeHandle); + if (bytesOnce <= 0) { + break; + } + bytesRead += bytesOnce; + } + if (bytesRead && ignoreTailLf) { + if (outBuf[bytesRead - 1] == '\n') { + outBuf[bytesRead - 1] = '\0'; + } + } + pclose(pipeHandle); + return bytesRead; + } + + bool SetHdcProperty(const char *key, const char *value) + { +#ifndef __MUSL__ +#ifdef HDC_PCDEBUG + WRITE_LOG(LOG_DEBUG, "Setproperty, key:%s value:%s", key, value); +#else + string sKey = key; + string sValue = value; + string sBuf = "setprop " + sKey + " " + value; + system(sBuf.c_str()); +#endif +#else + SetParameter(key, value); +#endif + return true; + } + + bool GetHdcProperty(const char *key, char *value, uint16_t sizeOutBuf) + { +#ifndef __MUSL__ +#ifdef HDC_PCDEBUG + WRITE_LOG(LOG_DEBUG, "Getproperty, key:%s value:%s", key, value); +#else + string sKey = key; + string sBuf = "getprop " + sKey; + RunPipeComand(sBuf.c_str(), value, sizeOutBuf, true); +#endif +#else + string sKey = key; + string sBuf = "param get " + sKey; + RunPipeComand(sBuf.c_str(), value, sizeOutBuf, true); +#endif + value[sizeOutBuf - 1] = '\0'; + return true; + } + + // bufLen == 0: alloc buffer in heap, need free it later + // >0: read max nBuffLen bytes to *buff + // ret value: <0 or bytes read + int ReadBinFile(const char *pathName, void **buf, const int bufLen) + { + uint8_t *pDst = nullptr; + int byteIO = 0; + struct stat statbuf; + int ret = stat(pathName, &statbuf); + if (ret < 0) { + return -1; + } + int nFileSize = statbuf.st_size; + int readMax = 0; + uint8_t dynamicBuf = 0; + ret = -3; + if (bufLen == 0) { + dynamicBuf = 1; + pDst = new uint8_t[nFileSize + 1](); // tail \0 + if (!pDst) { + return -1; + } + readMax = nFileSize; + } else { + if (nFileSize > bufLen) { + return -2; + } + readMax = nFileSize; + pDst = reinterpret_cast(buf); // The first address of the static array is the array address + } + + string srcPath(pathName); + string resolvedPath = CanonicalizeSpecPath(srcPath); + FILE *fp = fopen(resolvedPath.c_str(), "r"); + if (fp == nullptr) { + goto ReadFileFromPath_Finish; + } + byteIO = fread(pDst, 1, readMax, fp); + fclose(fp); + if (byteIO != readMax) { + goto ReadFileFromPath_Finish; + } + ret = 0; + ReadFileFromPath_Finish: + if (ret) { + if (dynamicBuf) { + delete[] pDst; + } + } else { + if (dynamicBuf) { + *buf = pDst; + } + ret = byteIO; + } + return ret; + } + + int WriteBinFile(const char *pathName, const uint8_t *buf, const int bufLen, bool newFile) + { + string mode; + string resolvedPath; + string srcPath(pathName); + if (newFile) { + mode = "wb+"; + // no std::fs supoort, else std::filesystem::canonical,-lstdc++fs + if (srcPath.find("..") != string::npos) { + return ERR_FILE_PATH_CHECK; + } + resolvedPath = srcPath.c_str(); + } else { + mode = "a+"; + resolvedPath = CanonicalizeSpecPath(srcPath); + } + FILE *fp = fopen(resolvedPath.c_str(), mode.c_str()); + if (fp == nullptr) { + WRITE_LOG(LOG_DEBUG, "Write to %s failed!", pathName); + return ERR_FILE_OPEN; + } + int bytesDone = fwrite(buf, 1, bufLen, fp); + fflush(fp); + fclose(fp); + if (bytesDone != bufLen) { + return ERR_BUF_SIZE; + } + return RET_SUCCESS; + } + + void CloseIdleCallback(uv_handle_t *handle) + { + delete (uv_idle_t *)handle; + }; + + void CloseTimerCallback(uv_handle_t *handle) + { + delete (uv_timer_t *)handle; + }; + + // return value: <0 error; 0 can start new server instance; >0 server already exists + int ProgramMutex(const char *procname, bool checkOrNew) + { + char bufPath[BUF_SIZE_DEFAULT] = ""; + char buf[BUF_SIZE_DEFAULT] = ""; + char pidBuf[BUF_SIZE_TINY] = ""; + size_t size = sizeof(buf); + if (uv_os_tmpdir(buf, &size) < 0) { + WRITE_LOG(LOG_FATAL, "Tmppath failed"); + return ERR_API_FAIL; + } + if (snprintf_s(bufPath, sizeof(bufPath), sizeof(bufPath) - 1, "%s%c.%s.pid", buf, Base::GetPathSep(), procname) + < 0) { + return ERR_BUF_OVERFLOW; + } + int pid = static_cast(getpid()); + if (snprintf_s(pidBuf, sizeof(pidBuf), sizeof(pidBuf) - 1, "%d", pid) < 0) { + return ERR_BUF_OVERFLOW; + } + // no need to CanonicalizeSpecPath, else not work + umask(0); + int fd = open(bufPath, O_RDWR | O_CREAT, 0666); // 0666:permission + if (fd < 0) { + WRITE_LOG(LOG_FATAL, "Open mutex file \"%s\" failed!!!Errno:%d\n", buf, errno); + return ERR_FILE_OPEN; + } +#ifdef _WIN32 + if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "Global\\%s", procname) < 0) { + return ERR_BUF_OVERFLOW; + } + HANDLE hMutex = CreateMutex(nullptr, FALSE, buf); + DWORD dwError = GetLastError(); + if (ERROR_ALREADY_EXISTS == dwError || ERROR_ACCESS_DENIED == dwError) { + WRITE_LOG(LOG_DEBUG, "File \"%s\" locked. proc already exit!!!\n", procname); + return 1; + } + if (checkOrNew) { + CloseHandle(hMutex); + } +#else + struct flock fl; + fl.l_type = F_WRLCK; + fl.l_start = 0; + fl.l_whence = SEEK_SET; + fl.l_len = 0; + int retChild = fcntl(fd, F_SETLK, &fl); + if (-1 == retChild) { + WRITE_LOG(LOG_DEBUG, "File \"%s\" locked. proc already exit!!!\n", bufPath); + close(fd); + return 1; + } +#endif + ftruncate(fd, 0); + write(fd, pidBuf, strlen(pidBuf) + 1); + WRITE_LOG(LOG_DEBUG, "Write mutext to %s, pid:%s", bufPath, pidBuf); + if (checkOrNew) { + // close it for check only + close(fd); + } + // Do not close the file descriptor, the process will be mutext effect under no-Win32 OS + return RET_SUCCESS; + } + + void SplitString(const string &origString, const string &seq, vector &resultStrings) + { + string::size_type p1 = 0; + string::size_type p2 = origString.find(seq); + + while (p2 != string::npos) { + if (p2 == p1) { + ++p1; + p2 = origString.find(seq, p1); + continue; + } + resultStrings.push_back(origString.substr(p1, p2 - p1)); + p1 = p2 + seq.size(); + p2 = origString.find(seq, p1); + } + + if (p1 != origString.size()) { + resultStrings.push_back(origString.substr(p1)); + } + } + + string GetShellPath() + { + struct stat filecheck; + string shellPath = "/bin/sh"; + if (stat(shellPath.c_str(), &filecheck) < 0) { + shellPath = "/system/bin/sh"; + if (stat(shellPath.c_str(), &filecheck) < 0) { + shellPath = "sh"; + } + } + return shellPath; + } + + // Not supported on some platforms, Can only be achieved manually + uint64_t HostToNet(uint64_t val) + { + if (htonl(1) == 1) + return val; + return (((uint64_t)htonl(val)) << 32) + htonl(val >> 32); + } + + uint64_t NetToHost(uint64_t val) + { + if (htonl(1) == 1) + return val; + return (((uint64_t)ntohl(val)) << 32) + ntohl(val >> 32); + } + + char GetPathSep() + { +#ifdef _WIN32 + const char sep = '\\'; +#else + const char sep = '/'; +#endif + return sep; + } + + string GetFullFilePath(const string &s) + { // cannot use s.rfind(std::filesystem::path::preferred_separator + size_t i = s.rfind(GetPathSep(), s.length()); + if (i != string::npos) { + return (s.substr(i + 1, s.length() - i)); + } + return s; + } + + int CreateSocketPair(int *fds) + { +#ifndef _WIN32 +#ifdef HOST_MAC + int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); + if (ret == 0) { + for (auto i = 0; i < 2; ++i) { + if (fcntl(fds[i], F_SETFD, FD_CLOEXEC) == -1) { + close(fds[0]); + close(fds[1]); + WRITE_LOG(LOG_WARN, "fcntl failed to set FD_CLOEXEC: %s", strerror(errno)); + return -1; + } + } + } + return ret; +#else + return socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds); +#endif +#else + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + int reuse = 1; + if (fds == 0) { + return -1; + } + int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (listener == -1) { + return -2; + } + Base::ZeroStruct(addr); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.sin_port = 0; + fds[0] = fds[1] = (int)-1; + do { + if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, (socklen_t)sizeof(reuse))) { + break; + } + if (::bind(listener, (struct sockaddr *)&addr, sizeof(addr))) { + break; + } + if (getsockname(listener, (struct sockaddr *)&addr, &addrlen)) { + break; + } + if (listen(listener, 1)) { + break; + } + fds[0] = socket(AF_INET, SOCK_STREAM, 0); + if (fds[0] == -1) { + break; + } + if (connect(fds[0], (struct sockaddr *)&addr, sizeof(addr)) == -1) { + break; + } + fds[1] = accept(listener, nullptr, nullptr); + if (fds[1] == -1) { + break; + } + closesocket(listener); + return 0; + } while (0); + + closesocket(listener); + closesocket(fds[0]); + closesocket(fds[1]); + return -1; +#endif + } + + void CloseSocketPair(const int *fds) + { +#ifndef _WIN32 + close(fds[0]); + close(fds[1]); +#else + closesocket(fds[0]); + closesocket(fds[1]); +#endif + } + + int StringEndsWith(string s, string sub) + { + return s.rfind(sub) == (s.length() - sub.length()) ? 1 : 0; + } + + // Both absolute and relative paths support + bool CheckDirectoryOrPath(const char *localPath, bool pathOrDir, bool readWrite) + { + if (pathOrDir) { // filepath + uv_fs_t req; + int r = uv_fs_lstat(nullptr, &req, localPath, nullptr); + uv_fs_req_cleanup(&req); + if (r == 0 && req.statbuf.st_mode & S_IFREG) { // is file + uv_fs_access(nullptr, &req, localPath, readWrite ? R_OK : W_OK, nullptr); + uv_fs_req_cleanup(&req); + if (req.result == 0) + return true; + } + } else { // dir + } + return false; + } + + // Using openssl encryption and decryption method, high efficiency; when encrypting more than 64 bytes, + // the carriage return will not be added, and the tail padding 00 is removed when decrypting + // The return value is the length of the string after Base64 + int Base64EncodeBuf(const uint8_t *input, const int length, uint8_t *bufOut) + { + return EVP_EncodeBlock(bufOut, input, length); + } + + vector Base64Encode(const uint8_t *input, const int length) + { + vector retVec; + uint8_t *pBuf = nullptr; + while (true) { + if (static_cast(length) > HDC_BUF_MAX_BYTES) { + break; + } + int base64Size = length * 1.4 + 256; + if (!(pBuf = new uint8_t[base64Size]())) { + break; + } + int childRet = Base64EncodeBuf(input, length, pBuf); + if (childRet <= 0) { + break; + } + retVec.insert(retVec.begin(), pBuf, pBuf + childRet); + break; + } + if (pBuf) { + delete[] pBuf; + } + + return retVec; + } + + inline int CalcDecodeLength(const uint8_t *b64input) + { + int len = strlen(reinterpret_cast(const_cast(b64input))); + if (!len) { + return 0; + } + int padding = 0; + if (b64input[len - 1] == '=' && b64input[len - 2] == '=') { + // last two chars are = + padding = 2; // 2 : last two chars + } else if (b64input[len - 1] == '=') { + // last char is = + padding = 1; + } + return static_cast(len * 0.75 - padding); + } + + // return -1 error; >0 decode size + int Base64DecodeBuf(const uint8_t *input, const int length, uint8_t *bufOut) + { + int nRetLen = CalcDecodeLength(input); + if (!nRetLen) { + return 0; + } + + if (EVP_DecodeBlock(bufOut, input, length) > 0) { + return nRetLen; + } + return 0; + } + + string Base64Decode(const uint8_t *input, const int length) + { + string retString; + uint8_t *pBuf = nullptr; + while (true) { + if ((uint32_t)length > HDC_BUF_MAX_BYTES) { + break; + } + // must less than length + if (!(pBuf = new uint8_t[length]())) { + break; + } + int childRet = Base64DecodeBuf(input, length, pBuf); + if (childRet <= 0) { + break; + } + retString = (reinterpret_cast(pBuf)); + break; + } + if (pBuf) { + delete[] pBuf; + } + return retString; + } + + void ReverseBytes(void *start, int size) + { + uint8_t *istart = (uint8_t *)start; + uint8_t *iend = istart + size; + std::reverse(istart, iend); + } + + // clang-format off + const string StringFormat(const char * const formater, ...) + { + va_list vaArgs; + va_start(vaArgs, formater); + string ret = StringFormat(formater, vaArgs); + va_end(vaArgs); + return ret; + } + + const string StringFormat(const char * const formater, va_list &vaArgs) + { + std::vector args(MAX_SIZE_IOBUF); + const int retSize = vsnprintf_s(args.data(), MAX_SIZE_IOBUF, args.size() - 1, formater, vaArgs); + if (retSize < 0) { + return std::string(""); + } else { + return std::string(args.data(), retSize); + } + } + // clang-format on + + string GetVersion() + { + const uint8_t a = 'a'; + uint8_t major = (HDC_VERSION_NUMBER >> 28) & 0xff; + uint8_t minor = (HDC_VERSION_NUMBER << 4 >> 24) & 0xff; + uint8_t version = (HDC_VERSION_NUMBER << 12 >> 24) & 0xff; + uint8_t fix = (HDC_VERSION_NUMBER << 20 >> 28) & 0xff; // max 16, tail is p + string ver = StringFormat("%x.%x.%x%c", major, minor, version, a + fix); + return "Ver: " + ver; + } + + bool IdleUvTask(uv_loop_t *loop, void *data, uv_idle_cb cb) + { + uv_idle_t *idle = new uv_idle_t(); + if (idle == nullptr) { + return false; + } + idle->data = data; + uv_idle_init(loop, idle); + uv_idle_start(idle, cb); + // delete by callback + return true; + } + + bool TimerUvTask(uv_loop_t *loop, void *data, uv_timer_cb cb, int repeatTimeout) + { + uv_timer_t *timer = new uv_timer_t(); + if (timer == nullptr) { + return false; + } + timer->data = data; + uv_timer_init(loop, timer); + uv_timer_start(timer, cb, 0, repeatTimeout); + // delete by callback + return true; + } + + // callback, uint8_t flag, string msg, const void * data + bool DelayDo(uv_loop_t *loop, const int delayMs, const uint8_t flag, string msg, void *data, + std::function cb) + { + struct DelayDoParam { + uv_timer_t handle; + uint8_t flag; + string msg; + void *data; + std::function cb; + }; + auto funcDelayDo = [](uv_timer_t *handle) -> void { + DelayDoParam *st = (DelayDoParam *)handle->data; + st->cb(st->flag, st->msg, st->data); + uv_close((uv_handle_t *)handle, [](uv_handle_t *handle) { + DelayDoParam *st = (DelayDoParam *)handle->data; + delete st; + }); + }; + DelayDoParam *st = new DelayDoParam(); + if (st == nullptr) { + return false; + } + st->cb = cb; + st->flag = flag; + st->msg = msg; + st->data = data; + st->handle.data = st; + uv_timer_init(loop, &st->handle); + uv_timer_start(&st->handle, funcDelayDo, delayMs, 0); + return true; + } + + string ReplaceAll(string str, const string from, const string to) + { + string::size_type startPos = 0; + while ((startPos = str.find(from, startPos)) != string::npos) { + str.replace(startPos, from.length(), to); + startPos += to.length(); // Handles case where 'to' is a substring of 'from' + } + return str; + } + + string CanonicalizeSpecPath(string &src) + { + char resolvedPath[PATH_MAX] = { 0 }; +#if defined(_WIN32) + if (!_fullpath(resolvedPath, src.c_str(), PATH_MAX)) { + WRITE_LOG(LOG_FATAL, "_fullpath %s failed", src.c_str()); + return ""; + } +#else + if (realpath(src.c_str(), resolvedPath) == nullptr) { + WRITE_LOG(LOG_FATAL, "realpath %s failed", src.c_str()); + return ""; + } +#endif + string res(resolvedPath); + return res; + } + + uint8_t CalcCheckSum(const uint8_t *data, int len) + { + uint8_t ret = 0; + for (int i = 0; i < len; ++i) { + ret += data[i]; + } + return ret; + } + + int open_osfhandle(uv_os_fd_t os_fd) + { + // equal libuv's uv_open_osfhandle, libuv 1.23 added. old libuv not impl... +#ifdef _WIN32 + return _open_osfhandle((intptr_t)os_fd, 0); +#else + return os_fd; +#endif + } + + uv_os_sock_t DuplicateUvSocket(uv_tcp_t *tcp) + { + uv_os_sock_t dupFd = -1; +#ifdef _WIN32 + WSAPROTOCOL_INFO info; + ZeroStruct(info); + if (WSADuplicateSocketA(tcp->socket, GetCurrentProcessId(), &info) < 0) { + return dupFd; + } + dupFd = WSASocketA(0, 0, 0, &info, 0, 0); +#else + uv_os_fd_t fdOs; + if (uv_fileno((const uv_handle_t *)tcp, &fdOs) < 0) { + return ERR_API_FAIL; + } + dupFd = dup(open_osfhandle(fdOs)); +#endif + return dupFd; + } + + vector Md5Sum(uint8_t *buf, int size) + { + vector ret; + uint8_t md5Hash[MD5_DIGEST_LENGTH] = { 0 }; + if (EVP_Digest(buf, size, md5Hash, NULL, EVP_md5(), NULL)) { + ret.insert(ret.begin(), md5Hash, md5Hash + sizeof(md5Hash)); + } + return ret; + } + + string GetCwd() + { + char path[PATH_MAX] = ""; + size_t size = sizeof(path); + string res; + if (uv_cwd(path, &size) < 0) { + return res; + } + if (path[strlen(path) - 1] != Base::GetPathSep()) { + path[strlen(path)] = Base::GetPathSep(); + } + res = path; + return res; + } + + string GetTmpDir() + { + string res; +#ifdef HDC_HOST + char path[PATH_MAX] = ""; + size_t size = sizeof(path); + if (uv_os_tmpdir(path, &size) < 0) { + WRITE_LOG(LOG_FATAL, "get tmppath failed!"); + return res; + } + if (path[strlen(path) - 1] != Base::GetPathSep()) { + path[strlen(path)] = Base::GetPathSep(); + } + res = path; +#else + res = "/data/local/tmp/"; +#endif + return res; + } + + bool IsRoot() + { +#ifdef _WIN32 + // reserve + return true; +#else + if (getuid() == 0) { + return true; + } +#endif + return false; + } + + bool IsAbsolutePath(string &path) + { + bool ret = false; +#ifdef _WIN32 + // shlwapi.h PathIsRelativeA not link in harmony project + // c:\ or UNC path '\\hostname\share\file' + ret = path.find(":\\") == 1 || path.find("\\\\") == 0; +#else + ret = path[0] == '/'; +#endif + return ret; + } +} +} // namespace Hdc diff --git a/services/flashd/common/base.h b/services/flashd/common/base.h new file mode 100755 index 00000000..9a6b12be --- /dev/null +++ b/services/flashd/common/base.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_BASE_H +#define HDC_BASE_H +#include "common.h" + +namespace Hdc { +namespace Base { + void SetLogLevel(const uint8_t logLevel); + void PrintLogEx(const char *functionName, int line, uint8_t logLevel, const char *msg, ...); + void PrintMessage(const char *fmt, ...); + // tcpHandle can't be const as it's passed into uv_tcp_keepalive + void SetTcpOptions(uv_tcp_t *tcpHandle); + // Realloc need to update origBuf&origSize which can't be const + void ReallocBuf(uint8_t **origBuf, int *nOrigSize, const int indexUsedBuf, int sizeWanted); + // handle&sendHandle must keep sync with uv_write + int SendToStreamEx(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen, uv_stream_t *handleSend, + const void *finishCallback, const void *pWriteReqData); + int SendToStream(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen); + // As an uv_write_cb it must keep the same as prototype + void SendCallback(uv_write_t *req, int status); + // As an uv_alloc_cb it must keep the same as prototype + void AllocBufferCallback(uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf); + uint64_t GetRuntimeMSec(); + string GetRandomString(const uint16_t expectedLen); + int GetRandomNum(const int min, const int max); + uint64_t GetRandom(const uint64_t min = 0, const uint64_t max = UINT64_MAX); + int ConnectKey2IPPort(const char *connectKey, char *outIP, uint16_t *outPort); + // As an uv_work_cb it must keep the same as prototype + // clang-format off + int StartWorkThread(uv_loop_t *loop, uv_work_cb pFuncWorkThread, + uv_after_work_cb pFuncAfterThread, void *pThreadData); + // clang-format on + // As an uv_work_cb it must keep the same as prototype + void FinishWorkThread(uv_work_t *req, int status); + int GetMaxBufSize(); + bool TryCloseLoop(uv_loop_t *ptrLoop, const char *callerName); + void TryCloseHandle(const uv_handle_t *handle); + void TryCloseHandle(const uv_handle_t *handle, uv_close_cb closeCallBack); + void TryCloseHandle(const uv_handle_t *handle, bool alwaysCallback, uv_close_cb closeCallBack); + char **SplitCommandToArgs(const char *cmdStringLine, int *slotIndex); + bool SetHdcProperty(const char *key, const char *value); + // value needs to save results which can't be const + bool GetHdcProperty(const char *key, char *value, uint16_t sizeOutBuf); + bool RunPipeComand(const char *cmdString, char *outBuf, uint16_t sizeOutBuf, bool ignoreTailLF); + // results need to save in buf which can't be const + int ReadBinFile(const char *pathName, void **buf, const int bufLen); + int WriteBinFile(const char *pathName, const uint8_t *buf, const int bufLen, bool newFile = false); + void CloseIdleCallback(uv_handle_t *handle); + void CloseTimerCallback(uv_handle_t *handle); + int ProgramMutex(const char *procname, bool checkOrNew); + // result needs to save results which can't be const + void SplitString(const string &origString, const string &seq, vector &resultStrings); + string GetShellPath(); + uint64_t HostToNet(uint64_t val); + uint64_t NetToHost(uint64_t val); + string GetFullFilePath(const string &s); + int CreateSocketPair(int *fds); + void CloseSocketPair(const int *fds); + int StringEndsWith(string s, string sub); + bool CheckDirectoryOrPath(const char *localPath, bool pathOrDir, bool readWrite); + int Base64EncodeBuf(const uint8_t *input, const int length, uint8_t *bufOut); + vector Base64Encode(const uint8_t *input, const int length); + int Base64DecodeBuf(const uint8_t *input, const int length, uint8_t *bufOut); + string Base64Decode(const uint8_t *input, const int length); + void ReverseBytes(void *start, int size); + string CanonicalizeSpecPath(string &src); + // Just zero a POD type, such as a structure or union + template int ZeroStruct(T &structBuf) + { + return memset_s(&structBuf, sizeof(T), 0, sizeof(T)); + } + // just zero a statically allocated array of POD or built-in types + template int ZeroArray(T (&arrayBuf)[N]) + { + return memset_s(arrayBuf, sizeof(T) * N, 0, sizeof(T) * N); + } + // just zero memory buf, such as pointer + template int ZeroBuf(T &arrayBuf, int size) + { + return memset_s(arrayBuf, size, 0, size); + } + // clang-format off + const string StringFormat(const char * const formater, ...); + const string StringFormat(const char * const formater, va_list &vaArgs); + // clang-format on + string GetVersion(); + bool IdleUvTask(uv_loop_t *loop, void *data, uv_idle_cb cb); + bool TimerUvTask(uv_loop_t *loop, void *data, uv_timer_cb cb, int repeatTimeout = UV_DEFAULT_INTERVAL); + bool DelayDo(uv_loop_t *loop, const int delayMs, const uint8_t flag, string msg, void *data, + std::function cb); + inline bool DelayDoSimple(uv_loop_t *loop, const int delayMs, + std::function cb) + { + return DelayDo(loop, delayMs, 0, "", nullptr, cb); + } + inline bool DoNextLoop(uv_loop_t *loop, void *data, std::function cb) + { + return DelayDo(loop, 0, 0, "", data, cb); + } + + // Trim from right side + inline string &RightTrim(string &s, const string &w = WHITE_SPACES) + { + s.erase(s.find_last_not_of(w) + 1); + return s; + } + + // Trim from left side + inline string &LeftTrim(string &s, const string &w = WHITE_SPACES) + { + s.erase(0, s.find_first_not_of(w)); + return s; + } + + // Trim from both sides + inline string &Trim(string &s, const string &w = WHITE_SPACES) + { + return LeftTrim(RightTrim(s, w), w); + } + string ReplaceAll(string str, const string from, const string to); + uint8_t CalcCheckSum(const uint8_t *data, int len); + string GetFileNameAny(string &path); + string GetCwd(); + string GetTmpDir(); + uv_os_sock_t DuplicateUvSocket(uv_tcp_t *tcp); + vector Md5Sum(uint8_t *buf, int size); + bool IsRoot(); + char GetPathSep(); + bool IsAbsolutePath(string &path); +} // namespace base +} // namespace Hdc + +#endif // HDC_BASE_H \ No newline at end of file diff --git a/services/flashd/common/channel.cpp b/services/flashd/common/channel.cpp new file mode 100755 index 00000000..8d944ac5 --- /dev/null +++ b/services/flashd/common/channel.cpp @@ -0,0 +1,434 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "channel.h" +namespace Hdc { +HdcChannelBase::HdcChannelBase(const bool serverOrClient, const string &addrString, uv_loop_t *loopMainIn) +{ + SetChannelTCPString(addrString); + isServerOrClient = serverOrClient; + loopMain = loopMainIn; + uv_rwlock_init(&mainAsync); + uv_async_init(loopMain, &asyncMainLoop, MainAsyncCallback); + uv_rwlock_init(&lockMapChannel); +} + +HdcChannelBase::~HdcChannelBase() +{ + ClearChannels(); + // clear + if (!uv_is_closing((uv_handle_t *)&asyncMainLoop)) { + uv_close((uv_handle_t *)&asyncMainLoop, nullptr); + } + + uv_rwlock_destroy(&mainAsync); + uv_rwlock_destroy(&lockMapChannel); +} + +vector HdcChannelBase::GetChannelHandshake(string &connectKey) const +{ + vector ret; + // clang-format off + struct ChannelHandShake handshake = {{0}}; + // clang-format on + Base::ZeroStruct(handshake); + if (strcpy_s(handshake.banner, sizeof(handshake.banner), HANDSHAKE_MESSAGE.c_str()) != EOK) { + return ret; + } + if (strcpy_s(handshake.connectKey, sizeof(handshake.connectKey), connectKey.c_str()) != EOK) { + return ret; + } + ret.insert(ret.begin(), (uint8_t *)&handshake, (uint8_t *)&handshake + sizeof(ChannelHandShake)); + return ret; +} + +bool HdcChannelBase::SetChannelTCPString(const string &addrString) +{ + bool ret = false; + while (true) { + if (addrString.find(":") == string::npos) { + break; + } + string host = addrString.substr(0, addrString.find(":")); + string port = addrString.substr(addrString.find(":") + 1); + channelPort = std::atoi(port.c_str()); + sockaddr_in addr; + if (!channelPort || uv_ip4_addr(host.c_str(), channelPort, &addr) != 0) { + break; + } + channelHost = host; + channelHostPort = addrString; + ret = true; + break; + } + if (!ret) { + channelPort = 0; + channelHost = STRING_EMPTY; + channelHostPort = STRING_EMPTY; + } + return ret; +} + +void HdcChannelBase::ClearChannels() +{ + for (auto v : mapChannel) { + HChannel hChannel = (HChannel)v.second; + if (!hChannel->isDead) { + FreeChannel(hChannel->channelId); + } + } +} + +void HdcChannelBase::WorkerPendding() +{ + WRITE_LOG(LOG_DEBUG, "Begin host channel pendding"); + uv_run(loopMain, UV_RUN_DEFAULT); + uv_loop_close(loopMain); +} + +void HdcChannelBase::ReadStream(uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) +{ + int size = 0; + int indexBuf = 0; + int childRet = 0; + bool needExit = false; + HChannel hChannel = (HChannel)tcp->data; + HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; + + if (nread == UV_ENOBUFS) { + WRITE_LOG(LOG_DEBUG, "HdcChannelBase::ReadStream Pipe IOBuf max"); + return; + } else if (nread == 0) { + // maybe just afer accept, second client req + WRITE_LOG(LOG_DEBUG, "HdcChannelBase::ReadStream idle read"); + return; + } else if (nread < 0) { + Base::TryCloseHandle((uv_handle_t *)tcp); + WRITE_LOG(LOG_DEBUG, "HdcChannelBase::ReadStream failed2:%s", uv_err_name(nread)); + needExit = true; + goto Finish; + } else { + hChannel->availTailIndex += nread; + } + while (hChannel->availTailIndex > DWORD_SERIALIZE_SIZE) { + size = ntohl(*(uint32_t *)(hChannel->ioBuf + indexBuf)); // big endian + if (size <= 0 || (uint32_t)size > HDC_BUF_MAX_BYTES) { + needExit = true; + break; + } + if (hChannel->availTailIndex - DWORD_SERIALIZE_SIZE < size) { + break; + } + childRet = thisClass->ReadChannel(hChannel, (uint8_t *)hChannel->ioBuf + DWORD_SERIALIZE_SIZE + indexBuf, size); + if (childRet < 0) { + if (!hChannel->keepAlive) { + needExit = true; + break; + } + } + // update io + hChannel->availTailIndex -= (DWORD_SERIALIZE_SIZE + size); + indexBuf += DWORD_SERIALIZE_SIZE + size; + } + if (indexBuf > 0 && hChannel->availTailIndex > 0) { + if (memmove_s(hChannel->ioBuf, hChannel->bufSize, hChannel->ioBuf + indexBuf, hChannel->availTailIndex)) { + needExit = true; + goto Finish; + } + } + +Finish: + if (needExit) { + thisClass->FreeChannel(hChannel->channelId); + WRITE_LOG(LOG_DEBUG, "Read Stream needExit, FreeChannel finish"); + } +} + +void HdcChannelBase::WriteCallback(uv_write_t *req, int status) +{ + HChannel hChannel = (HChannel)req->handle->data; + --hChannel->sendRef; + HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; + if (status < 0) { + Base::TryCloseHandle((uv_handle_t *)req->handle); + if (!hChannel->isDead && !hChannel->sendRef) { + thisClass->FreeChannel(hChannel->channelId); + WRITE_LOG(LOG_DEBUG, "WriteCallback TryCloseHandle"); + } + } + delete[]((uint8_t *)req->data); + delete req; +} + +void HdcChannelBase::AsyncMainLoopTask(uv_idle_t *handle) +{ + AsyncParam *param = (AsyncParam *)handle->data; + HdcChannelBase *thisClass = (HdcChannelBase *)param->thisClass; + + switch (param->method) { + case ASYNC_FREE_SESSION: { + // alloc/release should pair in main thread. + thisClass->FreeChannel(param->sid); + break; + } + default: + break; + } + if (param->data) { + delete[]((uint8_t *)param->data); + } + delete param; + uv_close((uv_handle_t *)handle, Base::CloseIdleCallback); +} + +// multiple uv_async_send() calls may be merged by libuv,so not each call will yield callback as expected. +// eg: if uv_async_send() 5 times before callback calling,it will be called only once. +// if uv_async_send() is called again after callback calling, it will be called again. +void HdcChannelBase::MainAsyncCallback(uv_async_t *handle) +{ + HdcChannelBase *thisClass = (HdcChannelBase *)handle->data; + if (uv_is_closing((uv_handle_t *)thisClass->loopMain)) { + return; + } + list::iterator i; + list &lst = thisClass->lstMainThreadOP; + uv_rwlock_wrlock(&thisClass->mainAsync); + for (i = lst.begin(); i != lst.end();) { + AsyncParam *param = (AsyncParam *)*i; + Base::IdleUvTask(thisClass->loopMain, param, AsyncMainLoopTask); + i = lst.erase(i); + } + uv_rwlock_wrunlock(&thisClass->mainAsync); +} + +void HdcChannelBase::PushAsyncMessage(const uint32_t channelId, const uint8_t method, const void *data, + const int dataSize) +{ + if (uv_is_closing((uv_handle_t *)&asyncMainLoop)) { + return; + } + auto param = new AsyncParam(); + if (!param) { + return; + } + param->sid = channelId; // Borrow SID storage + param->thisClass = this; + param->method = method; + if (dataSize > 0) { + param->dataSize = dataSize; + param->data = new uint8_t[param->dataSize](); + if (!param->data) { + delete param; + return; + } + if (memcpy_s((uint8_t *)param->data, param->dataSize, data, dataSize)) { + delete[]((uint8_t *)param->data); + delete param; + return; + } + } + asyncMainLoop.data = this; + uv_rwlock_wrlock(&mainAsync); + lstMainThreadOP.push_back(param); + uv_rwlock_wrunlock(&mainAsync); + uv_async_send(&asyncMainLoop); +} + +// client to server, or vice versa +// works only in current working thread +void HdcChannelBase::Send(const uint32_t channelId, uint8_t *bufPtr, const int size) +{ + uv_stream_t *sendStream = nullptr; + int sizeNewBuf = size + DWORD_SERIALIZE_SIZE; + HChannel hChannel = (HChannel)AdminChannel(OP_QUERY, channelId, nullptr); + if (!hChannel || hChannel->isDead) { + return; + } + auto data = new uint8_t[sizeNewBuf](); + if (!data) { + return; + } + *(uint32_t *)data = htonl(size); // big endian + if (memcpy_s(data + DWORD_SERIALIZE_SIZE, sizeNewBuf - DWORD_SERIALIZE_SIZE, bufPtr, size)) { + delete[] data; + return; + } + if (hChannel->hWorkThread == uv_thread_self()) { + sendStream = (uv_stream_t *)&hChannel->hWorkTCP; + } else { + sendStream = (uv_stream_t *)&hChannel->hChildWorkTCP; + } + if (!uv_is_closing((const uv_handle_t *)sendStream) && uv_is_writable(sendStream)) { + ++hChannel->sendRef; + Base::SendToStreamEx(sendStream, data, sizeNewBuf, nullptr, (void *)WriteCallback, data); + } +} + +void HdcChannelBase::AllocCallback(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) +{ + if (sizeWanted <= 0) { + return; + } + HChannel context = (HChannel)handle->data; + Base::ReallocBuf(&context->ioBuf, &context->bufSize, context->availTailIndex, sizeWanted); + buf->base = (char *)context->ioBuf + context->availTailIndex; + buf->len = context->bufSize - context->availTailIndex - 1; + if (buf->len < 0) { + buf->len = 0; + } +} + +uint32_t HdcChannelBase::MallocChannel(HChannel *hOutChannel) +{ + auto hChannel = new HdcChannel(); + if (!hChannel) { + return 0; + } + uint32_t channelId = Base::GetRuntimeMSec(); + if (isServerOrClient) { + hChannel->serverOrClient = isServerOrClient; + ++channelId; // Use different value for serverForClient&client in per process + } + uv_tcp_init(loopMain, &hChannel->hWorkTCP); + ++hChannel->uvRef; + hChannel->hWorkThread = uv_thread_self(); + hChannel->hWorkTCP.data = hChannel; + hChannel->clsChannel = this; + hChannel->channelId = channelId; + AdminChannel(OP_ADD, channelId, hChannel); + *hOutChannel = hChannel; + WRITE_LOG(LOG_DEBUG, "Mallocchannel:%d", channelId); + return channelId; +} + +// work when libuv-handle at struct of HdcSession has all callback finished +void HdcChannelBase::FreeChannelFinally(uv_idle_t *handle) +{ + HChannel hChannel = (HChannel)handle->data; + HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; + if (hChannel->uvRef > 0) { + return; + } + thisClass->NotifyInstanceChannelFree(hChannel); + thisClass->AdminChannel(OP_REMOVE, hChannel->channelId, nullptr); + WRITE_LOG(LOG_DEBUG, "!!!FreeChannelFinally channelId:%d finish", hChannel->channelId); + if (!hChannel->serverOrClient) { + uv_stop(thisClass->loopMain); + } + delete hChannel; + Base::TryCloseHandle((const uv_handle_t *)handle, Base::CloseIdleCallback); +} + +void HdcChannelBase::FreeChannelContinue(HChannel hChannel) +{ + auto closeChannelHandle = [](uv_handle_t *handle) -> void { + HChannel hChannel = (HChannel)handle->data; + --hChannel->uvRef; + Base::TryCloseHandle((uv_handle_t *)handle); + }; + hChannel->availTailIndex = 0; + if (hChannel->ioBuf) { + delete[] hChannel->ioBuf; + hChannel->ioBuf = nullptr; + } + if (!hChannel->serverOrClient) { + Base::TryCloseHandle((uv_handle_t *)&hChannel->stdinTty, closeChannelHandle); + Base::TryCloseHandle((uv_handle_t *)&hChannel->stdoutTty, closeChannelHandle); + } + if (uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP)) { + --hChannel->uvRef; + } else { + Base::TryCloseHandle((uv_handle_t *)&hChannel->hWorkTCP, closeChannelHandle); + } + Base::IdleUvTask(loopMain, hChannel, FreeChannelFinally); +} + +void HdcChannelBase::FreeChannelOpeate(uv_timer_t *handle) +{ + HChannel hChannel = (HChannel)handle->data; + HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; + if (hChannel->sendRef > 0) { + return; + } + if (hChannel->hChildWorkTCP.loop) { + auto ctrl = HdcSessionBase::BuildCtrlString(SP_DEATCH_CHANNEL, hChannel->channelId, nullptr, 0); + thisClass->ChannelSendSessionCtrlMsg(ctrl, hChannel->targetSessionId); + auto callbackCheckFreeChannelContinue = [](uv_timer_t *handle) -> void { + HChannel hChannel = (HChannel)handle->data; + HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; + if (!hChannel->childCleared) { + return; + } + Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback); + thisClass->FreeChannelContinue(hChannel); + }; + Base::TimerUvTask(thisClass->loopMain, hChannel, callbackCheckFreeChannelContinue); + } else { + thisClass->FreeChannelContinue(hChannel); + } + Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback); +} + +void HdcChannelBase::FreeChannel(const uint32_t channelId) +{ + HChannel hChannel = AdminChannel(OP_QUERY, channelId, nullptr); + if (!hChannel) { + return; + } + // Two cases: alloc in main thread, or work thread + if (hChannel->hWorkThread != uv_thread_self()) { + PushAsyncMessage(hChannel->channelId, ASYNC_FREE_SESSION, nullptr, 0); + return; + } + if (hChannel->isDead) { + return; + } + Base::TimerUvTask(loopMain, hChannel, FreeChannelOpeate, MINOR_TIMEOUT); // do immediately + hChannel->isDead = true; +} + +HChannel HdcChannelBase::AdminChannel(const uint8_t op, const uint32_t channelId, HChannel hInput) +{ + HChannel hRet = nullptr; + switch (op) { + case OP_ADD: + uv_rwlock_wrlock(&lockMapChannel); + mapChannel[channelId] = hInput; + uv_rwlock_wrunlock(&lockMapChannel); + break; + case OP_REMOVE: + uv_rwlock_wrlock(&lockMapChannel); + mapChannel.erase(channelId); + uv_rwlock_wrunlock(&lockMapChannel); + break; + case OP_QUERY: + uv_rwlock_rdlock(&lockMapChannel); + if (mapChannel.count(channelId)) { + hRet = mapChannel[channelId]; + } + uv_rwlock_rdunlock(&lockMapChannel); + break; + case OP_UPDATE: + uv_rwlock_wrlock(&lockMapChannel); + // remove old + mapChannel.erase(channelId); + mapChannel[hInput->channelId] = hInput; + uv_rwlock_wrunlock(&lockMapChannel); + break; + default: + break; + } + return hRet; +} +} \ No newline at end of file diff --git a/services/flashd/common/channel.h b/services/flashd/common/channel.h new file mode 100755 index 00000000..72b81813 --- /dev/null +++ b/services/flashd/common/channel.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_CHANNEL_H +#define HDC_CHANNEL_H +#include "common.h" + +namespace Hdc { +class HdcChannelBase { +public: + HdcChannelBase(const bool serverOrClient, const string &addrString, uv_loop_t *loopMainIn); + virtual ~HdcChannelBase(); + HChannel AdminChannel(const uint8_t op, const uint32_t channelId, HChannel hInput); + static void AllocCallback(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf); + static void ReadStream(uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf); + void PushAsyncMessage(const uint32_t channelId, const uint8_t method, const void *data, const int dataSize); + void WorkerPendding(); + void FreeChannel(const uint32_t channelId); + vector GetChannelHandshake(string &connectKey) const; + +protected: + struct ChannelHandShake { + char banner[12]; // must first index + union { + uint32_t channelId; + char connectKey[MAX_CONNECTKEY_SIZE]; + }; + } __attribute__((packed)); + uint32_t MallocChannel(HChannel *hOutChannel); + virtual int ReadChannel(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) + { + return 0; + } + virtual void NotifyInstanceChannelFree(HChannel hChannel) {}; + void Send(const uint32_t channelId, uint8_t *bufPtr, const int size); + virtual bool ChannelSendSessionCtrlMsg(vector &ctrlMsg, uint32_t sessionId) + { + return true; // just server use + } + + string channelHostPort; + string channelHost; + uint16_t channelPort; + uv_loop_t *loopMain; + bool isServerOrClient; + uv_rwlock_t mainAsync; + uv_async_t asyncMainLoop; + list lstMainThreadOP; + +private: + static void MainAsyncCallback(uv_async_t *handle); + static void WriteCallback(uv_write_t *req, int status); + static void AsyncMainLoopTask(uv_idle_t *handle); + static void FreeChannelOpeate(uv_timer_t *handle); + static void FreeChannelFinally(uv_idle_t *handle); + void ClearChannels(); + void FreeChannelContinue(HChannel hChannel); + bool SetChannelTCPString(const string &addrString); + + uv_rwlock_t lockMapChannel; // protect mapChannel + map mapChannel; +}; +} // namespace Hdc + +#endif // HDC_CHANNEL_H \ No newline at end of file diff --git a/services/flashd/common/common.h b/services/flashd/common/common.h new file mode 100755 index 00000000..e90125ba --- /dev/null +++ b/services/flashd/common/common.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_COMMON_H +#define HDC_COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::condition_variable; +using std::list; +using std::map; +using std::mutex; +using std::string; +using std::vector; + +// clang-format off +#include // libuv 1.35 +#ifdef HDC_HOST + +#ifdef HARMONY_PROJECT +#include +#else // NOT HARMONY_PROJECT +#include +#endif // END HARMONY_PROJECT + +#else // NOT HDC_HOST +#endif // HDC_HOST + +#ifndef _WIN32 +#include +#include +#endif + +#include + +#include "define.h" +#include "debug.h" +#include "base.h" +#include "task.h" +#include "channel.h" +#include "session.h" +#include "auth.h" + +#include "tcp.h" +#include "usb.h" +#include "file_descriptor.h" + +// clang-format on + +#endif // !defined(COMMON_H_INCLUDED) diff --git a/services/flashd/common/debug.cpp b/services/flashd/common/debug.cpp new file mode 100755 index 00000000..30b81c7e --- /dev/null +++ b/services/flashd/common/debug.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "debug.h" +#include "base.h" + +namespace Hdc { +namespace Debug { + int WriteHexToDebugFile(const char *fileName, const uint8_t *buf, const int bufLen) + { + char pathName[BUF_SIZE_DEFAULT]; + if (snprintf_s(pathName, sizeof(pathName), sizeof(pathName) - 1, "/mnt/hgfs/vtmp/%s", fileName) < 0) { + return ERR_BUF_OVERFLOW; + } + string srcPath = pathName; + string resolvedPath = Base::CanonicalizeSpecPath(srcPath); + FILE *fp = fopen(resolvedPath.c_str(), "a+"); + if (fp == nullptr) { + if (snprintf_s(pathName, sizeof(pathName), sizeof(pathName) - 1, "/tmp/%s", fileName) < 0) { + WRITE_LOG(LOG_DEBUG, "Write hex to %s failed!", pathName); + return ERR_FILE_OPEN; + } + + srcPath = pathName; + resolvedPath = Base::CanonicalizeSpecPath(srcPath); + if ((fp = fopen(resolvedPath.c_str(), "a+")) == nullptr) { + WRITE_LOG(LOG_DEBUG, "Write hex to %s failed!", pathName); + return ERR_FILE_OPEN; + } + } + fwrite(buf, 1, bufLen, fp); + fflush(fp); + fclose(fp); + return RET_SUCCESS; + } + + int ReadHexFromDebugFile(const char *fileName, uint8_t *buf, const int bufLen) + { + char pathName[BUF_SIZE_DEFAULT]; + if (snprintf_s(pathName, sizeof(pathName), sizeof(pathName) - 1, "/mnt/hgfs/vtmp/%s", fileName) < 0) { + return ERR_BUF_OVERFLOW; + } + FILE *fp = fopen(pathName, "r"); + if (fp == nullptr) { + if (snprintf_s(pathName, sizeof(pathName), sizeof(pathName) - 1, "/tmp/%s", fileName) < 0 + || (fp = fopen(pathName, "r")) == nullptr) { + if (fp != nullptr) { + fclose(fp); + } + WRITE_LOG(LOG_DEBUG, "Write hex to %s failed!", pathName); + return ERR_FILE_WRITE; + } + } + struct stat statbuf; + stat(pathName, &statbuf); + int size = statbuf.st_size; + if (size > bufLen) { + fclose(fp); + return ERR_BUF_SIZE; + } + int ret = fread(buf, 1, size, fp); + fflush(fp); + fclose(fp); + if (ret != size) { + return ERR_FILE_READ; + } + return size; + } + + void DetermineThread(HSession hSession) + { + if (uv_thread_self() == hSession->hWorkThread) { + WRITE_LOG(LOG_WARN, "At main workthread"); + } else if (uv_thread_self() == hSession->hWorkChildThread) { + WRITE_LOG(LOG_WARN, "At child workthread"); + } else { + WRITE_LOG(LOG_WARN, "At unknow workthread"); + } + } + + int PrintfHexBuf(const uint8_t *buf, int bufLen) + { + int i = 0; + for (i = 0; i < bufLen; ++i) { + printf("0x%02x, ", buf[i]); + fflush(stdout); + } + printf("\r\n"); + fflush(stdout); + return 0; + } +} +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/common/debug.h b/services/flashd/common/debug.h new file mode 100755 index 00000000..b14d1e10 --- /dev/null +++ b/services/flashd/common/debug.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_DEBUG_H +#define HDC_DEBUG_H +#include "common.h" + +namespace Hdc { +namespace Debug { + int WriteHexToDebugFile(const char *fileName, const uint8_t *buf, const int bufLen); + int ReadHexFromDebugFile(const char *fileName, uint8_t *buf, const int bufLen); + void DetermineThread(HSession hSession); + int PrintfHexBuf(const uint8_t *buf, int bufLen); +} +} // namespace Hdc + +#endif \ No newline at end of file diff --git a/services/flashd/common/define.h b/services/flashd/common/define.h new file mode 100755 index 00000000..0c1ddf0d --- /dev/null +++ b/services/flashd/common/define.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_DEFINE_H +#define HDC_DEFINE_H +#include "define_plus.h" + +namespace Hdc { +// ############################## config ####################################### +constexpr uint8_t MINOR_TIMEOUT = 5; +constexpr uint8_t SIZE_THREAD_POOL = 16; +constexpr uint8_t GLOBAL_TIMEOUT = 30; +constexpr uint16_t DEFAULT_PORT = 8710; +constexpr uint16_t MAX_SIZE_IOBUF = 5120; // USB EP block max size about 10k, USBFFS_BULKSIZE 16384 +constexpr bool ENABLE_IO_CHECKSUM = false; +const string DEFAULT_SERVER_ADDR = "127.0.0.1:8710"; + +// ################################ macro define ################################### +constexpr uint8_t DWORD_SERIALIZE_SIZE = 4; +constexpr uint8_t CMD_ARG1_COUNT = 2; +constexpr uint8_t STREAM_MAIN = 0; // work at main thread +constexpr uint8_t STREAM_WORK = 1; // work at work thread +constexpr uint16_t BUF_SIZE_MICRO = 16; +constexpr uint16_t BUF_SIZE_TINY = 64; +constexpr uint16_t BUF_SIZE_SMALL = 256; +constexpr uint16_t BUF_SIZE_MEDIUM = 512; +constexpr uint16_t BUF_SIZE_DEFAULT = 1024; +constexpr uint16_t BUF_SIZE_DEFAULT2 = BUF_SIZE_DEFAULT * 2; +constexpr uint16_t BUF_SIZE_DEFAULT4 = BUF_SIZE_DEFAULT * 4; +constexpr uint16_t MAX_IP_PORT = 65535; +constexpr uint16_t MAX_CONNECTKEY_SIZE = 32; // usb sn/tcp ipport +constexpr uint16_t TIME_BASE = 1000; // time unit conversion base value +constexpr uint16_t AID_SHELL = 2000; +constexpr uint16_t UV_DEFAULT_INTERVAL = 250; // ms +constexpr uint16_t VER_PROTOCOL = 0x01; +constexpr uint16_t EXTRA_ALLOC_SIZE = 2048; +// double-word(hex)=[0]major[1][2]minor[3][4]version[5]fix(a-p)[6][7]reserve +constexpr uint32_t HDC_VERSION_NUMBER = 0x10101800; // 1.1.1b=0x10101100 +constexpr uint32_t HDC_BUF_MAX_BYTES = 1024000000; + +const string WHITE_SPACES = " \t\n\r"; +const string UT_TMP_PATH = "/tmp/hdc-ut"; +const string LOG_FILE_NAME = "hdc.log"; +const string SERVER_NAME = "HDCServer"; +const string STRING_EMPTY = ""; +const string HANDSHAKE_MESSAGE = "OHOS HDC"; // sep not char '-', not more than 11 bytes +const string PACKET_FLAG = "HW"; // must 2bytes +const string EMPTY_ECHO = "[Empty]"; +const string MESSAGE_INFO = "[Info]"; +const string MESSAGE_FAIL = "[Fail]"; +const string MESSAGE_SUCCESS = "[Success]"; +// input command +const string CMDSTR_SOFTWARE_VERSION = "version"; +const string CMDSTR_SOFTWARE_HELP = "help"; +const string CMDSTR_TARGET_DISCOVER = "discover"; +const string CMDSTR_SERVICE_START = "start"; +const string CMDSTR_SERVICE_KILL = "kill"; +const string CMDSTR_GENERATE_KEY = "keygen"; +const string CMDSTR_KILL_SERVER = "kserver"; +const string CMDSTR_KILL_DAEMON = "kdaemon"; +const string CMDSTR_LIST_TARGETS = "list targets"; +const string CMDSTR_CONNECT_TARGET = "tconn"; +const string CMDSTR_CONNECT_ANY = "any"; +const string CMDSTR_SHELL = "shell"; +const string CMDSTR_TARGET_REBOOT = "target boot"; +const string CMDSTR_TARGET_MOUNT = "target mount"; +const string CMDSTR_STARTUP_MODE = "smode"; +const string CMDSTR_TARGET_MODE = "tmode"; +const string CMDSTR_BUGREPORT = "bugreport"; +const string CMDSTR_HILOG = "hilog"; +const string CMDSTR_TMODE_USB = "usb"; +const string CMDSTR_TMODE_TCP = "tcp"; +const string CMDSTR_FILE_SEND = "file send"; +const string CMDSTR_FILE_RECV = "file recv"; +const string CMDSTR_FORWARD_FPORT = "fport"; +const string CMDSTR_FORWARD_RPORT = "rport"; +const string CMDSTR_APP_INSTALL = "install"; +const string CMDSTR_APP_UNINSTALL = "uninstall"; +const string CMDSTR_APP_SIDELOAD = "sideload"; +const string CMDSTR_LIST_JDWP = "jpid"; +const string CMDSTR_UPDATE_SYSTEM = "update"; +const string CMDSTR_FLASH_PARTITION = "flash"; +const string CMDSTR_ERASE_PARTITION = "erase"; +const string CMDSTR_FORMAT_PARTITION = "format"; +const string CMDSTR_INNER_ENABLE_KEEPALIVE = "alive"; +} // namespace Hdc +#endif // HDC_DEFINE_H diff --git a/services/flashd/common/define_plus.h b/services/flashd/common/define_plus.h new file mode 100755 index 00000000..0e4c22b7 --- /dev/null +++ b/services/flashd/common/define_plus.h @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef DEFINE_PLUS_H +#define DEFINE_PLUS_H + +namespace Hdc { +constexpr uint8_t LOG_LEVEL_FULL = 5; +// ############################# enum define ################################### +enum LogLevel { + LOG_OFF, + LOG_FATAL, + LOG_INFO, // default + LOG_WARN, + LOG_DEBUG, + LOG_FULL, + LOG_LAST = LOG_FULL, // tail, not use +}; +#define WRITE_LOG(x, y...) Base::PrintLogEx(__FILE__, __LINE__, x, y) + +enum MessageLevel { + MSG_FAIL, + MSG_INFO, + MSG_OK, +}; + +enum ConnType { CONN_USB = 0, CONN_TCP, CONN_SERIAL, CONN_BT }; +enum ConnStatus { STATUS_UNKNOW = 0, STATUS_READY, STATUS_CONNECTED, STATUS_OFFLINE }; + +enum OperateID { + OP_ADD, + OP_REMOVE, + OP_QUERY, + OP_GET_STRLIST, + OP_GET_STRLIST_FULL, + OP_GET_ANY, + OP_UPDATE, + OP_CLEAR, + OP_INIT, + OP_GET_ONLY +}; + +enum RetErrCode { + RET_SUCCESS = 0, + ERR_GENERIC = -1, + ERR_BUF_SIZE = -10000, + ERR_BUF_ALLOC, + ERR_BUF_OVERFLOW, + ERR_BUF_CHECK, + ERR_BUF_RESET, + ERR_BUF_COPY, + ERR_FILE_OPEN = -11000, + ERR_FILE_READ, + ERR_FILE_WRITE, + ERR_FILE_STAT, + ERR_FILE_PATH_CHECK, + ERR_PARM_FORMAT = -12000, + ERR_PARM_SIZE, + ERR_PARM_FAIL, + ERR_API_FAIL = -13000, + ERR_IO_FAIL = -14000, + ERR_IO_TIMEOUT, + ERR_IO_SOFT_RESET, + ERR_SESSION_NOFOUND = -15000, + ERR_SESSION_OFFLINE, + ERR_SESSION_DEAD, + ERR_HANDSHAKE_NOTMATCH = -16000, + ERR_HANDSHAKE_CONNECTKEY_FAILED, + ERR_HANDSHAKE_HANGUP_CHILD, + ERR_SOCKET_FAIL = -17000, + ERR_SOCKET_DUPLICATE, + ERR_MODULE_JDWP_FAILED = -18000, + ERR_UT_MODULE_NOTREADY = -19000, + ERR_UT_MODULE_WAITMAX, + ERR_THREAD_MUTEX_FAIL = -20000, + ERR_PROCESS_SUB_FAIL = -21000, + ERR_PRIVELEGE_NEED = -22000, +}; + +// Flags shared by multiple modules +enum AsyncEvent { + ASYNC_STOP_MAINLOOP = 0, + ASYNC_FREE_SESSION, +}; +enum InnerCtrlCommand { + SP_START_SESSION = 0, + SP_STOP_SESSION, + SP_ATTACH_CHANNEL, + SP_DEATCH_CHANNEL, + SP_JDWP_NEWFD, +}; + +enum HdcCommand { + // core commands types + CMD_KERNEL_HELP = 0, + CMD_KERNEL_HANDSHAKE, + CMD_KERNEL_CHANNEL_CLOSE, + CMD_KERNEL_SERVER_KILL, + CMD_KERNEL_TARGET_DISCOVER, + CMD_KERNEL_TARGET_LIST, + CMD_KERNEL_TARGET_ANY, + CMD_KERNEL_TARGET_CONNECT, + CMD_KERNEL_TARGET_DISCONNECT, + CMD_KERNEL_ECHO, + CMD_KERNEL_ECHO_RAW, + CMD_KERNEL_ENABLE_KEEPALIVE, + // One-pass simple commands + CMD_UNITY_EXECUTE = 1000, + CMD_UNITY_REMOUNT, + CMD_UNITY_REBOOT, + CMD_UNITY_RUNMODE, + CMD_UNITY_HILOG, + CMD_UNITY_TERMINATE, + CMD_UNITY_ROOTRUN, + CMD_UNITY_BUGREPORT_INIT, + CMD_UNITY_BUGREPORT_DATA, + CMD_UNITY_JPID, + // Shell commands types + CMD_SHELL_INIT = 2000, + CMD_SHELL_DATA, + // Forward commands types + CMD_FORWARD_INIT = 2500, + CMD_FORWARD_CHECK, + CMD_FORWARD_CHECK_RESULT, + CMD_FORWARD_ACTIVE_SLAVE, + CMD_FORWARD_ACTIVE_MASTER, + CMD_FORWARD_DATA, + CMD_FORWARD_FREE_CONTEXT, + CMD_FORWARD_LIST, + CMD_FORWARD_REMOVE, + CMD_FORWARD_SUCCESS, + // File commands + CMD_FILE_INIT = 3000, + CMD_FILE_CHECK, + CMD_FILE_BEGIN, + CMD_FILE_DATA, + CMD_FILE_FINISH, + CMD_APP_SIDELOAD, + // App commands + CMD_APP_INIT = 3500, + CMD_APP_CHECK, + CMD_APP_BEGIN, + CMD_APP_DATA, + CMD_APP_FINISH, + CMD_APP_UNINSTALL, + // update + CMD_UPDATER_UPDATE_INIT = 4000, + CMD_UPDATER_FLASH_INIT, + CMD_UPDATER_CHECK, + CMD_UPDATER_BEGIN, + CMD_UPDATER_DATA, + CMD_UPDATER_FINISH = 4005, + CMD_UPDATER_ERASE, + CMD_UPDATER_FORMAT, + CMD_UPDATER_PROGRESS +}; + +enum UsbProtocolOption { + USB_OPTION_TAIL = 1, + USB_OPTION_RESET = 2, + USB_OPTION_RESERVE4 = 4, + USB_OPTION_RESERVE8 = 8, + USB_OPTION_RESERVE16 = 16, +}; +// ################################### struct define ################################### +#pragma pack(push) +#pragma pack(1) + +struct USBHead { + uint8_t flag[2]; + uint8_t option; + uint32_t sessionId; + uint16_t dataSize; +}; + +struct AsyncParam { + void *context; // context=hsession or hchannel + uint32_t sid; // sessionId/channelId + void *thisClass; // caller's class ptr + uint16_t method; + int dataSize; + void *data; // put it in the last +}; + +struct TaskInformation { + uint8_t taskType; + uint32_t sessionId; + uint32_t channelId; + bool hasInitial; + bool taskStop; + bool taskFree; + bool serverOrDaemon; + uv_loop_t *runLoop; + void *taskClass; + void *ownerSessionClass; +}; +using HTaskInfo = TaskInformation *; + +#pragma pack(pop) + +struct HdcUSB { +#ifdef HDC_HOST + libusb_context *ctxUSB = nullptr; // child-use, main null + libusb_device *device; + libusb_device_handle *devHandle; + uint8_t interfaceNumber; + uint16_t retryCount; + // D2H device to host endpoint's address + uint8_t epDevice; + // H2D host to device endpoint's address + uint8_t epHost; + uint8_t devId; + uint8_t busId; + int32_t sizeEpBuf; + uint16_t wMaxPacketSize; + string serialNumber; + string usbMountPoint; + uint8_t *bufDevice; + uint8_t *bufHost; + + mutex lockDeviceHandle; + libusb_transfer *transferRecv; + bool recvIOComplete; + + mutex lockSend; + condition_variable cvTransferSend; + libusb_transfer *transferSend; + bool sendIOComplete; +#else + // usb accessory FunctionFS + // USB main thread use, sub-thread disable, sub-thread uses the main thread USB handle + int bulkOut; // EP1 device recv + int bulkIn; // EP2 device send +#endif + vector bufRecv; + bool resetIO; // if true, must break write and read,default false +}; +using HUSB = struct HdcUSB *; + +struct HdcSession { + bool serverOrDaemon; // instance of daemon or server + bool handshakeOK; // Is an expected peer side + bool isDead; + string connectKey; + uint8_t connType; // ConnType + uint32_t sessionId; + std::atomic sendRef; + uint8_t uvRef; // libuv handle ref -- just main thread now + uint8_t uvChildRef; // libuv handle ref -- just main thread now + bool childCleared; + map *mapTask; + // class ptr + void *classInstance; // HdcSessionBase instance, HdcServer or HdcDaemon + void *classModule; // Communicate module, TCP or USB instance,HdcDaemonUSB HdcDaemonTCP etc... + // io cache + int bufSize; // total buffer size + int availTailIndex; // buffer available data size + uint8_t *ioBuf; + // auth + list *listKey; // rsa private or publickey list + uint8_t authKeyIndex; + string tokenRSA; // SHA_DIGEST_LENGTH+1==21 + // child work + uv_loop_t childLoop; // run in work thread + // pipe0 in main thread(hdc server mainloop), pipe1 in work thread + uv_tcp_t ctrlPipe[2]; // control channel + int ctrlFd[2]; // control channel socketpair + // data channel(TCP with socket, USB with thread forward) + uv_tcp_t dataPipe[2]; + int dataFd[2]; // data channel socketpair + uv_tcp_t hChildWorkTCP; // work channel,separate thread for server/daemon + uv_os_sock_t fdChildWorkTCP; + // usb handle + HUSB hUSB; + // tcp handle + uv_tcp_t hWorkTCP; + uv_thread_t hWorkThread; + uv_thread_t hWorkChildThread; +}; +using HSession = struct HdcSession *; + +struct HdcChannel { + void *clsChannel; // ptr Class of serverForClient or client + uint32_t channelId; + string connectKey; + uv_tcp_t hWorkTCP; // work channel for client, forward channel for server + uv_thread_t hWorkThread; + uint8_t uvRef = 0; // libuv handle ref -- just main thread now + bool handshakeOK; + bool isDead; + bool serverOrClient; // client's channel/ server's channel + bool childCleared; + bool interactiveShellMode; // Is shell interactive mode + bool keepAlive; // channel will not auto-close by server + std::atomic sendRef; + uint32_t targetSessionId; + // child work + uv_tcp_t hChildWorkTCP; // work channel for server, no use in client + uv_os_sock_t fdChildWorkTCP; + // read io cache + int bufSize; // total buffer size + int availTailIndex; // buffer available data size + uint8_t *ioBuf; + // std + uv_tty_t stdinTty; + uv_tty_t stdoutTty; + char bufStd[128]; +}; +using HChannel = struct HdcChannel *; + +struct HdcDaemonInformation { + uint8_t connType; + uint8_t connStatus; + string connectKey; + string usbMountPoint; + string devName; + HSession hSession; +}; +using HDaemonInfo = struct HdcDaemonInformation *; + +struct HdcForwardInformation { + string taskString; + bool forwardDirection; // true for forward, false is reverse; + uint32_t sessionId; + uint32_t channelId; +}; +using HForwardInfo = struct HdcForwardInformation *; +} +#endif \ No newline at end of file diff --git a/services/flashd/common/file.cpp b/services/flashd/common/file.cpp new file mode 100755 index 00000000..4e3cd905 --- /dev/null +++ b/services/flashd/common/file.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "file.h" +#include "serial_struct.h" + +namespace Hdc { +HdcFile::HdcFile(HTaskInfo hTaskInfo) + : HdcTransferBase(hTaskInfo) +{ + commandBegin = CMD_FILE_BEGIN; + commandData = CMD_FILE_DATA; +} + +HdcFile::~HdcFile() +{ + WRITE_LOG(LOG_DEBUG, "~HdcFile"); +}; + +void HdcFile::StopTask() +{ + WRITE_LOG(LOG_DEBUG, "HdcFile StopTask"); + singalStop = true; +}; + +bool HdcFile::BeginTransfer(CtxFile *context, const string &command) +{ + int argc = 0; + bool ret = false; + char **argv = Base::SplitCommandToArgs(command.c_str(), &argc); + if (argc < CMD_ARG1_COUNT || argv == nullptr) { + LogMsg(MSG_FAIL, "Transfer path split failed"); + if (argv) { + delete[]((char *)argv); + } + return false; + } + if (!SetMasterParameters(context, command.c_str(), argc, argv)) { + delete[]((char *)argv); + return false; + } + do { + ++refCount; + uv_fs_open(loopTask, &context->fsOpenReq, context->localPath.c_str(), O_RDONLY, S_IWUSR | S_IRUSR, OnFileOpen); + context->master = true; + ret = true; + } while (false); + if (!ret) { + LogMsg(MSG_FAIL, "Transfer path failed, Master:%s Slave:%s", context->localPath.c_str(), + context->remotePath.c_str()); + } + delete[]((char *)argv); + return ret; +} + +bool HdcFile::SetMasterParameters(CtxFile *context, const char *command, int argc, char **argv) +{ + int srcArgvIndex = 0; + const string CMD_OPTION_TSTMP = "-a"; + const string CMD_OPTION_SYNC = "-sync"; + const string CMD_OPTION_ZIP = "-z"; + + for (int i = 0; i < argc - CMD_ARG1_COUNT; i++) { + if (argv[i] == CMD_OPTION_ZIP) { + context->transferConfig.compressType = COMPRESS_LZ4; + ++srcArgvIndex; + } else if (argv[i] == CMD_OPTION_SYNC) { + context->transferConfig.updateIfNew = true; + ++srcArgvIndex; + } else if (argv[i] == CMD_OPTION_TSTMP) { + // The time zone difference may cause the display time on the PC and the + // device to differ by several hours + // + // ls -al --full-time + context->transferConfig.holdTimestamp = true; + ++srcArgvIndex; + } else if (argv[i] == CMD_OPTION_CLIENTCWD) { + context->transferConfig.clientCwd = argv[i + 1]; + srcArgvIndex += CMD_ARG1_COUNT; // skip 2args + } else if (argv[i][0] == '-') { + LogMsg(MSG_FAIL, "Unknow file option: %s", argv[i]); + return false; + } + } + context->remotePath = argv[argc - 1]; + context->localPath = argv[argc - 2]; + if (taskInfo->serverOrDaemon) { + // master and server + ExtractRelativePath(context->transferConfig.clientCwd, context->localPath); + } + if (!Base::CheckDirectoryOrPath(context->localPath.c_str(), true, true)) { + LogMsg(MSG_FAIL, "Src not exist, path: %s", context->localPath.c_str()); + return false; + } + context->localName = Base::GetFullFilePath(context->localPath); + return true; +} + +void HdcFile::CheckMaster(CtxFile *context) +{ + string s = SerialStruct::SerializeToString(context->transferConfig); + SendToAnother(CMD_FILE_CHECK, (uint8_t *)s.c_str(), s.size()); +} + +void HdcFile::WhenTransferFinish(CtxFile *context) +{ + WRITE_LOG(LOG_DEBUG, "HdcTransferBase OnFileClose"); + uint8_t flag = 1; + SendToAnother(CMD_FILE_FINISH, &flag, 1); +} + +void HdcFile::TransferSummary(CtxFile *context) +{ + uint64_t nMSec = Base::GetRuntimeMSec() - context->transferBegin; + double fRate = static_cast(context->indexIO) / nMSec; // / /1000 * 1000 = 0 + LogMsg(MSG_OK, "FileTransfer finish, Size:%lld time:%lldms rate:%.2lfkB/s", context->indexIO, nMSec, fRate); +} + +bool HdcFile::SlaveCheck(uint8_t *payload, const int payloadSize) +{ + bool ret = true; + bool childRet = false; + // parse option + string serialStrring((char *)payload, payloadSize); + TransferConfig &stat = ctxNow.transferConfig; + SerialStruct::ParseFromString(stat, serialStrring); + ctxNow.fileSize = stat.fileSize; + ctxNow.localPath = stat.path; + ctxNow.master = false; + ctxNow.fsOpenReq.data = &ctxNow; + // check path + childRet = SmartSlavePath(stat.clientCwd, ctxNow.localPath, stat.optionalName.c_str()); + if (childRet && ctxNow.transferConfig.updateIfNew) { // file exist and option need update + // if is newer + uv_fs_t fs; + Base::ZeroStruct(fs.statbuf); + uv_fs_stat(nullptr, &fs, ctxNow.localPath.c_str(), nullptr); + uv_fs_req_cleanup(&fs); + if ((uint64_t)fs.statbuf.st_mtim.tv_sec >= ctxNow.transferConfig.mtime) { + LogMsg(MSG_FAIL, "Target file is the same date or newer,path: %s", ctxNow.localPath.c_str()); + return false; + } + } + // begin work + ++refCount; + uv_fs_open(loopTask, &ctxNow.fsOpenReq, ctxNow.localPath.c_str(), UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, + S_IWUSR | S_IRUSR, OnFileOpen); + ctxNow.transferBegin = Base::GetRuntimeMSec(); + return ret; +} + +bool HdcFile::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ + HdcTransferBase::CommandDispatch(command, payload, payloadSize); + bool ret = true; + switch (command) { + case CMD_FILE_INIT: { // initial + string s = string((char *)payload, payloadSize); + ret = BeginTransfer(&ctxNow, s); + ctxNow.transferBegin = Base::GetRuntimeMSec(); + break; + } + case CMD_FILE_CHECK: { + ret = SlaveCheck(payload, payloadSize); + break; + } + case CMD_FILE_FINISH: { + if (*payload) { // close-step3 + --(*payload); + SendToAnother(CMD_FILE_FINISH, payload, 1); + ++refCount; + uv_fs_close(loopTask, &ctxNow.fsCloseReq, ctxNow.fsOpenReq.result, OnFileClose); + } else { // close-step3 + TransferSummary(&ctxNow); + TaskFinish(); + } + break; + } + default: + break; + } + return ret; +} +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/common/file.h b/services/flashd/common/file.h new file mode 100755 index 00000000..230d3f50 --- /dev/null +++ b/services/flashd/common/file.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_FILE_TRANSFER_H +#define HDC_FILE_TRANSFER_H +#include "common.h" +#include "transfer.h" + +namespace Hdc { +class HdcFile : public HdcTransferBase { +public: + HdcFile(HTaskInfo hTaskInfo); + virtual ~HdcFile(); + void StopTask(); + bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); + +protected: +private: + bool SlaveCheck(uint8_t *payload, const int payloadSize); + void CheckMaster(CtxFile *context); + void WhenTransferFinish(CtxFile *context); + bool BeginTransfer(CtxFile *context, const string &command); + void TransferSummary(CtxFile *context); + bool SetMasterParameters(CtxFile *context, const char *command, int argc, char **argv); +}; +} // namespace Hdc + +#endif \ No newline at end of file diff --git a/services/flashd/common/file_descriptor.cpp b/services/flashd/common/file_descriptor.cpp new file mode 100755 index 00000000..61886062 --- /dev/null +++ b/services/flashd/common/file_descriptor.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "file_descriptor.h" + +namespace Hdc { +HdcFileDescriptor::HdcFileDescriptor(uv_loop_t *loopIn, int fdToRead, void *callerContextIn, + CallBackWhenRead callbackReadIn, CmdResultCallback callbackFinishIn) +{ + loop = loopIn; + workContinue = true; + callbackFinish = callbackFinishIn; + callbackRead = callbackReadIn; + fdIO = fdToRead; + refIO = 0; + callerContext = callerContextIn; +} + +HdcFileDescriptor::~HdcFileDescriptor() +{ + if (refIO > 0) { + WRITE_LOG(LOG_FATAL, "~HdcFileDescriptor refIO > 0"); + } +} + +bool HdcFileDescriptor::ReadyForRelease() +{ + return refIO == 0; +} + +// just tryCloseFdIo = true, callback will be effect +void HdcFileDescriptor::StopWork(bool tryCloseFdIo, std::function closeFdCallback) +{ + workContinue = false; + callbackCloseFd = closeFdCallback; + if (tryCloseFdIo && refIO > 0) { + ++refIO; + reqClose.data = this; + uv_fs_close(loop, &reqClose, fdIO, [](uv_fs_t *req) { + auto thisClass = (HdcFileDescriptor *)req->data; + uv_fs_req_cleanup(req); + if (thisClass->callbackCloseFd != nullptr) { + thisClass->callbackCloseFd(); + } + --thisClass->refIO; + }); + } +}; + +void HdcFileDescriptor::OnFileIO(uv_fs_t *req) +{ + CtxFileIO *ctxIO = static_cast(req->data); + HdcFileDescriptor *thisClass = ctxIO->thisClass; + uint8_t *buf = ctxIO->bufIO; + bool bFinish = false; + bool fetalFinish = false; + + do { + if (req->result > 0) { + if (req->fs_type == UV_FS_READ) { + if (!thisClass->callbackRead(thisClass->callerContext, buf, req->result)) { + bFinish = true; + break; + } + thisClass->LoopRead(); + } else { + // fs_write + } + } else { + WRITE_LOG(LOG_DEBUG, "OnFileIO fd:%d failed:%s", thisClass->fdIO, uv_strerror(req->result)); + bFinish = true; + fetalFinish = true; + break; + } + } while (false); + uv_fs_req_cleanup(req); + delete[] buf; + delete ctxIO; + + --thisClass->refIO; + if (bFinish) { + thisClass->callbackFinish(thisClass->callerContext, fetalFinish, "OnRead finish"); + thisClass->workContinue = false; + } +} + +int HdcFileDescriptor::LoopRead() +{ + uv_buf_t iov; + int readMax = Base::GetMaxBufSize() * 1.2; + auto contextIO = new CtxFileIO(); + auto buf = new uint8_t[readMax](); + if (!contextIO || !buf) { + if (contextIO) { + delete contextIO; + } + if (buf) { + delete[] buf; + } + WRITE_LOG(LOG_FATAL, "Memory alloc failed"); + callbackFinish(callerContext, true, "Memory alloc failed"); + return -1; + } + uv_fs_t *req = &contextIO->fs; + contextIO->bufIO = buf; + contextIO->thisClass = this; + req->data = contextIO; + ++refIO; + iov = uv_buf_init((char *)buf, readMax); + uv_fs_read(loop, req, fdIO, &iov, 1, -1, OnFileIO); + return 0; +} + +bool HdcFileDescriptor::StartWork() +{ + if (LoopRead() < 0) { + return false; + } + return true; +} + +int HdcFileDescriptor::Write(uint8_t *data, int size) +{ + if (size > static_cast(HDC_BUF_MAX_BYTES)) { + size = static_cast(HDC_BUF_MAX_BYTES); + } + auto buf = new uint8_t[size]; + if (!buf) { + return -1; + } + memcpy_s(buf, size, data, size); + return WriteWithMem(buf, size); +} + +// Data's memory must be Malloc, and the callback FREE after this function is completed +int HdcFileDescriptor::WriteWithMem(uint8_t *data, int size) +{ + auto contextIO = new CtxFileIO(); + if (!contextIO) { + delete[] data; + WRITE_LOG(LOG_FATAL, "Memory alloc failed"); + callbackFinish(callerContext, true, "Memory alloc failed"); + return -1; + } + uv_fs_t *req = &contextIO->fs; + contextIO->bufIO = data; + contextIO->thisClass = this; + req->data = contextIO; + ++refIO; + + uv_buf_t iov = uv_buf_init((char *)data, size); + uv_fs_write(loop, req, fdIO, &iov, 1, -1, OnFileIO); + return size; +} +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/common/file_descriptor.h b/services/flashd/common/file_descriptor.h new file mode 100755 index 00000000..40311e71 --- /dev/null +++ b/services/flashd/common/file_descriptor.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_FILE_DESCRIPTOR_H +#define HDC_FILE_DESCRIPTOR_H +#include "common.h" + +namespace Hdc { +class HdcFileDescriptor { +public: + // callerContext, normalFinish, errorString + using CmdResultCallback = std::function; + // callerContext, readBuf, readIOByes + using CallBackWhenRead = std::function; + HdcFileDescriptor(uv_loop_t *loopIn, int fdToRead, void *callerContextIn, CallBackWhenRead callbackReadIn, + CmdResultCallback callbackFinishIn); + virtual ~HdcFileDescriptor(); + int Write(uint8_t *data, int size); + int WriteWithMem(uint8_t *data, int size); + + bool ReadyForRelease(); + bool StartWork(); + void StopWork(bool tryCloseFdIo, std::function closeFdCallback); + +protected: +private: + struct CtxFileIO { + uv_fs_t fs; + uint8_t *bufIO; + HdcFileDescriptor *thisClass; + }; + static void OnFileIO(uv_fs_t *req); + int LoopRead(); + + std::function callbackCloseFd; + CmdResultCallback callbackFinish; + CallBackWhenRead callbackRead; + uv_loop_t *loop; + uv_fs_t reqClose; + void *callerContext; + bool workContinue; + int fdIO; + int refIO; +}; +} // namespace Hdc + +#endif // HDC_FILE_DESCRIPTOR_H \ No newline at end of file diff --git a/services/flashd/common/forward.cpp b/services/flashd/common/forward.cpp new file mode 100755 index 00000000..b096cbb9 --- /dev/null +++ b/services/flashd/common/forward.cpp @@ -0,0 +1,789 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "forward.h" +#include "base.h" + +namespace Hdc { +HdcForwardBase::HdcForwardBase(HTaskInfo hTaskInfo) + : HdcTaskBase(hTaskInfo) +{ +} + +HdcForwardBase::~HdcForwardBase() +{ + WRITE_LOG(LOG_DEBUG, "~HdcForwardBase"); +}; + +bool HdcForwardBase::ReadyForRelease() +{ + if (!HdcTaskBase::ReadyForRelease()) { + return false; + } + return true; +} + +void HdcForwardBase::StopTask() +{ + map::iterator iter; + for (iter = mapCtxPoint.begin(); iter != mapCtxPoint.end(); ++iter) { + HCtxForward ctx = iter->second; + FreeContext(ctx, 0, false); + } + // FREECONTEXT in the STOP is triggered by the other party sector, no longer notifying each other. + mapCtxPoint.clear(); +}; + +void HdcForwardBase::OnAccept(uv_stream_t *server, HCtxForward ctxClient, uv_stream_t *client) +{ + HCtxForward ctxListen = (HCtxForward)server->data; + char buf[BUF_SIZE_DEFAULT] = { 0 }; + bool ret = false; + while (true) { + if (uv_accept(server, client)) { + break; + } + ctxClient->type = ctxListen->type; + ctxClient->remoteParamenters = ctxListen->remoteParamenters; + int maxSize = sizeof(buf) - FORWARD_PARAMENTER_BUFSIZE; + // clang-format off + if (snprintf_s(buf + FORWARD_PARAMENTER_BUFSIZE, maxSize, maxSize - 1, "%s", + ctxClient->remoteParamenters.c_str()) < 0) { + break; + } + // clang-format on + // pre 8bytes preserve for param bits + SendToTask(ctxClient->id, CMD_FORWARD_ACTIVE_SLAVE, (uint8_t *)buf, + strlen(buf + FORWARD_PARAMENTER_BUFSIZE) + 9); + ret = true; + break; + } + if (!ret) { + FreeContext(ctxClient, 0, false); + } +} + +void HdcForwardBase::ListenCallback(uv_stream_t *server, const int status) +{ + HCtxForward ctxListen = (HCtxForward)server->data; + HdcForwardBase *thisClass = ctxListen->thisClass; + uv_stream_t *client = nullptr; + + if (status == -1 || !ctxListen->ready) { + thisClass->FreeContext(ctxListen, 0, false); + thisClass->TaskFinish(); + return; + } + HCtxForward ctxClient = (HCtxForward)thisClass->MallocContext(true); + if (!ctxClient) { + return; + } + if (FORWARD_TCP == ctxListen->type) { + uv_tcp_init(ctxClient->thisClass->loopTask, &ctxClient->tcp); + client = (uv_stream_t *)&ctxClient->tcp; + } else { + // FORWARD_ABSTRACT, FORWARD_RESERVED, FORWARD_FILESYSTEM, + uv_pipe_init(ctxClient->thisClass->loopTask, &ctxClient->pipe, 0); + client = (uv_stream_t *)&ctxClient->pipe; + } + thisClass->OnAccept(server, ctxClient, client); +} + +void *HdcForwardBase::MallocContext(bool masterSlave) +{ + HCtxForward ctx = nullptr; + if ((ctx = new ContextForward()) == nullptr) { + return nullptr; + } + ctx->id = Base::GetRuntimeMSec(); + ctx->masterSlave = masterSlave; + ctx->thisClass = this; + ctx->fdClass = nullptr; + ctx->tcp.data = ctx; + ctx->pipe.data = ctx; + AdminContext(OP_ADD, ctx->id, ctx); + refCount++; + return ctx; +} + +void HdcForwardBase::FreeContextCallBack(HCtxForward ctx) +{ + AdminContext(OP_REMOVE, ctx->id, nullptr); + Base::DoNextLoop(loopTask, ctx, [](const uint8_t flag, string &msg, const void *data) { + HCtxForward ctx = (HCtxForward)data; + delete ctx; + }); + --refCount; +} + +void HdcForwardBase::FreeJDWP(HCtxForward ctx) +{ + if (ctx->fd > 0) { + close(ctx->fd); + } + if (ctx->fdClass) { + ctx->fdClass->StopWork(false, nullptr); + + auto funcReqClose = [](uv_idle_t *handle) -> void { + uv_close_cb funcIdleHandleClose = [](uv_handle_t *handle) -> void { + HCtxForward ctx = (HCtxForward)handle->data; + ctx->thisClass->FreeContextCallBack(ctx); + delete (uv_idle_t *)handle; + }; + HCtxForward ctx = (HCtxForward)handle->data; + if (ctx->fdClass->ReadyForRelease()) { + delete ctx->fdClass; + ctx->fdClass = nullptr; + Base::TryCloseHandle((uv_handle_t *)handle, funcIdleHandleClose); + } + }; + Base::IdleUvTask(loopTask, ctx, funcReqClose); + } +} + +void HdcForwardBase::FreeContext(HCtxForward ctxIn, const uint32_t id, bool bNotifyRemote) +{ + WRITE_LOG(LOG_DEBUG, "FreeContext bNotifyRemote:%d %p", bNotifyRemote, ctxIn); + HCtxForward ctx = nullptr; + if (!ctxIn) { + if (!(ctx = (HCtxForward)AdminContext(OP_QUERY, id, nullptr))) { + WRITE_LOG(LOG_DEBUG, "Query id failed"); + return; + } + } else { + ctx = ctxIn; + } + if (ctx->finish) { + return; + } + if (bNotifyRemote) { + SendToTask(ctx->id, CMD_FORWARD_FREE_CONTEXT, nullptr, 0); + } + uv_close_cb funcHandleClose = [](uv_handle_t *handle) -> void { + HCtxForward ctx = (HCtxForward)handle->data; + ctx->thisClass->FreeContextCallBack(ctx); + }; + switch (ctx->type) { + case FORWARD_TCP: + case FORWARD_JDWP: + Base::TryCloseHandle((uv_handle_t *)&ctx->tcp, true, funcHandleClose); + break; + case FORWARD_ABSTRACT: + case FORWARD_RESERVED: + case FORWARD_FILESYSTEM: + Base::TryCloseHandle((uv_handle_t *)&ctx->pipe, true, funcHandleClose); + break; + case FORWARD_DEVICE: { + FreeJDWP(ctx); + break; + } + default: + break; + } + ctx->finish = true; +} + +bool HdcForwardBase::SendToTask(const uint32_t cid, const uint16_t command, uint8_t *bufPtr, const int bufSize) +{ + bool ret = false; + // usually MAX_SIZE_IOBUF*2 from HdcFileDescriptor maxIO + if (bufSize > Base::GetMaxBufSize() * 2) { + return false; + } + auto newBuf = new uint8_t[bufSize + 4]; + if (!newBuf) { + return false; + } + *(uint32_t *)(newBuf) = htonl(cid); + if (bufSize > 0 && bufPtr != nullptr && memcpy_s(newBuf + 4, bufSize, bufPtr, bufSize) != EOK) { + delete[] newBuf; + return false; + } + ret = SendToAnother(command, newBuf, bufSize + 4); + delete[] newBuf; + return ret; +} + +// Forward flow is small and frequency is fast +void HdcForwardBase::AllocForwardBuf(uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf) +{ + const uint16_t size = 1492 - 256; // For layer 3, the default MTU is 1492 bytes. reserve hdc header 256 bytes + buf->base = (char *)new char[size]; + if (buf->base) { + buf->len = size - 1; + } else { + WRITE_LOG(LOG_WARN, "AllocForwardBuf == null"); + } +} + +void HdcForwardBase::ReadForwardBuf(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) +{ + HCtxForward ctx = (HCtxForward)stream->data; + if (nread < 0) { + ctx->thisClass->FreeContext(ctx, 0, true); + return; + } + ctx->thisClass->SendToTask(ctx->id, CMD_FORWARD_DATA, (uint8_t *)buf->base, nread); + // clear + delete[] buf->base; +} + +void HdcForwardBase::ConnectTarget(uv_connect_t *connection, int status) +{ + HCtxForward ctx = (HCtxForward)connection->data; + HdcForwardBase *thisClass = ctx->thisClass; + delete connection; + if (status < 0) { + WRITE_LOG(LOG_WARN, "Forward connect result:%d error:%s", status, uv_err_name(status)); + } + thisClass->SetupPointContinue(ctx, status); +} + +bool HdcForwardBase::CheckNodeInfo(const char *nodeInfo, string as[2]) +{ + char bufString[BUF_SIZE_MEDIUM]; + if (!strchr(nodeInfo, ':')) { + return false; + } + if (EOK != strcpy_s(bufString, sizeof(bufString), nodeInfo)) { + return false; + } + if (*strchr(bufString, ':')) { + *strchr(bufString, ':') = '\0'; + } else { + return false; + } + as[0] = bufString; + as[1] = bufString + strlen(bufString) + 1; + if (as[0].size() > BUF_SIZE_SMALL || as[1].size() > BUF_SIZE_SMALL) { + return false; + } + if (as[0] == "tcp") { + int port = atoi(as[1].c_str()); + if (port <= 0 || port > MAX_IP_PORT) { + return false; + } + } + return true; +} + +bool HdcForwardBase::SetupPointContinue(HCtxForward ctx, int status) +{ + if (ctx->checkPoint) { + // send to active + uint8_t flag = status > 0; + SendToTask(ctx->id, CMD_FORWARD_CHECK_RESULT, &flag, 1); + FreeContext(ctx, 0, false); + return true; + } + if (status < 0) { + FreeContext(ctx, 0, true); + return false; + } + // send to active + if (!SendToTask(ctx->id, CMD_FORWARD_ACTIVE_MASTER, nullptr, 0)) { + FreeContext(ctx, 0, true); + return false; + } + return DoForwardBegin(ctx); +} + +bool HdcForwardBase::DetechForwardType(HCtxForward ctxPoint) +{ + string &sFType = ctxPoint->localArgs[0]; + string &sNodeCfg = ctxPoint->localArgs[1]; + // string to enum + if (sFType == "tcp") { + ctxPoint->type = FORWARD_TCP; + } else if (sFType == "dev") { + ctxPoint->type = FORWARD_DEVICE; + } else if (sFType == "localabstract") { + // daemon shell: /system/bin/socat abstract-listen:linux-abstract - + // daemon shell: /system/bin/socat - abstract-connect:linux-abstract + // host: hdc_std fport tcp:8080 localabstract:linux-abstract + ctxPoint->type = FORWARD_ABSTRACT; + } else if (sFType == "localreserved") { + sNodeCfg = HARMONY_RESERVED_SOCKET_PREFIX + sNodeCfg; + ctxPoint->type = FORWARD_RESERVED; + } else if (sFType == "localfilesystem") { + sNodeCfg = FILESYSTEM_SOCKET_PREFIX + sNodeCfg; + ctxPoint->type = FORWARD_FILESYSTEM; + } else if (sFType == "jdwp") { + ctxPoint->type = FORWARD_JDWP; + } else { + return false; + } + return true; +} + +bool HdcForwardBase::SetupTCPPoint(HCtxForward ctxPoint) +{ + string &sNodeCfg = ctxPoint->localArgs[1]; + int port = atoi(sNodeCfg.c_str()); + ctxPoint->tcp.data = ctxPoint; + uv_tcp_init(loopTask, &ctxPoint->tcp); + struct sockaddr_in addr; + if (ctxPoint->masterSlave) { + uv_ip4_addr("0.0.0.0", port, &addr); // loop interface + uv_tcp_bind(&ctxPoint->tcp, (const struct sockaddr *)&addr, 0); + if (uv_listen((uv_stream_t *)&ctxPoint->tcp, 4, ListenCallback)) { + ctxPoint->lastError = "TCP Port listen failed at " + sNodeCfg; + return false; + } + } else { + uv_ip4_addr("127.0.0.1", port, &addr); // loop interface + uv_connect_t *conn = new uv_connect_t(); + conn->data = ctxPoint; + uv_tcp_connect(conn, (uv_tcp_t *)&ctxPoint->tcp, (const struct sockaddr *)&addr, ConnectTarget); + } + return true; +} + +bool HdcForwardBase::SetupDevicePoint(HCtxForward ctxPoint) +{ + uint8_t flag = 1; + string &sNodeCfg = ctxPoint->localArgs[1]; + string resolvedPath = Base::CanonicalizeSpecPath(sNodeCfg); + if ((ctxPoint->fd = open(resolvedPath.c_str(), O_RDWR)) < 0) { + ctxPoint->lastError = "Open unix-dev failed"; + flag = -1; + } + auto funcRead = [&](const void *a, uint8_t *b, const int c) -> bool { + HCtxForward ctx = (HCtxForward)a; + return SendToTask(ctx->id, CMD_FORWARD_DATA, b, c); + }; + auto funcFinish = [&](const void *a, const bool b, const string c) -> bool { + HCtxForward ctx = (HCtxForward)a; + WRITE_LOG(LOG_DEBUG, "Error ReadForwardBuf dev,ret:%d reson:%s", b, c.c_str()); + FreeContext(ctx, 0, true); + return false; + }; + ctxPoint->fdClass = new HdcFileDescriptor(loopTask, ctxPoint->fd, ctxPoint, funcRead, funcFinish); + SetupPointContinue(ctxPoint, flag); + return true; +} + +bool HdcForwardBase::LocalAbstractConnect(uv_pipe_t *pipe, string &sNodeCfg) +{ + bool abstractRet = false; +#ifndef _WIN32 + int s = 0; + do { + if ((s = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) { + break; + } + fcntl(s, F_SETFD, FD_CLOEXEC); + struct sockaddr_un addr; + Base::ZeroStruct(addr); + int addrLen = sNodeCfg.size() + offsetof(struct sockaddr_un, sun_path) + 1; + addr.sun_family = AF_LOCAL; + addr.sun_path[0] = 0; + + if (memcpy_s(addr.sun_path + 1, sizeof(addr.sun_path) - 1, sNodeCfg.c_str(), sNodeCfg.size()) != EOK) { + break; + }; + // local connect, ignore timeout + if (connect(s, (struct sockaddr *)&addr, addrLen) < 0) { + break; + } + if (uv_pipe_open(pipe, s)) { + break; + } + abstractRet = true; + } while (false); + if (!abstractRet && s > 0) { + close(s); + } +#endif + return abstractRet; +} + +bool HdcForwardBase::SetupFilePoint(HCtxForward ctxPoint) +{ + string &sNodeCfg = ctxPoint->localArgs[1]; + ctxPoint->pipe.data = ctxPoint; + uv_pipe_init(loopTask, &ctxPoint->pipe, 0); + if (ctxPoint->masterSlave) { + if (ctxPoint->type == FORWARD_RESERVED || ctxPoint->type == FORWARD_FILESYSTEM) { + unlink(sNodeCfg.c_str()); + } + if (uv_pipe_bind(&ctxPoint->pipe, sNodeCfg.c_str())) { + ctxPoint->lastError = "Unix pipe bind failed"; + return false; + } + if (uv_listen((uv_stream_t *)&ctxPoint->pipe, 4, ListenCallback)) { + ctxPoint->lastError = "Unix pipe listen failed"; + return false; + } + } else { + uv_connect_t *connect = new uv_connect_t(); + connect->data = ctxPoint; + if (ctxPoint->type == FORWARD_ABSTRACT) { + bool abstractRet = LocalAbstractConnect(&ctxPoint->pipe, sNodeCfg); + SetupPointContinue(ctxPoint, abstractRet ? 0 : -1); + if (!abstractRet) { + ctxPoint->lastError = "LocalAbstractConnect failed"; + return false; + } + } else { + uv_pipe_connect(connect, &ctxPoint->pipe, sNodeCfg.c_str(), ConnectTarget); + } + } + return true; +} + +bool HdcForwardBase::SetupPoint(HCtxForward ctxPoint) +{ + bool ret = true; + if (!DetechForwardType(ctxPoint)) { + return false; + } + switch (ctxPoint->type) { + case FORWARD_TCP: + if (!SetupTCPPoint(ctxPoint)) { + ret = false; + }; + break; +#ifndef _WIN32 + case FORWARD_DEVICE: + if (!SetupDevicePoint(ctxPoint)) { + ret = false; + }; + break; + case FORWARD_JDWP: + if (!SetupJdwpPoint(ctxPoint)) { + ret = false; + }; + break; + case FORWARD_ABSTRACT: + case FORWARD_RESERVED: + case FORWARD_FILESYSTEM: + if (!SetupFilePoint(ctxPoint)) { + ret = false; + }; + break; +#else + case FORWARD_DEVICE: + case FORWARD_JDWP: + case FORWARD_ABSTRACT: + case FORWARD_RESERVED: + case FORWARD_FILESYSTEM: + ctxPoint->lastError = "Not supoort forward-type"; + ret = false; + break; +#endif + default: + ctxPoint->lastError = "Not supoort forward-type"; + ret = false; + break; + } + return ret; +} + +bool HdcForwardBase::BeginForward(const char *command, string &sError) +{ + bool ret = false; + int argc = 0; + char bufString[BUF_SIZE_SMALL] = ""; + HCtxForward ctxPoint = (HCtxForward)MallocContext(true); + if (!ctxPoint) { + WRITE_LOG(LOG_FATAL, "MallocContext failed"); + return false; + } + char **argv = Base::SplitCommandToArgs(command, &argc); + while (true) { + if (argc < CMD_ARG1_COUNT) { + break; + } + if (strlen(argv[0]) > BUF_SIZE_SMALL || strlen(argv[1]) > BUF_SIZE_SMALL) { + break; + } + if (!CheckNodeInfo(argv[0], ctxPoint->localArgs)) { + break; + } + if (!CheckNodeInfo(argv[1], ctxPoint->remoteArgs)) { + break; + } + ctxPoint->remoteParamenters = argv[1]; + if (!SetupPoint(ctxPoint)) { + break; + } + + ret = true; + break; + } + sError = ctxPoint->lastError; + if (ret) { + // First 8-byte parameter bit + int maxBufSize = sizeof(bufString) - FORWARD_PARAMENTER_BUFSIZE; + if (snprintf_s(bufString + FORWARD_PARAMENTER_BUFSIZE, maxBufSize, maxBufSize - 1, "%s", argv[1]) > 0) { + SendToTask(ctxPoint->id, CMD_FORWARD_CHECK, (uint8_t *)bufString, + FORWARD_PARAMENTER_BUFSIZE + strlen(bufString + FORWARD_PARAMENTER_BUFSIZE) + 1); + taskCommand = command; + } + } + if (argv) { + delete[]((char *)argv); + } + return ret; +} + +inline bool HdcForwardBase::FilterCommand(uint8_t *bufCmdIn, uint32_t *idOut, uint8_t **pContentBuf) +{ + *pContentBuf = bufCmdIn + DWORD_SERIALIZE_SIZE; + *idOut = ntohl(*(uint32_t *)bufCmdIn); + return true; +} + +bool HdcForwardBase::SlaveConnect(uint8_t *bufCmd, bool bCheckPoint, string &sError) +{ + bool ret = false; + char *content = nullptr; + uint32_t idSlaveOld = 0; + HCtxForward ctxPoint = (HCtxForward)MallocContext(false); + if (!ctxPoint) { + WRITE_LOG(LOG_FATAL, "MallocContext failed"); + return false; + } + idSlaveOld = ctxPoint->id; + ctxPoint->checkPoint = bCheckPoint; + // refresh another id,8byte param + FilterCommand(bufCmd, &ctxPoint->id, (uint8_t **)&content); + AdminContext(OP_UPDATE, idSlaveOld, ctxPoint); + content += FORWARD_PARAMENTER_BUFSIZE; + if (!CheckNodeInfo(content, ctxPoint->localArgs)) { + return false; + } + if ((ctxPoint->checkPoint && slaveCheckWhenBegin) || !ctxPoint->checkPoint) { + if (!SetupPoint(ctxPoint)) { + WRITE_LOG(LOG_FATAL, "SetupPoint failed"); + goto Finish; + } + sError = ctxPoint->lastError; + } else { + SetupPointContinue(ctxPoint, 0); + } + ret = true; +Finish: + if (!ret) { + FreeContext(ctxPoint, 0, true); + } + return ret; +} + +bool HdcForwardBase::DoForwardBegin(HCtxForward ctx) +{ + switch (ctx->type) { + case FORWARD_TCP: + case FORWARD_JDWP: // jdwp use tcp ->socketpair->jvm + uv_tcp_nodelay((uv_tcp_t *)&ctx->tcp, 1); + uv_read_start((uv_stream_t *)&ctx->tcp, AllocForwardBuf, ReadForwardBuf); + break; + case FORWARD_ABSTRACT: + case FORWARD_RESERVED: + case FORWARD_FILESYSTEM: + uv_read_start((uv_stream_t *)&ctx->pipe, AllocForwardBuf, ReadForwardBuf); + break; + case FORWARD_DEVICE: { + ctx->fdClass->StartWork(); + break; + } + default: + break; + } + ctx->ready = true; + return true; +} + +void *HdcForwardBase::AdminContext(const uint8_t op, const uint32_t id, HCtxForward hInput) +{ + void *hRet = nullptr; + map &mapCtx = mapCtxPoint; + switch (op) { + case OP_ADD: + mapCtx[id] = hInput; + break; + case OP_REMOVE: + mapCtx.erase(id); + break; + case OP_QUERY: + if (mapCtx.count(id)) { + hRet = mapCtx[id]; + } + break; + case OP_UPDATE: + mapCtx.erase(id); + mapCtx[hInput->id] = hInput; + break; + default: + break; + } + return hRet; +} + +void HdcForwardBase::SendCallbackForwardBuf(uv_write_t *req, int status) +{ + ContextForwardIO *ctxIO = (ContextForwardIO *)req->data; + HCtxForward ctx = (HCtxForward)ctxIO->ctxForward; + if (status < 0 && !ctx->finish) { + WRITE_LOG(LOG_DEBUG, "SendCallbackForwardBuf ctx->type:%d, status:%d finish", ctx->type, status); + ctx->thisClass->FreeContext(ctx, 0, true); + } + delete[] ctxIO->bufIO; + delete ctxIO; + delete req; +} + +int HdcForwardBase::SendForwardBuf(HCtxForward ctx, uint8_t *bufPtr, const int size) +{ + int nRet = 0; + if (size > static_cast(HDC_BUF_MAX_BYTES)) { + return -1; + } + auto pDynBuf = new uint8_t[size]; + if (!pDynBuf) { + return -1; + } + memcpy_s(pDynBuf, size, bufPtr, size); + if (FORWARD_DEVICE == ctx->type) { + nRet = ctx->fdClass->WriteWithMem(pDynBuf, size); + } else { + auto ctxIO = new ContextForwardIO(); + if (!ctxIO) { + delete[] pDynBuf; + return -1; + } + ctxIO->ctxForward = ctx; + ctxIO->bufIO = pDynBuf; + if (FORWARD_TCP == ctx->type || FORWARD_JDWP == ctx->type) { + nRet = Base::SendToStreamEx((uv_stream_t *)&ctx->tcp, pDynBuf, size, nullptr, + (void *)SendCallbackForwardBuf, (void *)ctxIO); + } else { + // FORWARD_ABSTRACT, FORWARD_RESERVED, FORWARD_FILESYSTEM, + nRet = Base::SendToStreamEx((uv_stream_t *)&ctx->pipe, pDynBuf, size, nullptr, + (void *)SendCallbackForwardBuf, (void *)ctxIO); + } + } + return nRet; +} + +bool HdcForwardBase::CommandForwardCheckResult(HCtxForward ctx, uint8_t *payload) +{ + bool ret = true; + bool bCheck = (bool)payload; + LogMsg(bCheck ? MSG_OK : MSG_FAIL, "Forwardport result:%s", bCheck ? "OK" : "Failed"); + if (bCheck) { + string mapInfo = taskInfo->serverOrDaemon ? "1|" : "0|"; + mapInfo += taskCommand; + ctx->ready = true; + ServerCommand(CMD_FORWARD_SUCCESS, (uint8_t *)mapInfo.c_str(), mapInfo.size() + 1); + } else { + ret = false; + FreeContext(ctx, 0, false); + } + return ret; +} + +bool HdcForwardBase::ForwardCommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ + bool ret = true; + uint8_t *pContent = nullptr; + int sizeContent = 0; + uint32_t id = 0; + HCtxForward ctx = nullptr; + FilterCommand(payload, &id, &pContent); + sizeContent = payloadSize - DWORD_SERIALIZE_SIZE; + if (!(ctx = (HCtxForward)AdminContext(OP_QUERY, id, nullptr))) { + WRITE_LOG(LOG_WARN, "Query id failed"); + return false; + } + switch (command) { + case CMD_FORWARD_CHECK_RESULT: { + ret = CommandForwardCheckResult(ctx, payload); + break; + } + case CMD_FORWARD_ACTIVE_MASTER: { + ret = DoForwardBegin(ctx); + break; + } + case CMD_FORWARD_DATA: { + if (ctx->finish) { + break; + } + if (SendForwardBuf(ctx, pContent, sizeContent) < 0) { + FreeContext(ctx, 0, true); + } + break; + } + case CMD_FORWARD_FREE_CONTEXT: { + FreeContext(ctx, 0, false); + break; + } + default: + ret = false; + break; + } + if (!ret) { + if (ctx) { + FreeContext(ctx, 0, true); + } else { + WRITE_LOG(LOG_DEBUG, "ctx==nullptr raw free"); + TaskFinish(); + } + } + return ret; +} + +bool HdcForwardBase::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ + bool ret = true; + string sError; + // prepare + if (CMD_FORWARD_INIT == command) { + if (!BeginForward((char *)(payload), sError)) { + ret = false; + goto Finish; + } + return true; + } else if (CMD_FORWARD_CHECK == command) { + // Detect remote if it's reachable + if (!SlaveConnect(payload, true, sError)) { + ret = false; + goto Finish; + } + return true; + } else if (CMD_FORWARD_ACTIVE_SLAVE == command) { + // slave connect target port when activating + if (!SlaveConnect(payload, false, sError)) { + ret = false; + goto Finish; + } + return true; + } + if (!ForwardCommandDispatch(command, payload, payloadSize)) { + ret = false; + goto Finish; + } +Finish: + if (!ret) { + if (!sError.size()) { + LogMsg(MSG_FAIL, "Forward parament failed"); + } else { + LogMsg(MSG_FAIL, (char *)sError.c_str()); + WRITE_LOG(LOG_WARN, (char *)sError.c_str()); + } + } + return ret; +} +} // namespace Hdc diff --git a/services/flashd/common/forward.h b/services/flashd/common/forward.h new file mode 100755 index 00000000..9baf4702 --- /dev/null +++ b/services/flashd/common/forward.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_FORWARD_H +#define HDC_FORWARD_H +#include "common.h" + +namespace Hdc { +class HdcForwardBase : public HdcTaskBase { +public: + HdcForwardBase(HTaskInfo hTaskInfo); + virtual ~HdcForwardBase(); + bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); + bool BeginForward(const char *command, string &sError); + void StopTask(); + bool ReadyForRelease(); + +protected: + enum FORWARD_TYPE { + FORWARD_TCP, + FORWARD_DEVICE, + FORWARD_JDWP, + FORWARD_ABSTRACT, + FORWARD_RESERVED, + FORWARD_FILESYSTEM, + }; + struct ContextForward { + FORWARD_TYPE type; + bool masterSlave; + bool checkPoint; + bool ready; + bool finish; + int fd; + uint32_t id; + uv_tcp_t tcp; + uv_pipe_t pipe; + HdcFileDescriptor *fdClass; + HdcForwardBase *thisClass; + string path; + string lastError; + string localArgs[2]; + string remoteArgs[2]; + string remoteParamenters; + }; + using HCtxForward = struct ContextForward *; + struct ContextForwardIO { + HCtxForward ctxForward; + uint8_t *bufIO; + }; + + virtual bool SetupJdwpPoint(HCtxForward ctxPoint) + { + return false; + } + bool SetupPointContinue(HCtxForward ctx, int status); + +private: + static void ListenCallback(uv_stream_t *server, const int status); + static void ConnectTarget(uv_connect_t *connection, int status); + static void ReadForwardBuf(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); + static void AllocForwardBuf(uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf); + static void SendCallbackForwardBuf(uv_write_t *req, int status); + static void OnFdRead(uv_fs_t *req); + + bool SetupPoint(HCtxForward ctxPoint); + void *MallocContext(bool masterSlave); + bool SlaveConnect(uint8_t *bufCmd, bool bCheckPoint, string &sError); + bool SendToTask(const uint32_t cid, const uint16_t command, uint8_t *bufPtr, const int bufSize); + bool FilterCommand(uint8_t *bufCmdIn, uint32_t *idOut, uint8_t **pContentBuf); + void *AdminContext(const uint8_t op, const uint32_t id, HCtxForward hInput); + bool DoForwardBegin(HCtxForward ctx); + int SendForwardBuf(HCtxForward ctx, uint8_t *bufPtr, const int size); + bool CheckNodeInfo(const char *nodeInfo, string as[2]); + void FreeContext(HCtxForward ctxIn, const uint32_t id, bool bNotifyRemote); + int LoopFdRead(HCtxForward ctx); + void FreeContextCallBack(HCtxForward ctx); + void FreeJDWP(HCtxForward ctx); + void OnAccept(uv_stream_t *server, HCtxForward ctxClient, uv_stream_t *client); + bool DetechForwardType(HCtxForward ctxPoint); + bool SetupTCPPoint(HCtxForward ctxPoint); + bool SetupDevicePoint(HCtxForward ctxPoint); + bool SetupFilePoint(HCtxForward ctxPoint); + bool ForwardCommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); + bool CommandForwardCheckResult(HCtxForward ctx, uint8_t *payload); + bool LocalAbstractConnect(uv_pipe_t *pipe, string &sNodeCfg); + + map mapCtxPoint; + string taskCommand; + const uint8_t FORWARD_PARAMENTER_BUFSIZE = 8; + const string FILESYSTEM_SOCKET_PREFIX = "/tmp/"; + const string HARMONY_RESERVED_SOCKET_PREFIX = "/dev/socket/"; + // set true to enable slave check when forward create + const bool slaveCheckWhenBegin = false; +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/common/serial_struct.h b/services/flashd/common/serial_struct.h new file mode 100755 index 00000000..b151f9dc --- /dev/null +++ b/services/flashd/common/serial_struct.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_SERIAL_STRUCT_H +#define HDC_SERIAL_STRUCT_H +#include "common.h" +#include "serial_struct_define.h" +#include "transfer.h" + +namespace Hdc { +namespace SerialStruct { + constexpr int fieldOne = 1; + constexpr int fieldTwo = 2; + constexpr int fieldThree = 3; + constexpr int fieldFour = 4; + constexpr int fieldFive = 5; + constexpr int fieldSix = 6; + constexpr int fieldSeven = 7; + constexpr int fieldEight = 8; + constexpr int fieldNine = 9; + constexpr int fieldTen = 10; + constexpr int field11 = 11; + constexpr int field12 = 12; + constexpr int field13 = 13; + + template<> struct Descriptor { + static auto type() + { + return Message(Field("fileSize"), + Field("atime"), + Field("mtime"), + Field("options"), + Field("path"), + Field("optionalName"), + Field("updateIfNew"), + Field("compressType"), + Field("holdTimestamp"), + Field("functionName"), + Field("clientCwd"), + Field("reserve1"), + Field("reserve2")); + } + }; + + template<> struct Descriptor { + static auto type() + { + return Message(Field("index"), + Field("compressType"), + Field("compressSize"), + Field("uncompressSize")); + } + }; + + template<> struct Descriptor { + static auto type() + { + return Message(Field("banner"), + Field("authType"), + Field("sessionId"), + Field("connectKey"), + Field("buf")); + } + }; + + template<> struct Descriptor { + static auto type() + { + return Message(Field("channelId"), + Field("commandFlag"), + Field("checkSum"), + Field("vCode")); + } + }; +} // SerialStruct +} // Hdc +#endif // HDC_SERIAL_STRUCT_H diff --git a/services/flashd/common/serial_struct_define.h b/services/flashd/common/serial_struct_define.h new file mode 100755 index 00000000..f2beb1cd --- /dev/null +++ b/services/flashd/common/serial_struct_define.h @@ -0,0 +1,1314 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_SERIAL_STRUCT_DEFINE_H +#define HDC_SERIAL_STRUCT_DEFINE_H +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// static file define. No need not modify. by zako +namespace Hdc { +// clang-format off +namespace SerialStruct { + namespace SerialDetail { + template struct MemPtr { + }; + template struct MemPtr { + using type = T; + using MemberType = U; + }; + template struct MessageImpl { + public: + MessageImpl(Fields &&... fields) + : _fields(std::move(fields)...) + { + } + + template void Visit(Handler &&handler) const + { + VisitImpl(std::forward(handler), std::make_index_sequence()); + } + + private: + std::tuple _fields; + + template void VisitImpl(Handler &&handler, std::index_sequence) const + { + (handler(std::get(_fields)), ...); + } + }; + + template struct FieldImpl { + using type = typename SerialDetail::MemPtr::type; + using MemberType = typename SerialDetail::MemPtr::MemberType; + constexpr static const uint32_t tag = Tag; + constexpr static const uint32_t flags = Flags; + const std::string field_name; + + static decltype(auto) get(const type &value) + { + return value.*MemPtr; + } + + static decltype(auto) get(type &value) + { + return value.*MemPtr; + } + }; + + template struct OneofFieldImpl { + using type = typename SerialDetail::MemPtr::type; + using MemberType = typename SerialDetail::MemPtr::MemberType; + constexpr static const uint32_t tag = Tag; + constexpr static const size_t index = Index; + constexpr static const uint32_t flags = Flags; + const std::string field_name; + + static decltype(auto) get(const type &value) + { + return value.*MemPtr; + } + + static decltype(auto) get(type &value) + { + return value.*MemPtr; + } + }; + + template + struct MapFieldImpl { + using type = typename SerialDetail::MemPtr::type; + using MemberType = typename SerialDetail::MemPtr::MemberType; + constexpr static const uint32_t tag = Tag; + constexpr static const uint32_t KEY_FLAGS = KeyFlags; + constexpr static const uint32_t VALUE_FLAGS = ValueFlags; + + const std::string field_name; + + static decltype(auto) get(const type &value) + { + return value.*MemPtr; + } + + static decltype(auto) get(type &value) + { + return value.*MemPtr; + } + }; + } + + enum class WireType : uint32_t { + VARINT = 0, + FIXED64 = 1, + LENGTH_DELIMETED = 2, + START_GROUP = 3, + END_GROUP = 4, + FIXED32 = 5, + }; + enum flags { no = 0, s = 1, f = 2 }; + template struct FlagsType { + }; + + template struct Descriptor { + static_assert(sizeof(T) == 0, "You need to implement descriptor for your own types"); + static void type() + { + } + }; + + template constexpr auto Message(Fields &&... fields) + { + return SerialDetail::MessageImpl(std::forward(fields)...); + } + + template constexpr auto Field(const std::string &fieldName) + { + return SerialDetail::FieldImpl { fieldName }; + } + + template + constexpr auto OneofField(const std::string &fieldName) + { + return SerialDetail::OneofFieldImpl { fieldName }; + } + + template + constexpr auto MapField(const std::string &fieldName) + { + return SerialDetail::MapFieldImpl { fieldName }; + } + + template const auto &MessageType() + { + static const auto message = Descriptor::type(); + return message; + } + + template struct Serializer; + + struct Writer { + virtual void Write(const void *bytes, size_t size) = 0; + }; + + struct reader { + virtual size_t Read(void *bytes, size_t size) = 0; + }; + + namespace SerialDetail { + template + struct HasSerializePacked : public std::false_type { + }; + + template + struct HasSerializePacked().SerializePacked( + std::declval(), std::declval(), std::declval()))>> : public std::true_type { + }; + + template + constexpr bool HAS_SERIALIZE_PACKED_V = HasSerializePacked::value; + + template + struct HasParsePacked : public std::false_type { + }; + + template + struct HasParsePacked().ParsePacked( + std::declval(), std::declval(), std::declval()))>> : public std::true_type { + }; + + template + constexpr bool HAS_PARSE_PACKED_V = HasParsePacked::value; + + static uint32_t MakeTagWireType(uint32_t tag, WireType wireType) + { + return (tag << 3) | static_cast(wireType); + } + + static inline void ReadTagWireType(uint32_t tagKey, uint32_t &tag, WireType &wireType) + { + wireType = static_cast(tagKey & 0b0111); + tag = tagKey >> 3; + } + + static uint32_t MakeZigzagValue(int32_t value) + { + return (static_cast(value) << 1) ^ static_cast(value >> 31); + } + + static uint64_t MakeZigzagValue(int64_t value) + { + return (static_cast(value) << 1) ^ static_cast(value >> 63); + } + + static int32_t ReadZigzagValue(uint32_t value) + { + return static_cast((value >> 1) ^ (~(value & 1) + 1)); + } + + static int64_t ReadZigzagValue(uint64_t value) + { + return static_cast((value >> 1) ^ (~(value & 1) + 1)); + } + + template To BitCast(From from) + { + static_assert(sizeof(To) == sizeof(From), ""); + static_assert(std::is_trivially_copyable_v, ""); + static_assert(std::is_trivially_copyable_v, ""); + To to; + memcpy_s(&to, sizeof(To), &from, sizeof(from)); + return to; + } + + struct WriterSizeCollector : public Writer { + void Write(const void *, size_t size) override + { + byte_size += size; + } + size_t byte_size = 0; + }; + + struct LimitedReader : public reader { + LimitedReader(reader &parent, size_t sizeLimit) + : _parent(parent), _size_limit(sizeLimit) + { + } + + size_t Read(void *bytes, size_t size) + { + auto sizeToRead = std::min(size, _size_limit); + auto readSize = _parent.Read(bytes, sizeToRead); + _size_limit -= readSize; + return readSize; + } + + size_t AvailableBytes() const + { + return _size_limit; + } + + private: + reader &_parent; + size_t _size_limit; + }; + + static bool ReadByte(uint8_t &value, reader &in) + { + return in.Read(&value, 1) == 1; + } + + static void WriteVarint(uint32_t value, Writer &out) + { + uint8_t b[5] {}; + for (size_t i = 0; i < 5; ++i) { + b[i] = value & 0b0111'1111; + value >>= 7; + if (value) { + b[i] |= 0b1000'0000; + } else { + out.Write(b, i + 1); + break; + } + } + } + + static void WriteVarint(uint64_t value, Writer &out) + { + uint8_t b[10] {}; + for (size_t i = 0; i < 10; ++i) { + b[i] = value & 0b0111'1111; + value >>= 7; + if (value) { + b[i] |= 0b1000'0000; + } else { + out.Write(b, i + 1); + break; + } + } + } + +#if defined(HOST_MAC) + static void WriteVarint(unsigned long value, Writer &out) + { + WriteVarint(static_cast(value), out); + } +#endif + + static bool ReadVarint(uint32_t &value, reader &in) + { + value = 0; + for (size_t c = 0; c < 5; ++c) { + uint8_t x; + if (!ReadByte(x, in)) { + return false; + } + value |= static_cast(x & 0b0111'1111) << 7 * c; + if (!(x & 0b1000'0000)) { + return true; + } + } + + return false; + } + + static bool ReadVarint(uint64_t &value, reader &in) + { + value &= 0; + for (size_t c = 0; c < 10; ++c) { + uint8_t x; + if (!ReadByte(x, in)) { + return false; + } + value |= static_cast(x & 0b0111'1111) << 7 * c; + if (!(x & 0b1000'0000)) { + return true; + } + } + return false; + } + +#if defined(HOST_MAC) + static bool ReadVarint(unsigned long &value, reader &in) + { + uint64_t intermediateValue; + if (ReadVarint(intermediateValue, in)) { + value = static_cast(intermediateValue); + return true; + } + return false; + } +#endif + + static void WriteFixed(uint32_t value, Writer &out) + { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + out.Write(&value, sizeof(value)); +#else + static_assert(false, "Not a little-endian"); +#endif + } + + static void WriteFixed(uint64_t value, Writer &out) + { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + out.Write(&value, sizeof(value)); +#else + static_assert(false, "Not a little-endian"); +#endif + } + + static void WriteFixed(double value, Writer &out) + { + WriteFixed(BitCast(value), out); + } + + static void WriteFixed(float value, Writer &out) + { + WriteFixed(BitCast(value), out); + } + + static void WriteVarint(int32_t value, Writer &out) + { + WriteVarint(BitCast(value), out); + } + + static void WriteVarint(int64_t value, Writer &out) + { + WriteVarint(BitCast(value), out); + } + + static void WriteSignedVarint(int32_t value, Writer &out) + { + WriteVarint(MakeZigzagValue(value), out); + } + + static void WriteSignedVarint(int64_t value, Writer &out) + { + WriteVarint(MakeZigzagValue(value), out); + } + + static void WriteSignedFixed(int32_t value, Writer &out) + { + WriteFixed(static_cast(value), out); + } + + static void WriteSignedFixed(int64_t value, Writer &out) + { + WriteFixed(static_cast(value), out); + } + + static void WriteTagWriteType(uint32_t tag, WireType wireType, Writer &out) + { + WriteVarint(MakeTagWireType(tag, wireType), out); + } + + static bool ReadFixed(uint32_t &value, reader &in) + { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return in.Read(&value, sizeof(value)) == sizeof(value); +#else + static_assert(false, "Not a little-endian"); +#endif + } + + static bool ReadFixed(uint64_t &value, reader &in) + { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return in.Read(&value, sizeof(value)) == sizeof(value); +#else + static_assert(false, "Not a little-endian"); +#endif + } + + static bool ReadFixed(double &value, reader &in) + { + uint64_t intermediateValue; + if (ReadFixed(intermediateValue, in)) { + value = BitCast(intermediateValue); + return true; + } + return false; + } + + static bool ReadFixed(float &value, reader &in) + { + uint32_t intermediateValue; + if (ReadFixed(intermediateValue, in)) { + value = BitCast(intermediateValue); + return true; + } + return false; + } + + static bool ReadVarint(int32_t &value, reader &in) + { + uint32_t intermediateValue; + if (ReadVarint(intermediateValue, in)) { + value = BitCast(intermediateValue); + return true; + } + return false; + } + + static bool ReadVarint(int64_t &value, reader &in) + { + uint64_t intermediateValue; + if (ReadVarint(intermediateValue, in)) { + value = BitCast(intermediateValue); + return true; + } + return false; + } + + static bool ReadSignedVarint(int32_t &value, reader &in) + { + uint32_t intermediateValue; + if (ReadVarint(intermediateValue, in)) { + value = ReadZigzagValue(intermediateValue); + return true; + } + return false; + } + + static bool ReadSignedVarint(int64_t &value, reader &in) + { + uint64_t intermediateValue; + if (ReadVarint(intermediateValue, in)) { + value = ReadZigzagValue(intermediateValue); + return true; + } + return false; + } + + static bool ReadSignedFixed(int32_t &value, reader &in) + { + uint32_t intermediateValue; + if (ReadFixed(intermediateValue, in)) { + value = static_cast(intermediateValue); + return true; + } + return false; + } + + static bool ReadSignedFixed(int64_t &value, reader &in) + { + uint64_t intermediateValue; + if (ReadFixed(intermediateValue, in)) { + value = static_cast(intermediateValue); + return true; + } + return false; + } + + template + void WriteField(const T &value, + const SerialDetail::OneofFieldImpl &, Writer &out) + { + using OneOf = SerialDetail::OneofFieldImpl; + Serializer::template SerializeOneof( + OneOf::tag, OneOf::get(value), FlagsType(), out); + } + + template + void WriteField(const T &value, + const SerialDetail::MapFieldImpl &, Writer &out) + { + using Map = SerialDetail::MapFieldImpl; + Serializer::SerializeMap( + Map::tag, Map::get(value), FlagsType(), FlagsType(), out); + } + + template + void WriteField(const T &value, const SerialDetail::FieldImpl &, Writer &out) + { + using Field = SerialDetail::FieldImpl; + Serializer::Serialize( + Field::tag, Field::get(value), FlagsType(), out); + } + + template + void WriteMessage(const T &value, const SerialDetail::MessageImpl &message, Writer &out) + { + message.Visit([&](const auto &field) { WriteField(value, field, out); }); + } + + template + void WriteRepeated(uint32_t tag, It begin, It end, Writer &out) + { + if (begin == end) { + return; + } + if constexpr (SerialDetail::HAS_SERIALIZE_PACKED_V, ValueType, FlagsType, + Writer>) { + WriteVarint(MakeTagWireType(tag, WireType::LENGTH_DELIMETED), out); + WriterSizeCollector sizeCollector; + for (auto it = begin; it != end; ++it) { + Serializer::SerializePacked(*it, FlagsType {}, sizeCollector); + } + WriteVarint(sizeCollector.byte_size, out); + for (auto it = begin; it != end; ++it) { + Serializer::SerializePacked(*it, FlagsType {}, out); + } + } else { + for (auto it = begin; it != end; ++it) { + Serializer::Serialize(tag, *it, FlagsType(), out); + } + } + } + + template + void WriteMapKeyValue(const std::pair &value, Writer &out) + { + Serializer::Serialize(1, value.first, FlagsType {}, out, true); + Serializer::Serialize(2, value.second, FlagsType {}, out, true); + } + + template + void WriteMap(uint32_t tag, const T &value, Writer &out) + { + auto begin = std::begin(value); + auto end = std::end(value); + + for (auto it = begin; it != end; ++it) { + WriteTagWriteType(tag, WireType::LENGTH_DELIMETED, out); + WriterSizeCollector sizeCollector; + WriteMapKeyValue(*it, sizeCollector); + WriteVarint(sizeCollector.byte_size, out); + WriteMapKeyValue(*it, out); + } + } + + template + bool ReadMapKeyValue(std::pair &value, reader &in) + { + static const auto pairAsMessage = Message(Field<1, &std::pair::first, KeyFlags>("key"), + Field<2, &std::pair::second, ValueFlags>("value")); + return ReadMessage(value, pairAsMessage, in); + } + + template + bool ReadMap(WireType wireType, T &value, reader &in) + { + if (wireType != WireType::LENGTH_DELIMETED) { + return false; + } + size_t size; + if (ReadVarint(size, in)) { + LimitedReader limitedIn(in, size); + while (limitedIn.AvailableBytes() > 0) { + std::pair item; + if (!ReadMapKeyValue(item, limitedIn)) { + return false; + } + value.insert(std::move(item)); + } + return true; + } + return false; + } + + template + bool ReadRepeated(WireType wireType, OutputIt output_it, reader &in) + { + if constexpr (SerialDetail::HAS_PARSE_PACKED_V, ValueType, FlagsType, + reader>) { + if (wireType != WireType::LENGTH_DELIMETED) { + return false; + } + + size_t size; + if (ReadVarint(size, in)) { + LimitedReader limitedIn(in, size); + + while (limitedIn.AvailableBytes() > 0) { + ValueType value; + if (!Serializer::ParsePacked(value, FlagsType(), limitedIn)) { + return false; + } + output_it = value; + ++output_it; + } + return true; + } + return false; + } else { + ValueType value; + if (Serializer::Parse(wireType, value, FlagsType(), in)) { + output_it = value; + ++output_it; + return true; + } + return false; + } + } + + template + void ReadField(T &value, uint32_t tag, WireType wireType, + const SerialDetail::OneofFieldImpl &, reader &in) + { + if (Tag != tag) { + return; + } + using OneOf = SerialDetail::OneofFieldImpl; + Serializer::template ParseOneof( + wireType, OneOf::get(value), FlagsType(), in); + } + + template + void ReadField(T &value, uint32_t tag, WireType wireType, + const SerialDetail::MapFieldImpl &, reader &in) + { + if (Tag != tag) { + return; + } + using Map = SerialDetail::MapFieldImpl; + Serializer::ParseMap( + wireType, Map::get(value), FlagsType(), FlagsType(), in); + } + + template + void ReadField(T &value, uint32_t tag, WireType wireType, + const SerialDetail::FieldImpl &, reader &in) + { + if (Tag != tag) { + return; + } + using Field = SerialDetail::FieldImpl; + Serializer::Parse(wireType, Field::get(value), FlagsType(), in); + } + + template bool ReadMessage(T &value, const MessageImpl &message, reader &in) + { + uint32_t tagKey; + while (ReadVarint(tagKey, in)) { + uint32_t tag; + WireType wireType; + ReadTagWireType(tagKey, tag, wireType); + message.Visit([&](const auto &field) { ReadField(value, tag, wireType, field, in); }); + } + return true; + } + } + + template struct Serializer { + // Commion Serializer threat type as Message + static void Serialize(uint32_t tag, const T &value, FlagsType<>, Writer &out, bool force = false) + { + SerialDetail::WriterSizeCollector sizeCollector; + SerialDetail::WriteMessage(value, MessageType(), sizeCollector); + if (!force && sizeCollector.byte_size == 0) { + return; + } + SerialDetail::WriteTagWriteType(tag, WireType::LENGTH_DELIMETED, out); + SerialDetail::WriteVarint(sizeCollector.byte_size, out); + SerialDetail::WriteMessage(value, MessageType(), out); + } + + static bool Parse(WireType wireType, T &value, FlagsType<>, reader &in) + { + if (wireType != WireType::LENGTH_DELIMETED) { + return false; + } + size_t size; + if (SerialDetail::ReadVarint(size, in)) { + SerialDetail::LimitedReader limitedIn(in, size); + return SerialDetail::ReadMessage(value, MessageType(), limitedIn); + } + return false; + } + }; + + template<> struct Serializer { + static void Serialize(uint32_t tag, int32_t value, FlagsType<>, Writer &out, bool force = false) + { + SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); + SerialDetail::WriteVarint(value, out); + } + + static void Serialize(uint32_t tag, int32_t value, FlagsType, Writer &out, bool force = false) + { + SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); + SerialDetail::WriteSignedVarint(value, out); + } + + static void Serialize( + uint32_t tag, int32_t value, FlagsType, Writer &out, bool force = false) + { + SerialDetail::WriteTagWriteType(tag, WireType::FIXED32, out); + SerialDetail::WriteSignedFixed(value, out); + } + + static void SerializePacked(int32_t value, FlagsType<>, Writer &out) + { + SerialDetail::WriteVarint(value, out); + } + + static void SerializePacked(int32_t value, FlagsType, Writer &out) + { + SerialDetail::WriteSignedVarint(value, out); + } + + static void SerializePacked(int32_t value, FlagsType, Writer &out) + { + SerialDetail::WriteSignedFixed(value, out); + } + + static bool Parse(WireType wire_type, int32_t &value, FlagsType<>, reader &in) + { + if (wire_type != WireType::VARINT) + return false; + return SerialDetail::ReadVarint(value, in); + } + + static bool Parse(WireType wire_type, int32_t &value, FlagsType, reader &in) + { + if (wire_type != WireType::VARINT) + return false; + return SerialDetail::ReadSignedVarint(value, in); + } + + static bool Parse(WireType wire_type, int32_t &value, FlagsType, reader &in) + { + if (wire_type != WireType::FIXED32) + return false; + return SerialDetail::ReadSignedFixed(value, in); + } + + static bool ParsePacked(int32_t &value, FlagsType<>, reader &in) + { + return SerialDetail::ReadVarint(value, in); + } + + static bool ParsePacked(int32_t &value, FlagsType, reader &in) + { + return SerialDetail::ReadSignedVarint(value, in); + } + + static bool ParsePacked(int32_t &value, FlagsType, reader &in) + { + return SerialDetail::ReadSignedFixed(value, in); + } + }; + + template<> struct Serializer { + static void Serialize(uint32_t tag, uint32_t value, FlagsType<>, Writer &out, bool force = false) + { + SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); + SerialDetail::WriteVarint(value, out); + } + + static void Serialize(uint32_t tag, uint32_t value, FlagsType, Writer &out, bool force = false) + { + SerialDetail::WriteTagWriteType(tag, WireType::FIXED32, out); + SerialDetail::WriteFixed(value, out); + } + + static void SerializePacked(uint32_t value, FlagsType<>, Writer &out) + { + SerialDetail::WriteVarint(value, out); + } + + static void SerializePacked(uint32_t value, FlagsType, Writer &out) + { + SerialDetail::WriteFixed(value, out); + } + + static bool Parse(WireType wire_type, uint32_t &value, FlagsType<>, reader &in) + { + if (wire_type != WireType::VARINT) + return false; + return SerialDetail::ReadVarint(value, in); + } + + static bool Parse(WireType wire_type, uint32_t &value, FlagsType, reader &in) + { + if (wire_type != WireType::FIXED32) + return false; + return SerialDetail::ReadFixed(value, in); + } + + static bool ParsePacked(uint32_t &value, FlagsType<>, reader &in) + { + return SerialDetail::ReadVarint(value, in); + } + + static bool ParsePacked(uint32_t &value, FlagsType, reader &in) + { + return SerialDetail::ReadFixed(value, in); + } + }; + + template<> struct Serializer { + static void Serialize(uint32_t tag, int64_t value, FlagsType<>, Writer &out, bool force = false) + { + SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); + SerialDetail::WriteVarint(value, out); + } + + static void Serialize(uint32_t tag, int64_t value, FlagsType, Writer &out, bool force = false) + { + SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); + SerialDetail::WriteSignedVarint(value, out); + } + + static void Serialize( + uint32_t tag, int64_t value, FlagsType, Writer &out, bool force = false) + { + SerialDetail::WriteTagWriteType(tag, WireType::FIXED64, out); + SerialDetail::WriteSignedFixed(value, out); + } + + static void SerializePacked(int64_t value, FlagsType<>, Writer &out) + { + SerialDetail::WriteVarint(value, out); + } + + static void SerializePacked(int64_t value, FlagsType, Writer &out) + { + SerialDetail::WriteSignedVarint(value, out); + } + + static void SerializePacked(int64_t value, FlagsType, Writer &out) + { + SerialDetail::WriteSignedFixed(value, out); + } + + static bool Parse(WireType wire_type, int64_t &value, FlagsType<>, reader &in) + { + if (wire_type != WireType::VARINT) + return false; + return SerialDetail::ReadVarint(value, in); + } + + static bool Parse(WireType wire_type, int64_t &value, FlagsType, reader &in) + { + if (wire_type != WireType::VARINT) + return false; + return SerialDetail::ReadSignedVarint(value, in); + } + + static bool Parse(WireType wire_type, int64_t &value, FlagsType, reader &in) + { + if (wire_type != WireType::FIXED64) + return false; + return SerialDetail::ReadSignedFixed(value, in); + } + + static bool ParsePacked(int64_t &value, FlagsType<>, reader &in) + { + return SerialDetail::ReadVarint(value, in); + } + + static bool ParsePacked(int64_t &value, FlagsType, reader &in) + { + return SerialDetail::ReadSignedVarint(value, in); + } + + static bool ParsePacked(int64_t &value, FlagsType, reader &in) + { + return SerialDetail::ReadSignedFixed(value, in); + } + }; + + template<> struct Serializer { + static void Serialize(uint32_t tag, uint64_t value, FlagsType<>, Writer &out, bool force = false) + { + SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); + SerialDetail::WriteVarint(value, out); + } + + static void Serialize(uint32_t tag, uint64_t value, FlagsType, Writer &out, bool force = false) + { + if (!force && value == UINT64_C(0)) + return; + + SerialDetail::WriteTagWriteType(tag, WireType::FIXED64, out); + SerialDetail::WriteFixed(value, out); + } + + static void SerializePacked(uint64_t value, FlagsType<>, Writer &out) + { + SerialDetail::WriteVarint(value, out); + } + + static void SerializePacked(uint64_t value, FlagsType, Writer &out) + { + SerialDetail::WriteFixed(value, out); + } + + static bool Parse(WireType wire_type, uint64_t &value, FlagsType<>, reader &in) + { + if (wire_type != WireType::VARINT) + return false; + return SerialDetail::ReadVarint(value, in); + } + + static bool Parse(WireType wire_type, uint64_t &value, FlagsType, reader &in) + { + if (wire_type != WireType::FIXED64) + return false; + return SerialDetail::ReadFixed(value, in); + } + + static bool ParsePacked(uint64_t &value, FlagsType<>, reader &in) + { + return SerialDetail::ReadVarint(value, in); + } + + static bool ParsePacked(uint64_t &value, FlagsType, reader &in) + { + return SerialDetail::ReadFixed(value, in); + } + }; + + template<> struct Serializer { + static void Serialize(uint32_t tag, double value, FlagsType<>, Writer &out, bool force = false) + { + if (!force && std::fpclassify(value) == FP_ZERO) { + return; + } + SerialDetail::WriteTagWriteType(tag, WireType::FIXED64, out); + SerialDetail::WriteFixed(value, out); + } + + static void SerializePacked(double value, FlagsType<>, Writer &out) + { + SerialDetail::WriteFixed(value, out); + } + + static bool Parse(WireType wire_type, double &value, FlagsType<>, reader &in) + { + if (wire_type != WireType::FIXED64) { + return false; + } + return SerialDetail::ReadFixed(value, in); + } + + static bool ParsePacked(double &value, FlagsType<>, reader &in) + { + return SerialDetail::ReadFixed(value, in); + } + }; + + template<> struct Serializer { + static void Serialize(uint32_t tag, float value, FlagsType<>, Writer &out, bool force = false) + { + if (!force && std::fpclassify(value) == FP_ZERO) { + return; + } + SerialDetail::WriteTagWriteType(tag, WireType::FIXED32, out); + SerialDetail::WriteFixed(value, out); + } + + static void SerializePacked(float value, FlagsType<>, Writer &out) + { + SerialDetail::WriteFixed(value, out); + } + + static bool Parse(WireType wire_type, float &value, FlagsType<>, reader &in) + { + if (wire_type != WireType::FIXED32) { + return false; + } + return SerialDetail::ReadFixed(value, in); + } + + static bool ParsePacked(float &value, FlagsType<>, reader &in) + { + return SerialDetail::ReadFixed(value, in); + } + }; + + template<> struct Serializer { + static void Serialize(uint32_t tag, bool value, FlagsType<>, Writer &out, bool force = false) + { + Serializer::Serialize(tag, value ? 1 : 0, FlagsType(), out, force); + } + + static void SerializePacked(bool value, FlagsType<>, Writer &out) + { + Serializer::SerializePacked(value ? 1 : 0, FlagsType(), out); + } + + static bool Parse(WireType wire_type, bool &value, FlagsType<>, reader &in) + { + uint32_t intermedaite_value; + if (Serializer::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) { + value = static_cast(intermedaite_value); + return true; + } + return false; + } + + static bool ParsePacked(bool &value, FlagsType<>, reader &in) + { + uint32_t intermedaite_value; + if (Serializer::ParsePacked(intermedaite_value, FlagsType<>(), in)) { + value = static_cast(intermedaite_value); + return true; + } + return false; + } + }; + + template struct Serializer>> { + using U = std::underlying_type_t; + + static void Serialize(uint32_t tag, T value, FlagsType<>, Writer &out, bool force = false) + { + Serializer::Serialize(tag, static_cast(value), FlagsType<>(), out, force); + } + + static void SerializePacked(T value, FlagsType<>, Writer &out) + { + Serializer::SerializePacked(static_cast(value), FlagsType<>(), out); + } + + static bool Parse(WireType wire_type, T &value, FlagsType<>, reader &in) + { + U intermedaite_value; + if (Serializer::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) { + value = static_cast(intermedaite_value); + return true; + } + return false; + } + + static bool ParsePacked(T &value, FlagsType<>, reader &in) + { + U intermedaite_value; + if (Serializer::ParsePacked(intermedaite_value, FlagsType<>(), in)) { + value = static_cast(intermedaite_value); + return true; + } + return false; + } + }; + + template<> struct Serializer { + static void Serialize(uint32_t tag, const std::string &value, FlagsType<>, Writer &out, bool force = false) + { + SerialDetail::WriteTagWriteType(tag, WireType::LENGTH_DELIMETED, out); + SerialDetail::WriteVarint(value.size(), out); + out.Write(value.data(), value.size()); + } + + static bool Parse(WireType wire_type, std::string &value, FlagsType<>, reader &in) + { + if (wire_type != WireType::LENGTH_DELIMETED) { + return false; + } + size_t size; + if (SerialDetail::ReadVarint(size, in)) { + value.resize(size); + if (in.Read(value.data(), size) == size) { + return true; + } + } + return false; + } + }; + + template struct Serializer> { + template + static void Serialize(uint32_t tag, const std::vector &value, FlagsType, Writer &out) + { + SerialDetail::WriteRepeated(tag, value.begin(), value.end(), out); + } + + template + static bool Parse(WireType wire_type, std::vector &value, FlagsType, reader &in) + { + return SerialDetail::ReadRepeated(wire_type, std::back_inserter(value), in); + } + }; + + template struct Serializer> { + template + static void Serialize(uint32_t tag, const std::optional &value, FlagsType, Writer &out) + { + if (!value.has_value()) { + return; + } + Serializer::Serialize(tag, *value, FlagsType(), out); + } + + template + static bool Parse(WireType wire_type, std::optional &value, FlagsType, reader &in) + { + return Serializer::Parse(wire_type, value.emplace(), FlagsType(), in); + } + }; + + template struct Serializer> { + template + static void SerializeOneof(uint32_t tag, const std::variant &value, FlagsType, Writer &out) + { + if (value.index() != Index) + return; + + Serializer>>::Serialize( + tag, std::get(value), FlagsType(), out); + } + + template + static bool ParseOneof(WireType wire_type, std::variant &value, FlagsType, reader &in) + { + return Serializer>>::Parse( + wire_type, value.template emplace(), FlagsType(), in); + } + }; + + template struct Serializer> { + template + static void SerializeMap( + uint32_t tag, const std::map &value, FlagsType, FlagsType, Writer &out) + { + SerialDetail::WriteMap(tag, value, out); + } + + template + static bool ParseMap( + WireType wire_type, std::map &value, FlagsType, FlagsType, reader &in) + { + return SerialDetail::ReadMap(wire_type, value, in); + } + }; + + struct StringWriter : public Writer { + StringWriter(std::string &out) + : _out(out) + { + } + + void Write(const void *bytes, size_t size) override + { + _out.append(reinterpret_cast(bytes), size); + } + + private: + std::string &_out; + }; + + struct StringReader : public reader { + StringReader(const std::string &in) + : _in(in), _pos(0) + { + } + + size_t Read(void *bytes, size_t size) override + { + size_t readSize = std::min(size, _in.size() - _pos); + if (memcpy_s(bytes, size, _in.data() + _pos, readSize) != EOK) { + return readSize; + } + _pos += readSize; + return readSize; + } + + private: + const std::string &_in; + size_t _pos; + }; + // mytype begin, just support base type, but really use protobuf raw type(uint32) + template<> struct Serializer { + static void Serialize(uint32_t tag, uint8_t value, FlagsType<>, Writer &out, bool force = false) + { + Serializer::Serialize(tag, value, FlagsType(), out, force); + } + + static void SerializePacked(uint8_t value, FlagsType<>, Writer &out) + { + Serializer::SerializePacked(value, FlagsType(), out); + } + + static bool Parse(WireType wire_type, uint8_t &value, FlagsType<>, reader &in) + { + uint32_t intermedaite_value; + if (Serializer::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) { + value = static_cast(intermedaite_value); + return true; + } + return false; + } + + static bool ParsePacked(uint8_t &value, FlagsType<>, reader &in) + { + uint32_t intermedaite_value; + if (Serializer::ParsePacked(intermedaite_value, FlagsType<>(), in)) { + value = static_cast(intermedaite_value); + return true; + } + return false; + } + }; + template<> struct Serializer { + static void Serialize(uint32_t tag, uint16_t value, FlagsType<>, Writer &out, bool force = false) + { + Serializer::Serialize(tag, value, FlagsType(), out, force); + } + + static void SerializePacked(uint16_t value, FlagsType<>, Writer &out) + { + Serializer::SerializePacked(value, FlagsType(), out); + } + + static bool Parse(WireType wire_type, uint16_t &value, FlagsType<>, reader &in) + { + uint32_t intermedaite_value; + if (Serializer::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) { + value = static_cast(intermedaite_value); + return true; + } + return false; + } + + static bool ParsePacked(uint16_t &value, FlagsType<>, reader &in) + { + uint32_t intermedaite_value; + if (Serializer::ParsePacked(intermedaite_value, FlagsType<>(), in)) { + value = static_cast(intermedaite_value); + return true; + } + return false; + } + }; + // mytype finish + + template std::string SerializeToString(const T &value) + { + std::string out; + StringWriter stringOut(out); + SerialDetail::WriteMessage(value, MessageType(), stringOut); + return out; + } + + template bool ParseFromString(T &value, const std::string &in) + { + StringReader stringIn(in); + return SerialDetail::ReadMessage(value, MessageType(), stringIn); + } +} +// clang-format on +} // Hdc +#endif // HDC_SERIAL_STRUCT_DEFINE_H diff --git a/services/flashd/common/session.cpp b/services/flashd/common/session.cpp new file mode 100755 index 00000000..bef648a2 --- /dev/null +++ b/services/flashd/common/session.cpp @@ -0,0 +1,1062 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "session.h" +#include "serial_struct.h" + +namespace Hdc { +HdcSessionBase::HdcSessionBase(bool serverOrDaemonIn) +{ + // server/daemon common initialization code + string threadNum = std::to_string(SIZE_THREAD_POOL); + uv_os_setenv("UV_THREADPOOL_SIZE", threadNum.c_str()); + uv_loop_init(&loopMain); + WRITE_LOG(LOG_DEBUG, "loopMain init"); + uv_rwlock_init(&mainAsync); + uv_async_init(&loopMain, &asyncMainLoop, MainAsyncCallback); + uv_rwlock_init(&lockMapSession); + serverOrDaemon = serverOrDaemonIn; + ctxUSB = nullptr; + wantRestart = false; + +#ifdef HDC_HOST + if (serverOrDaemon) { + libusb_init((libusb_context **)&ctxUSB); + } +#endif +} + +HdcSessionBase::~HdcSessionBase() +{ + Base::TryCloseHandle((uv_handle_t *)&asyncMainLoop); + uv_loop_close(&loopMain); + // clear base + uv_rwlock_destroy(&mainAsync); + uv_rwlock_destroy(&lockMapSession); +#ifdef HDC_HOST + if (serverOrDaemon) { + libusb_exit((libusb_context *)ctxUSB); + } +#endif + WRITE_LOG(LOG_DEBUG, "~HdcSessionBase free sessionRef:%d instance:%s", uint32_t(sessionRef), + serverOrDaemon ? "server" : "daemon"); +} + +// remove step2 +bool HdcSessionBase::TryRemoveTask(HTaskInfo hTask) +{ + if (hTask->taskFree) { + return true; + } + bool ret = RemoveInstanceTask(OP_REMOVE, hTask); + if (ret) { + hTask->taskFree = true; + } else { + // This is used to check that the memory cannot be cleaned up. If the memory cannot be released, break point + // here to see which task has not been released + // print task clear + } + return ret; +} + +// remove step1 +bool HdcSessionBase::BeginRemoveTask(HTaskInfo hTask) +{ + bool ret = true; + if (hTask->taskStop || hTask->taskFree || !hTask->taskClass) { + return true; + } + + WRITE_LOG(LOG_DEBUG, "BeginRemoveTask taskType:%d", hTask->taskType); + ret = RemoveInstanceTask(OP_CLEAR, hTask); + auto taskClassDeleteRetry = [](uv_idle_t *handle) -> void { + HTaskInfo hTask = (HTaskInfo)handle->data; + HdcSessionBase *thisClass = (HdcSessionBase *)hTask->ownerSessionClass; + if (!thisClass->TryRemoveTask(hTask)) { + return; + } + HSession hSession = thisClass->AdminSession(OP_QUERY, hTask->sessionId, nullptr); + thisClass->AdminTask(OP_REMOVE, hSession, hTask->channelId, nullptr); + WRITE_LOG(LOG_DEBUG, "TaskDelay task remove finish, channelId:%d", hTask->channelId); + delete hTask; + Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseIdleCallback); + }; + Base::IdleUvTask(hTask->runLoop, hTask, taskClassDeleteRetry); + + hTask->taskStop = true; + ret = true; + return ret; +} + +// Clear all Task or a single Task, the regular situation is stopped first, and the specific class memory is cleaned up +// after the end of the LOOP. +// When ChannelIdinput == 0, at this time, all of the LOOP ends, all runs in the class end, so directly skip STOP, +// physical memory deletion class trimming +void HdcSessionBase::ClearOwnTasks(HSession hSession, const uint32_t channelIDInput) +{ + // First case: normal task cleanup process (STOP Remove) + // Second: The task is cleaned up, the session ends + // Third: The task is cleaned up, and the session is directly over the session. + map::iterator iter; + for (iter = hSession->mapTask->begin(); iter != hSession->mapTask->end();) { + uint32_t channelId = iter->first; + HTaskInfo hTask = iter->second; + if (channelIDInput != 0) { // single + if (channelIDInput != channelId) { + ++iter; + continue; + } + BeginRemoveTask(hTask); + WRITE_LOG(LOG_DEBUG, "ClearOwnTasks OP_CLEAR finish,session:%p channelIDInput:%d", hSession, + channelIDInput); + break; + } + // multi + BeginRemoveTask(hTask); + ++iter; + } +} + +void HdcSessionBase::ClearSessions() +{ + // no need to lock mapSession + // broadcast free singal + for (auto v : mapSession) { + HSession hSession = (HSession)v.second; + if (!hSession->isDead) { + FreeSession(hSession->sessionId); + } + } +} + +void HdcSessionBase::ReMainLoopForInstanceClear() +{ // reloop + auto clearSessionsForFinish = [](uv_idle_t *handle) -> void { + HdcSessionBase *thisClass = (HdcSessionBase *)handle->data; + if (thisClass->sessionRef > 0) { + return; + } + // all task has been free + uv_close((uv_handle_t *)handle, Base::CloseIdleCallback); + uv_stop(&thisClass->loopMain); + }; + Base::IdleUvTask(&loopMain, this, clearSessionsForFinish); + uv_run(&loopMain, UV_RUN_DEFAULT); +}; + +void HdcSessionBase::EnumUSBDeviceRegister(void (*pCallBack)(HSession hSession)) +{ + if (!pCallBack) { + return; + } + uv_rwlock_rdlock(&lockMapSession); + map::iterator i; + for (i = mapSession.begin(); i != mapSession.end(); ++i) { + HSession hs = i->second; + if (hs->connType != CONN_USB) { + continue; + } + if (hs->hUSB == nullptr) { + continue; + } + if (pCallBack) { + pCallBack(hs); + } + break; + } + uv_rwlock_rdunlock(&lockMapSession); +} + +// The PC side gives the device information, determines if the USB device is registered +// PDEV and Busid Devid two choices +HSession HdcSessionBase::QueryUSBDeviceRegister(void *pDev, int busIDIn, int devIDIn) +{ +#ifdef HDC_HOST + libusb_device *dev = (libusb_device *)pDev; + HSession hResult = nullptr; + if (!mapSession.size()) { + return nullptr; + } + uint8_t busId = 0; + uint8_t devId = 0; + if (pDev) { + busId = libusb_get_bus_number(dev); + devId = libusb_get_device_address(dev); + } else { + busId = busIDIn; + devId = devIDIn; + } + uv_rwlock_rdlock(&lockMapSession); + map::iterator i; + for (i = mapSession.begin(); i != mapSession.end(); ++i) { + HSession hs = i->second; + if (hs->connType == CONN_USB) { + continue; + } + if (hs->hUSB == nullptr) { + continue; + } + if (hs->hUSB->devId != devId || hs->hUSB->busId != busId) { + continue; + } + hResult = hs; + break; + } + uv_rwlock_rdunlock(&lockMapSession); + return hResult; +#else + return nullptr; +#endif +} + +void HdcSessionBase::AsyncMainLoopTask(uv_idle_t *handle) +{ + AsyncParam *param = (AsyncParam *)handle->data; + HdcSessionBase *thisClass = (HdcSessionBase *)param->thisClass; + switch (param->method) { + case ASYNC_FREE_SESSION: + // Destruction is unified in the main thread + thisClass->FreeSession(param->sid); // todo Double lock + break; + case ASYNC_STOP_MAINLOOP: + uv_stop(&thisClass->loopMain); + break; + default: + break; + } + if (param->data) { + delete[]((uint8_t *)param->data); + } + delete param; + param = nullptr; + Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseIdleCallback); +} + +void HdcSessionBase::MainAsyncCallback(uv_async_t *handle) +{ + HdcSessionBase *thisClass = (HdcSessionBase *)handle->data; + list::iterator i; + list &lst = thisClass->lstMainThreadOP; + uv_rwlock_wrlock(&thisClass->mainAsync); + for (i = lst.begin(); i != lst.end();) { + AsyncParam *param = (AsyncParam *)*i; + Base::IdleUvTask(&thisClass->loopMain, param, AsyncMainLoopTask); + i = lst.erase(i); + } + uv_rwlock_wrunlock(&thisClass->mainAsync); +} + +void HdcSessionBase::PushAsyncMessage(const uint32_t sessionId, const uint8_t method, const void *data, + const int dataSize) +{ + AsyncParam *param = new AsyncParam(); + if (!param) { + return; + } + param->sid = sessionId; + param->thisClass = this; + param->method = method; + if (dataSize > 0) { + param->dataSize = dataSize; + param->data = new uint8_t[param->dataSize](); + if (!param->data) { + delete param; + return; + } + if (memcpy_s((uint8_t *)param->data, param->dataSize, data, dataSize)) { + delete[]((uint8_t *)param->data); + delete param; + return; + } + } + + asyncMainLoop.data = this; + uv_rwlock_wrlock(&mainAsync); + lstMainThreadOP.push_back(param); + uv_rwlock_wrunlock(&mainAsync); + uv_async_send(&asyncMainLoop); +} + +void HdcSessionBase::WorkerPendding() +{ + uv_run(&loopMain, UV_RUN_DEFAULT); + ClearInstanceResource(); +} + +int HdcSessionBase::MallocSessionByConnectType(HSession hSession) +{ + int ret = 0; + switch (hSession->connType) { + case CONN_TCP: { + uv_tcp_init(&loopMain, &hSession->hWorkTCP); + ++hSession->uvRef; + hSession->hWorkTCP.data = hSession; + break; + } + case CONN_USB: { + // Some members need to be placed at the primary thread + HUSB hUSB = new HdcUSB(); + if (!hUSB) { + ret = -1; + break; + } + hSession->hUSB = hUSB; +#ifdef HDC_HOST + constexpr auto maxBufFactor = 1.5; + int max = Base::GetMaxBufSize() * maxBufFactor + sizeof(USBHead); + hUSB->sizeEpBuf = max; + hUSB->bufDevice = new uint8_t[max](); + hUSB->bufHost = new uint8_t[max](); + hUSB->transferRecv = libusb_alloc_transfer(0); + hUSB->transferSend = libusb_alloc_transfer(0); +#else +#endif + break; + } + default: + ret = -1; + break; + } + return ret; +} + +// Avoid unit test when client\server\daemon on the same host, maybe get the same ID value +uint32_t HdcSessionBase::GetSessionPseudoUid() +{ + uint32_t uid = 0; + Hdc::HSession hInput = nullptr; + do { + uid = static_cast(Base::GetRandom()); + } while ((hInput = AdminSession(OP_QUERY, uid, nullptr)) != nullptr); + return uid; +} + +// when client 0 to automatic generated,when daemon First place 1 followed by +HSession HdcSessionBase::MallocSession(bool serverOrDaemon, const ConnType connType, void *classModule, + uint32_t sessionId) +{ + HSession hSession = new HdcSession(); + if (!hSession) { + return nullptr; + } + int ret = 0; + ++sessionRef; + memset_s(hSession->ctrlFd, sizeof(hSession->ctrlFd), 0, sizeof(hSession->ctrlFd)); + hSession->classInstance = this; + hSession->connType = connType; + hSession->classModule = classModule; + hSession->isDead = false; + hSession->sessionId = ((sessionId == 0) ? GetSessionPseudoUid() : sessionId); + hSession->serverOrDaemon = serverOrDaemon; + hSession->hWorkThread = uv_thread_self(); + hSession->mapTask = new map(); + hSession->listKey = new list; + hSession->uvRef = 0; + // pullup child + WRITE_LOG(LOG_DEBUG, "HdcSessionBase NewSession, sessionId:%u", hSession->sessionId); + + uv_tcp_init(&loopMain, &hSession->ctrlPipe[STREAM_MAIN]); + ++hSession->uvRef; + Base::CreateSocketPair(hSession->ctrlFd); + uv_tcp_open(&hSession->ctrlPipe[STREAM_MAIN], hSession->ctrlFd[STREAM_MAIN]); + uv_read_start((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], Base::AllocBufferCallback, ReadCtrlFromSession); + hSession->ctrlPipe[STREAM_MAIN].data = hSession; + hSession->ctrlPipe[STREAM_WORK].data = hSession; + // Activate USB DAEMON's data channel, may not for use + uv_tcp_init(&loopMain, &hSession->dataPipe[STREAM_MAIN]); + ++hSession->uvRef; + Base::CreateSocketPair(hSession->dataFd); + uv_tcp_open(&hSession->dataPipe[STREAM_MAIN], hSession->dataFd[STREAM_MAIN]); + hSession->dataPipe[STREAM_MAIN].data = hSession; + hSession->dataPipe[STREAM_WORK].data = hSession; + Base::SetTcpOptions(&hSession->dataPipe[STREAM_MAIN]); + ret = MallocSessionByConnectType(hSession); + if (ret) { + delete hSession; + hSession = nullptr; + } else { + AdminSession(OP_ADD, hSession->sessionId, hSession); + } + return hSession; +} + +void HdcSessionBase::FreeSessionByConnectType(HSession hSession) +{ + if (CONN_USB == hSession->connType) { + // ibusb All context is applied for sub-threaded, so it needs to be destroyed in the subline + if (!hSession->hUSB) { + return; + } + HUSB hUSB = hSession->hUSB; + if (!hUSB) { + return; + } +#ifdef HDC_HOST + if (hUSB->devHandle) { + libusb_release_interface(hUSB->devHandle, hUSB->interfaceNumber); + libusb_close(hUSB->devHandle); + hUSB->devHandle = nullptr; + } + + delete[] hUSB->bufDevice; + delete[] hUSB->bufHost; + libusb_free_transfer(hUSB->transferRecv); + libusb_free_transfer(hUSB->transferSend); +#else + if (hUSB->bulkIn > 0) { + close(hUSB->bulkIn); + hUSB->bulkIn = 0; + } + if (hUSB->bulkOut > 0) { + close(hUSB->bulkOut); + hUSB->bulkOut = 0; + } +#endif + delete hSession->hUSB; + hSession->hUSB = nullptr; + } +} + +// work when libuv-handle at struct of HdcSession has all callback finished +void HdcSessionBase::FreeSessionFinally(uv_idle_t *handle) +{ + HSession hSession = (HSession)handle->data; + HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance; + if (hSession->uvRef > 0) { + return; + } + // Notify Server or Daemon, just UI or display commandline + thisClass->NotifyInstanceSessionFree(hSession, true); + // all hsession uv handle has been clear + thisClass->AdminSession(OP_REMOVE, hSession->sessionId, nullptr); + WRITE_LOG(LOG_DEBUG, "!!!FreeSessionFinally sessionId:%u finish", hSession->sessionId); + delete hSession; + hSession = nullptr; // fix CodeMars SetNullAfterFree issue + Base::TryCloseHandle((const uv_handle_t *)handle, Base::CloseIdleCallback); + --thisClass->sessionRef; +} + +// work when child-work thread finish +void HdcSessionBase::FreeSessionContinue(HSession hSession) +{ + auto closeSessionTCPHandle = [](uv_handle_t *handle) -> void { + HSession hSession = (HSession)handle->data; + --hSession->uvRef; + Base::TryCloseHandle((uv_handle_t *)handle); + }; + if (CONN_TCP == hSession->connType) { + // Turn off TCP to prevent continuing writing + Base::TryCloseHandle((uv_handle_t *)&hSession->hWorkTCP, true, closeSessionTCPHandle); + } + hSession->availTailIndex = 0; + if (hSession->ioBuf) { + delete[] hSession->ioBuf; + hSession->ioBuf = nullptr; + } + Base::TryCloseHandle((uv_handle_t *)&hSession->ctrlPipe[STREAM_MAIN], true, closeSessionTCPHandle); + Base::TryCloseHandle((uv_handle_t *)&hSession->dataPipe[STREAM_MAIN], true, closeSessionTCPHandle); + delete hSession->mapTask; + HdcAuth::FreeKey(!hSession->serverOrDaemon, hSession->listKey); + delete hSession->listKey; // to clear + FreeSessionByConnectType(hSession); + // finish + Base::IdleUvTask(&loopMain, hSession, FreeSessionFinally); +} + +void HdcSessionBase::FreeSessionOpeate(uv_timer_t *handle) +{ + HSession hSession = (HSession)handle->data; + HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance; + if (hSession->sendRef > 0) { + return; + } +#ifdef HDC_HOST + if (hSession->hUSB != nullptr && (!hSession->hUSB->recvIOComplete || !hSession->hUSB->sendIOComplete)) { + return; + } +#endif + // wait workthread to free + if (hSession->ctrlPipe[STREAM_WORK].loop) { + auto ctrl = BuildCtrlString(SP_STOP_SESSION, 0, nullptr, 0); + Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); + WRITE_LOG(LOG_DEBUG, "FreeSession, send workthread fo free. sessionId:%u", hSession->sessionId); + auto callbackCheckFreeSessionContinue = [](uv_timer_t *handle) -> void { + HSession hSession = (HSession)handle->data; + HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance; + if (!hSession->childCleared) { + return; + } + Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback); + thisClass->FreeSessionContinue(hSession); + }; + Base::TimerUvTask(&thisClass->loopMain, hSession, callbackCheckFreeSessionContinue); + } else { + thisClass->FreeSessionContinue(hSession); + } + Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback); +} + +void HdcSessionBase::FreeSession(const uint32_t sessionId) +{ + HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr); + if (!hSession) { + return; + } + if (hSession->hWorkThread != uv_thread_self()) { + PushAsyncMessage(hSession->sessionId, ASYNC_FREE_SESSION, nullptr, 0); + return; + } + if (hSession->isDead) { + return; + } + hSession->isDead = true; + Base::TimerUvTask(&loopMain, hSession, FreeSessionOpeate); + NotifyInstanceSessionFree(hSession, false); + WRITE_LOG(LOG_DEBUG, "FreeSession sessionId:%u sendref:%u", hSession->sessionId, uint16_t(hSession->sendRef)); +} + +HSession HdcSessionBase::AdminSession(const uint8_t op, const uint32_t sessionId, HSession hInput) +{ + HSession hRet = nullptr; + switch (op) { + case OP_ADD: + uv_rwlock_wrlock(&lockMapSession); + mapSession[sessionId] = hInput; + uv_rwlock_wrunlock(&lockMapSession); + break; + case OP_REMOVE: + uv_rwlock_wrlock(&lockMapSession); + mapSession.erase(sessionId); + uv_rwlock_wrunlock(&lockMapSession); + break; + case OP_QUERY: + uv_rwlock_rdlock(&lockMapSession); + if (mapSession.count(sessionId)) { + hRet = mapSession[sessionId]; + } + uv_rwlock_rdunlock(&lockMapSession); + break; + case OP_UPDATE: + uv_rwlock_wrlock(&lockMapSession); + // remove old + mapSession.erase(sessionId); + mapSession[hInput->sessionId] = hInput; + uv_rwlock_wrunlock(&lockMapSession); + break; + default: + break; + } + return hRet; +} + +// All in the corresponding sub-thread, no need locks +HTaskInfo HdcSessionBase::AdminTask(const uint8_t op, HSession hSession, const uint32_t channelId, HTaskInfo hInput) +{ + HTaskInfo hRet = nullptr; + map &mapTask = *hSession->mapTask; + switch (op) { + case OP_ADD: + mapTask[channelId] = hInput; + break; + case OP_REMOVE: + mapTask.erase(channelId); + break; + case OP_QUERY: + if (mapTask.count(channelId)) { + hRet = mapTask[channelId]; + } + break; + default: + break; + } + return hRet; +} + +int HdcSessionBase::SendByProtocol(HSession hSession, uint8_t *bufPtr, const int bufLen) +{ + if (hSession->isDead) { + return ERR_SESSION_NOFOUND; + } + int ret = 0; + ++hSession->sendRef; + switch (hSession->connType) { + case CONN_TCP: { + if (hSession->hWorkThread == uv_thread_self()) { + ret = Base::SendToStreamEx((uv_stream_t *)&hSession->hWorkTCP, bufPtr, bufLen, nullptr, + (void *)FinishWriteSessionTCP, bufPtr); + } else if (hSession->hWorkChildThread == uv_thread_self()) { + ret = Base::SendToStreamEx((uv_stream_t *)&hSession->hChildWorkTCP, bufPtr, bufLen, nullptr, + (void *)FinishWriteSessionTCP, bufPtr); + } else { + WRITE_LOG(LOG_FATAL, "SendByProtocol uncontrol send"); + ret = ERR_API_FAIL; + } + break; + } + case CONN_USB: { + HdcUSBBase *pUSB = ((HdcUSBBase *)hSession->classModule); + ret = pUSB->SendUSBBlock(hSession, bufPtr, bufLen); + delete[] bufPtr; + break; + } + default: + break; + } + return ret; +} + +int HdcSessionBase::Send(const uint32_t sessionId, const uint32_t channelId, const uint16_t commandFlag, + const uint8_t *data, const int dataSize) +{ + HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr); + if (!hSession) { + WRITE_LOG(LOG_DEBUG, "Send to offline device, drop it, sessionId:%u", sessionId); + return ERR_SESSION_NOFOUND; + } + PayloadProtect protectBuf; // noneed convert to big-endian + protectBuf.channelId = channelId; + protectBuf.commandFlag = commandFlag; + protectBuf.checkSum = (ENABLE_IO_CHECKSUM && dataSize > 0) ? Base::CalcCheckSum(data, dataSize) : 0; + protectBuf.vCode = payloadProtectStaticVcode; + string s = SerialStruct::SerializeToString(protectBuf); + // reserve for encrypt here + // xx-encrypt + + PayloadHead payloadHead; // need convert to big-endian + Base::ZeroStruct(payloadHead); + payloadHead.flag[0] = PACKET_FLAG.at(0); + payloadHead.flag[1] = PACKET_FLAG.at(1); + payloadHead.protocolVer = VER_PROTOCOL; + payloadHead.headSize = htons(s.size()); + payloadHead.dataSize = htonl(dataSize); + int finalBufSize = sizeof(PayloadHead) + s.size() + dataSize; + uint8_t *finayBuf = new uint8_t[finalBufSize](); + if (finayBuf == nullptr) { + return ERR_BUF_ALLOC; + } + bool bufRet = false; + do { + if (memcpy_s(finayBuf, sizeof(PayloadHead), reinterpret_cast(&payloadHead), sizeof(PayloadHead))) { + break; + } + if (memcpy_s(finayBuf + sizeof(PayloadHead), s.size(), + reinterpret_cast(const_cast(s.c_str())), s.size())) { + break; + } + if (dataSize > 0 && memcpy_s(finayBuf + sizeof(PayloadHead) + s.size(), dataSize, data, dataSize)) { + break; + } + bufRet = true; + } while (false); + if (!bufRet) { + delete[] finayBuf; + return ERR_BUF_COPY; + } + return SendByProtocol(hSession, finayBuf, finalBufSize); +} + +int HdcSessionBase::DecryptPayload(HSession hSession, PayloadHead *payloadHeadBe, uint8_t *encBuf) +{ + PayloadProtect protectBuf; + Base::ZeroStruct(protectBuf); + uint16_t headSize = ntohs(payloadHeadBe->headSize); + int dataSize = ntohl(payloadHeadBe->dataSize); + string encString(reinterpret_cast(encBuf), headSize); + SerialStruct::ParseFromString(protectBuf, encString); + if (protectBuf.vCode != payloadProtectStaticVcode) { + WRITE_LOG(LOG_FATAL, "Session recv static vcode failed"); + return ERR_BUF_CHECK; + } + uint8_t *data = encBuf + headSize; + if (protectBuf.checkSum != 0 && (protectBuf.checkSum != Base::CalcCheckSum(data, dataSize))) { + WRITE_LOG(LOG_FATAL, "Session recv CalcCheckSum failed"); + return ERR_BUF_CHECK; + } + if (!FetchCommand(hSession, protectBuf.channelId, protectBuf.commandFlag, data, dataSize)) { + WRITE_LOG(LOG_WARN, "FetchCommand failed"); + return ERR_GENERIC; + } + return RET_SUCCESS; +} + +int HdcSessionBase::OnRead(HSession hSession, uint8_t *bufPtr, const int bufLen) +{ + int ret = ERR_GENERIC; + if (memcmp(bufPtr, PACKET_FLAG.c_str(), PACKET_FLAG.size())) { + return ERR_BUF_CHECK; + } + struct PayloadHead *payloadHead = (struct PayloadHead *)bufPtr; + int tobeReadLen = ntohl(payloadHead->dataSize) + ntohs(payloadHead->headSize); + int packetHeadSize = sizeof(struct PayloadHead); + if (tobeReadLen <= 0 || (uint32_t)tobeReadLen > HDC_BUF_MAX_BYTES) { + // max 1G + return ERR_BUF_CHECK; + } + if (bufLen - packetHeadSize < tobeReadLen) { + return 0; + } + if (DecryptPayload(hSession, payloadHead, bufPtr + packetHeadSize)) { + return ERR_BUF_CHECK; + } + ret = packetHeadSize + tobeReadLen; + return ret; +} + +// Returns <0 error;> 0 receives the number of bytes; 0 untreated +int HdcSessionBase::FetchIOBuf(HSession hSession, uint8_t *ioBuf, int read) +{ + HdcSessionBase *ptrConnect = (HdcSessionBase *)hSession->classInstance; + int indexBuf = 0; + int childRet = 0; + if (read < 0) { + return ERR_IO_FAIL; + } + hSession->availTailIndex += read; + while (!hSession->isDead && hSession->availTailIndex > static_cast(sizeof(PayloadHead))) { + childRet = ptrConnect->OnRead(hSession, ioBuf + indexBuf, hSession->availTailIndex); + if (childRet > 0) { + hSession->availTailIndex -= childRet; + indexBuf += childRet; + } else if (childRet == 0) { + // Not enough a IO + break; + } else { + // <0 + hSession->availTailIndex = 0; // Preventing malicious data packages + indexBuf = ERR_BUF_SIZE; + break; + } + // It may be multi-time IO to merge in a BUF, need to loop processing + } + if (indexBuf > 0 && hSession->availTailIndex > 0) { + memmove_s(hSession->ioBuf, hSession->bufSize, hSession->ioBuf + indexBuf, hSession->availTailIndex); + uint8_t *bufToZero = (uint8_t *)(hSession->ioBuf + hSession->availTailIndex); + Base::ZeroBuf(bufToZero, hSession->bufSize - hSession->availTailIndex); + } + return indexBuf; +} + +void HdcSessionBase::AllocCallback(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) +{ + HSession context = (HSession)handle->data; + Base::ReallocBuf(&context->ioBuf, &context->bufSize, context->availTailIndex, sizeWanted); + buf->base = (char *)context->ioBuf + context->availTailIndex; + buf->len = context->bufSize - context->availTailIndex - 1; // 16Bytes are retained to prevent memory sticking + assert(buf->len >= 0); +} + +void HdcSessionBase::FinishWriteSessionTCP(uv_write_t *req, int status) +{ + HSession hSession = (HSession)req->handle->data; + --hSession->sendRef; + HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance; + if (status < 0) { + Base::TryCloseHandle((uv_handle_t *)req->handle); + if (!hSession->isDead && !hSession->sendRef) { + WRITE_LOG(LOG_DEBUG, "FinishWriteSessionTCP freesession :%p", hSession); + thisClass->FreeSession(hSession->sessionId); + } + } + delete[]((uint8_t *)req->data); + delete req; +} + +bool HdcSessionBase::DispatchSessionThreadCommand(uv_stream_t *uvpipe, HSession hSession, const uint8_t *baseBuf, + const int bytesIO) +{ + bool ret = true; + uint8_t flag = *(uint8_t *)baseBuf; + + switch (flag) { + case SP_JDWP_NEWFD: { + JdwpNewFileDescriptor(baseBuf, bytesIO); + break; + } + default: + WRITE_LOG(LOG_WARN, "Not support session command"); + break; + } + return ret; +} + +void HdcSessionBase::ReadCtrlFromSession(uv_stream_t *uvpipe, ssize_t nread, const uv_buf_t *buf) +{ + HSession hSession = (HSession)uvpipe->data; + HdcSessionBase *hSessionBase = (HdcSessionBase *)hSession->classInstance; + while (true) { + if (nread < 0) { + WRITE_LOG(LOG_DEBUG, "SessionCtrl failed,%s", uv_strerror(nread)); + break; + } + if (nread > 64) { // 64 : max length + WRITE_LOG(LOG_WARN, "HdcSessionBase read overlap data"); + break; + } + // only one command, no need to split command from stream + // if add more commands, consider the format command + hSessionBase->DispatchSessionThreadCommand(uvpipe, hSession, (uint8_t *)buf->base, nread); + break; + } + delete[] buf->base; +} + +bool HdcSessionBase::WorkThreadStartSession(HSession hSession) +{ + bool regOK = false; + int childRet = 0; + if (hSession->connType == CONN_TCP) { + HdcTCPBase *pTCPBase = (HdcTCPBase *)hSession->classModule; + hSession->hChildWorkTCP.data = hSession; + if ((childRet = uv_tcp_init(&hSession->childLoop, &hSession->hChildWorkTCP)) < 0) { + WRITE_LOG(LOG_DEBUG, "HdcSessionBase SessionCtrl failed 1"); + return false; + } + if ((childRet = uv_tcp_open(&hSession->hChildWorkTCP, hSession->fdChildWorkTCP)) < 0) { + WRITE_LOG(LOG_DEBUG, "SessionCtrl failed 2,fd:%d,str:%s", hSession->fdChildWorkTCP, uv_strerror(childRet)); + return false; + } + Base::SetTcpOptions((uv_tcp_t *)&hSession->hChildWorkTCP); + uv_read_start((uv_stream_t *)&hSession->hChildWorkTCP, AllocCallback, pTCPBase->ReadStream); + regOK = true; + } else { // USB + HdcUSBBase *pUSBBase = (HdcUSBBase *)hSession->classModule; + WRITE_LOG(LOG_DEBUG, "USB ReadyForWorkThread"); + regOK = pUSBBase->ReadyForWorkThread(hSession); + } + if (regOK && hSession->serverOrDaemon) { + // session handshake step1 + SessionHandShake handshake; + Base::ZeroStruct(handshake); + handshake.banner = HANDSHAKE_MESSAGE; + handshake.sessionId = hSession->sessionId; + handshake.connectKey = hSession->connectKey; + handshake.authType = AUTH_NONE; + string hs = SerialStruct::SerializeToString(handshake); + Send(hSession->sessionId, 0, CMD_KERNEL_HANDSHAKE, (uint8_t *)hs.c_str(), hs.size()); + } + return regOK; +} + +vector HdcSessionBase::BuildCtrlString(InnerCtrlCommand command, uint32_t channelId, uint8_t *data, + int dataSize) +{ + vector ret; + while (true) { + if (dataSize > BUF_SIZE_MICRO) { + break; + } + CtrlStruct ctrl; + Base::ZeroStruct(ctrl); + ctrl.command = command; + ctrl.channelId = channelId; + ctrl.dataSize = dataSize; + if (dataSize > 0 && data != nullptr && memcpy_s(ctrl.data, sizeof(ctrl.data), data, dataSize) != EOK) { + break; + } + uint8_t *buf = reinterpret_cast(&ctrl); + ret.insert(ret.end(), buf, buf + sizeof(CtrlStruct)); + break; + } + return ret; +} + +bool HdcSessionBase::DispatchMainThreadCommand(HSession hSession, const CtrlStruct *ctrl) +{ + bool ret = true; + uint32_t channelId = ctrl->channelId; // if send not set, it is zero + switch (ctrl->command) { + case SP_START_SESSION: { + WRITE_LOG(LOG_DEBUG, "Dispatch MainThreadCommand START_SESSION sessionId:%u instance:%s", + hSession->sessionId, hSession->serverOrDaemon ? "server" : "daemon"); + ret = WorkThreadStartSession(hSession); + break; + } + case SP_STOP_SESSION: { + WRITE_LOG(LOG_DEBUG, "Dispatch MainThreadCommand STOP_SESSION sessionId:%u", hSession->sessionId); + auto closeSessionChildThreadTCPHandle = [](uv_handle_t *handle) -> void { + HSession hSession = (HSession)handle->data; + Base::TryCloseHandle((uv_handle_t *)handle); + if (--hSession->uvChildRef == 0) { + uv_stop(&hSession->childLoop); + }; + }; + hSession->uvChildRef += 2; + if (hSession->hChildWorkTCP.loop) { // maybe not use it + ++hSession->uvChildRef; + Base::TryCloseHandle((uv_handle_t *)&hSession->hChildWorkTCP, true, closeSessionChildThreadTCPHandle); + } + Base::TryCloseHandle((uv_handle_t *)&hSession->ctrlPipe[STREAM_WORK], true, + closeSessionChildThreadTCPHandle); + Base::TryCloseHandle((uv_handle_t *)&hSession->dataPipe[STREAM_WORK], true, + closeSessionChildThreadTCPHandle); + break; + } + case SP_ATTACH_CHANNEL: { + if (!serverOrDaemon) { + break; // Only Server has this feature + } + AttachChannel(hSession, channelId); + break; + } + case SP_DEATCH_CHANNEL: { + if (!serverOrDaemon) { + break; // Only Server has this feature + } + DeatchChannel(hSession, channelId); + break; + } + default: + WRITE_LOG(LOG_WARN, "Not support main command"); + ret = false; + break; + } + return ret; +} + +// Several bytes of control instructions, generally do not stick +void HdcSessionBase::ReadCtrlFromMain(uv_stream_t *uvpipe, ssize_t nread, const uv_buf_t *buf) +{ + HSession hSession = (HSession)uvpipe->data; + HdcSessionBase *hSessionBase = (HdcSessionBase *)hSession->classInstance; + int formatCommandSize = sizeof(CtrlStruct); + int index = 0; + bool ret = true; + while (true) { + if (nread < 0) { + WRITE_LOG(LOG_DEBUG, "SessionCtrl failed,%s", uv_strerror(nread)); + ret = false; + break; + } + if (nread % formatCommandSize != 0) { + WRITE_LOG(LOG_FATAL, "ReadCtrlFromMain size failed, nread == %d", nread); + ret = false; + break; + } + CtrlStruct *ctrl = reinterpret_cast(buf->base + index); + if (!(ret = hSessionBase->DispatchMainThreadCommand(hSession, ctrl))) { + ret = false; + break; + } + index += sizeof(CtrlStruct); + if (index >= nread) { + break; + } + } + delete[] buf->base; +} + +void HdcSessionBase::ReChildLoopForSessionClear(HSession hSession) +{ + // Restart loop close task + ClearOwnTasks(hSession, 0); + auto clearTaskForSessionFinish = [](uv_idle_t *handle) -> void { + HSession hSession = (HSession)handle->data; + for (auto v : *hSession->mapTask) { + HTaskInfo hTask = (HTaskInfo)v.second; + if (!hTask->taskFree) + return; + } + // all task has been free + uv_close((uv_handle_t *)handle, Base::CloseIdleCallback); + uv_stop(&hSession->childLoop); // stop ReChildLoopForSessionClear pendding + }; + Base::IdleUvTask(&hSession->childLoop, hSession, clearTaskForSessionFinish); + uv_run(&hSession->childLoop, UV_RUN_DEFAULT); + // clear + Base::TryCloseLoop(&hSession->childLoop, "Session childUV"); +} + +void HdcSessionBase::SessionWorkThread(uv_work_t *arg) +{ + int childRet = 0; + HSession hSession = (HSession)arg->data; + HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance; + uv_loop_init(&hSession->childLoop); + hSession->hWorkChildThread = uv_thread_self(); + if ((childRet = uv_tcp_init(&hSession->childLoop, &hSession->ctrlPipe[STREAM_WORK])) < 0) { + WRITE_LOG(LOG_DEBUG, "SessionCtrl err1, %s", uv_strerror(childRet)); + } + if ((childRet = uv_tcp_open(&hSession->ctrlPipe[STREAM_WORK], hSession->ctrlFd[STREAM_WORK])) < 0) { + WRITE_LOG(LOG_DEBUG, "SessionCtrl err2, %s fd:%d", uv_strerror(childRet), hSession->ctrlFd[STREAM_WORK]); + } + uv_read_start((uv_stream_t *)&hSession->ctrlPipe[STREAM_WORK], Base::AllocBufferCallback, ReadCtrlFromMain); + WRITE_LOG(LOG_DEBUG, "!!!Workthread run begin, sessionId:%u instance:%s", hSession->sessionId, + thisClass->serverOrDaemon ? "server" : "daemon"); + uv_run(&hSession->childLoop, UV_RUN_DEFAULT); // work pendding + WRITE_LOG(LOG_DEBUG, "!!!Workthread run again, sessionId:%u", hSession->sessionId); + // main loop has exit + thisClass->ReChildLoopForSessionClear(hSession); // work pending again + hSession->childCleared = true; + WRITE_LOG(LOG_DEBUG, "!!!Workthread run finish, sessionId:%u workthread:%p", hSession->sessionId, uv_thread_self()); +} + +// clang-format off +void HdcSessionBase::LogMsg(const uint32_t sessionId, const uint32_t channelId, + MessageLevel level, const char *msg, ...) +// clang-format on +{ + va_list vaArgs; + va_start(vaArgs, msg); + string log = Base::StringFormat(msg, vaArgs); + va_end(vaArgs); + vector buf; + buf.push_back(level); + buf.insert(buf.end(), log.c_str(), log.c_str() + log.size()); + ServerCommand(sessionId, channelId, CMD_KERNEL_ECHO, buf.data(), buf.size()); +} + +// Heavy and time-consuming work was putted in the new thread to do, and does +// not occupy the main thread +bool HdcSessionBase::DispatchTaskData(HSession hSession, const uint32_t channelId, const uint16_t command, + uint8_t *payload, int payloadSize) +{ + bool ret = false; + while (true) { + HTaskInfo hTaskInfo = AdminTask(OP_QUERY, hSession, channelId, nullptr); + if (!hTaskInfo) { + WRITE_LOG(LOG_DEBUG, "New HTaskInfo"); + hTaskInfo = new TaskInformation(); + hTaskInfo->channelId = channelId; + hTaskInfo->sessionId = hSession->sessionId; + hTaskInfo->runLoop = &hSession->childLoop; + hTaskInfo->serverOrDaemon = serverOrDaemon; + } + if (hTaskInfo->taskStop) { + WRITE_LOG(LOG_DEBUG, "RedirectToTask jump stopped task:%d", channelId); + break; + } + if (hTaskInfo->taskFree) { + WRITE_LOG(LOG_DEBUG, "Jump delete HTaskInfo"); + break; + } + bool result = RedirectToTask(hTaskInfo, hSession, channelId, command, payload, payloadSize); + if (!hTaskInfo->hasInitial) { + AdminTask(OP_ADD, hSession, channelId, hTaskInfo); + hTaskInfo->hasInitial = true; + } + if (result) { + ret = true; + } + break; + } + return ret; +} + +void HdcSessionBase::PostStopInstanceMessage(bool restart) +{ + PushAsyncMessage(0, ASYNC_STOP_MAINLOOP, nullptr, 0); + WRITE_LOG(LOG_DEBUG, "StopDaemon has sended"); + wantRestart = restart; +} +} // namespace Hdc diff --git a/services/flashd/common/session.h b/services/flashd/common/session.h new file mode 100755 index 00000000..fe580717 --- /dev/null +++ b/services/flashd/common/session.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_SESSION_H +#define HDC_SESSION_H +#include "common.h" + +namespace Hdc { +enum TaskType { TYPE_UNITY, TYPE_SHELL, TASK_FILE, TASK_FORWARD, TASK_APP, TASK_UPDATER }; + +class HdcSessionBase { +public: + enum AuthType { AUTH_NONE, AUTH_TOKEN, AUTH_SIGNATURE, AUTH_PUBLICKEY, AUTH_OK }; + struct SessionHandShake { + string banner; // must first index + // auth none + uint8_t authType; + uint32_t sessionId; + string connectKey; + string buf; + }; + struct CtrlStruct { + InnerCtrlCommand command; + uint32_t channelId; + uint8_t dataSize; + uint8_t data[BUF_SIZE_MICRO]; + }; + struct PayloadProtect { // reserve for encrypt and decrypt + uint32_t channelId; + uint32_t commandFlag; + uint8_t checkSum; // enable it will be lose about 20% speed + uint8_t vCode; + }; + + HdcSessionBase(bool serverOrDaemonIn); + virtual ~HdcSessionBase(); + virtual void AttachChannel(HSession hSession, const uint32_t channelId) {}; + virtual void DeatchChannel(HSession hSession, const uint32_t channelId) {}; + virtual bool RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, + const uint16_t command, uint8_t *payload, const int payloadSize) + { + return true; + } + virtual void NotifyInstanceSessionFree(HSession hSession, bool freeOrClear) + { + } + // Thread security interface for global stop programs + void PostStopInstanceMessage(bool restart = false); + void ReMainLoopForInstanceClear(); + // server, Two parameters in front of call can be empty + void LogMsg(const uint32_t sessionId, const uint32_t channelId, MessageLevel level, const char *msg, ...); + static void AllocCallback(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf); + static void MainAsyncCallback(uv_async_t *handle); + static void FinishWriteSessionTCP(uv_write_t *req, int status); + static void SessionWorkThread(uv_work_t *arg); + static void ReadCtrlFromMain(uv_stream_t *uvpipe, ssize_t nread, const uv_buf_t *buf); + static void ReadCtrlFromSession(uv_stream_t *uvpipe, ssize_t nread, const uv_buf_t *buf); + HSession QueryUSBDeviceRegister(void *pDev, int busIDIn, int devIDIn); + HSession MallocSession(bool serverOrDaemon, const ConnType connType, void *classModule, uint32_t sessionId = 0); + void FreeSession(const uint32_t sessionId); + void WorkerPendding(); + int OnRead(HSession hSession, uint8_t *bufPtr, const int bufLen); + int Send(const uint32_t sessionId, const uint32_t channelId, const uint16_t commandFlag, const uint8_t *data, + const int dataSize); + int SendByProtocol(HSession hSession, uint8_t *bufPtr, const int bufLen); + HSession AdminSession(const uint8_t op, const uint32_t sessionId, HSession hInput); + int FetchIOBuf(HSession hSession, uint8_t *ioBuf, int read); + void PushAsyncMessage(const uint32_t sessionId, const uint8_t method, const void *data, const int dataSize); + HTaskInfo AdminTask(const uint8_t op, HSession hSession, const uint32_t channelId, HTaskInfo hInput); + bool DispatchTaskData(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, + int payloadSize); + void EnumUSBDeviceRegister(void (*pCallBack)(HSession hSession)); + void ClearOwnTasks(HSession hSession, const uint32_t channelIDInput); + virtual bool FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, + int payloadSize) + { + return true; + } + virtual bool ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, + uint8_t *bufPtr, const int size) + { + return true; + } + virtual bool RemoveInstanceTask(const uint8_t op, HTaskInfo hTask) + { + return true; + } + bool WantRestart() + { + return wantRestart; + } + static vector BuildCtrlString(InnerCtrlCommand command, uint32_t channelId, uint8_t *data, int dataSize); + uv_loop_t loopMain; + bool serverOrDaemon; + uv_async_t asyncMainLoop; + uv_rwlock_t mainAsync; + list lstMainThreadOP; + void *ctxUSB; + +protected: + struct PayloadHead { + uint8_t flag[2]; + uint8_t reserve[2]; // encrypt'flag or others options + uint8_t protocolVer; + uint16_t headSize; + uint32_t dataSize; + } __attribute__((packed)); + void ClearSessions(); + virtual void JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO) + { + } + // must be define in haderfile, cannot in cpp file + template + bool TaskCommandDispatch(HTaskInfo hTaskInfo, uint8_t taskType, const uint16_t command, uint8_t *payload, + const int payloadSize) + { + bool ret = true; + T *ptrTask = nullptr; + if (!hTaskInfo->hasInitial) { + ptrTask = new T(hTaskInfo); + hTaskInfo->taskClass = ptrTask; + hTaskInfo->taskType = taskType; + } else { + ptrTask = (T *)hTaskInfo->taskClass; + } + if (!ptrTask->CommandDispatch(command, payload, payloadSize)) { + ptrTask->TaskFinish(); + } + return ret; + } + template bool DoTaskRemove(HTaskInfo hTaskInfo, const uint8_t op) + { + T *ptrTask = (T *)hTaskInfo->taskClass; + if (OP_CLEAR == op) { + ptrTask->StopTask(); + } else if (OP_REMOVE == op) { + if (!ptrTask->ReadyForRelease()) { + return false; + } + delete ptrTask; + } + return true; + } + bool wantRestart; + +private: + virtual void ClearInstanceResource() + { + } + int DecryptPayload(HSession hSession, PayloadHead *payloadHeadBe, uint8_t *encBuf); + bool DispatchMainThreadCommand(HSession hSession, const CtrlStruct *ctrl); + bool DispatchSessionThreadCommand(uv_stream_t *uvpipe, HSession hSession, const uint8_t *baseBuf, + const int bytesIO); + bool BeginRemoveTask(HTaskInfo hTask); + bool TryRemoveTask(HTaskInfo hTask); + void ReChildLoopForSessionClear(HSession hSession); + void FreeSessionContinue(HSession hSession); + static void FreeSessionFinally(uv_idle_t *handle); + static void AsyncMainLoopTask(uv_idle_t *handle); + static void FreeSessionOpeate(uv_timer_t *handle); + int MallocSessionByConnectType(HSession hSession); + void FreeSessionByConnectType(HSession hSession); + bool WorkThreadStartSession(HSession hSession); + uint32_t GetSessionPseudoUid(); + + map mapSession; + uv_rwlock_t lockMapSession; + std::atomic sessionRef = 0; + const uint8_t payloadProtectStaticVcode = 0x09; +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/common/task.cpp b/services/flashd/common/task.cpp new file mode 100755 index 00000000..11461858 --- /dev/null +++ b/services/flashd/common/task.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "task.h" + +namespace Hdc { +// ----------------------------------------------------------- +// notice!!! The constructor is called at the Child thread, so in addition to initialization, do not excess actions, if +// destructor is required, please clean up in the subclasses. +HdcTaskBase::HdcTaskBase(HTaskInfo hTaskInfo) +{ + taskInfo = hTaskInfo; + loopTask = hTaskInfo->runLoop; + clsSession = hTaskInfo->ownerSessionClass; + childReady = false; + singalStop = false; + refCount = 0; +} + +HdcTaskBase::~HdcTaskBase() +{ + WRITE_LOG(LOG_DEBUG, "~HdcTaskBase"); +} + +bool HdcTaskBase::ReadyForRelease() +{ + return refCount == 0; +} + +// Only the Task work thread call is allowed to use only when Workfortask returns FALSE. +void HdcTaskBase::TaskFinish() +{ + uint8_t count = 1; + SendToAnother(CMD_KERNEL_CHANNEL_CLOSE, &count, 1); + WRITE_LOG(LOG_DEBUG, "HdcTaskBase::TaskFinish notify"); +} + +bool HdcTaskBase::SendToAnother(const uint16_t command, uint8_t *bufPtr, const int size) +{ + if (singalStop) { + return false; + } + HdcSessionBase *sessionBase = reinterpret_cast(taskInfo->ownerSessionClass); + return sessionBase->Send(taskInfo->sessionId, taskInfo->channelId, command, bufPtr, size) > 0; +} + +void HdcTaskBase::LogMsg(MessageLevel level, const char *msg, ...) +{ + va_list vaArgs; + va_start(vaArgs, msg); + string log = Base::StringFormat(msg, vaArgs); + va_end(vaArgs); + HdcSessionBase *sessionBase = reinterpret_cast(clsSession); + sessionBase->LogMsg(taskInfo->sessionId, taskInfo->channelId, level, log.c_str()); +} + +void HdcTaskBase::SendRawData(uint8_t *bufPtr, const int size) +{ + HdcSessionBase *sessionBase = (HdcSessionBase *)clsSession; + sessionBase->ServerCommand(taskInfo->sessionId, + taskInfo->channelId, CMD_KERNEL_ECHO_RAW, bufPtr, size); +} + +bool HdcTaskBase::ServerCommand(const uint16_t command, uint8_t *bufPtr, const int size) +{ + HdcSessionBase *hSession = (HdcSessionBase *)taskInfo->ownerSessionClass; + return hSession->ServerCommand(taskInfo->sessionId, taskInfo->channelId, command, bufPtr, size); +} + +// cross thread +int HdcTaskBase::ThreadCtrlCommunicate(const uint8_t *bufPtr, const int size) +{ + HdcSessionBase *sessionBase = (HdcSessionBase *)taskInfo->ownerSessionClass; + HSession hSession = sessionBase->AdminSession(OP_QUERY, taskInfo->sessionId, nullptr); + if (!hSession) { + return -1; + } + uv_stream_t *handleStream = nullptr; + if (uv_thread_self() == hSession->hWorkThread) { + handleStream = (uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN]; + } else if (uv_thread_self() == hSession->hWorkChildThread) { + handleStream = (uv_stream_t *)&hSession->ctrlPipe[STREAM_WORK]; + } else { + return ERR_GENERIC; + } + return Base::SendToStream(handleStream, bufPtr, size); +} +} \ No newline at end of file diff --git a/services/flashd/common/task.h b/services/flashd/common/task.h new file mode 100755 index 00000000..0d0d5a67 --- /dev/null +++ b/services/flashd/common/task.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_TASK_H +#define HDC_TASK_H +#include "common.h" + +namespace Hdc { +// Only allow inheritance +class HdcTaskBase { +public: + HdcTaskBase(HTaskInfo hTaskInfo); + virtual ~HdcTaskBase(); + virtual bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) + { + return true; + } + // The following two functions are used to clean up. To ensure that subclasses are safely cleaned, each subclass is + // directly instantified of these two virtual functions. + virtual void StopTask() + { + singalStop = true; // default opeartion + } + bool ReadyForRelease(); + void TaskFinish(); + void SendRawData(uint8_t *bufPtr, const int size); +protected: // D/S==daemon/server + bool SendToAnother(const uint16_t command, uint8_t *bufPtr, const int size); // D / S corresponds to the Task class + void LogMsg(MessageLevel level, const char *msg, ...); // D / S log Send to Client + bool ServerCommand(const uint16_t command, uint8_t *bufPtr, const int size); // D / s command is sent to Server + int ThreadCtrlCommunicate(const uint8_t *bufPtr, const int size); // main thread and session thread + + uv_loop_t *loopTask; // childuv pointer + void *clsSession; + // Task has stopped running. When Task is officially running, set True as soon as possible, set FALSE after the last + // step, when the value is false, the Task class will be destructured as soon as possible + bool childReady; // Subcompulents have been prepared + bool singalStop; // Request stop signal + HTaskInfo taskInfo; + uint32_t refCount; + +private: +}; +} // namespace Hdc + +#endif \ No newline at end of file diff --git a/services/flashd/common/tcp.cpp b/services/flashd/common/tcp.cpp new file mode 100755 index 00000000..18f267c7 --- /dev/null +++ b/services/flashd/common/tcp.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "tcp.h" + +namespace Hdc { +HdcTCPBase::HdcTCPBase(const bool serverOrDaemonIn, void *ptrMainBase) +{ + // Calling the initialization + InitialChildClass(serverOrDaemonIn, ptrMainBase); +} + +HdcTCPBase::~HdcTCPBase() +{ +} + +// Subclasses must be explicitly called +void HdcTCPBase::InitialChildClass(const bool serverOrDaemonIn, void *ptrMainBase) +{ + serverOrDaemon = serverOrDaemonIn; + clsMainBase = ptrMainBase; +} + +void HdcTCPBase::RecvUDP(uv_udp_t *handle, ssize_t nread, const uv_buf_t *rcvbuf, const struct sockaddr *addr, + unsigned flags) +{ + while (true) { + HdcTCPBase *thisClass = (HdcTCPBase *)handle->data; + if (nread <= 0) { + // ==0 finish;<0 error + break; + } + WRITE_LOG(LOG_DEBUG, "RecvUDP %s", rcvbuf->base); + if (strncmp(rcvbuf->base, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) { + break; + } + thisClass->RecvUDPEntry(addr, handle, rcvbuf); + break; + } + delete[] rcvbuf->base; +} + +void HdcTCPBase::AllocStreamUDP(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) +{ + int bufLen = BUF_SIZE_DEFAULT; + char *pRecvBuf = (char *)new uint8_t[bufLen](); + if (!pRecvBuf) { + return; + } + buf->base = pRecvBuf; + buf->len = bufLen; +} + +void HdcTCPBase::SendUDPFinish(uv_udp_send_t *req, int status) +{ + delete req; +} + +void HdcTCPBase::ReadStream(uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) +{ + HSession hSession = (HSession)tcp->data; + HdcTCPBase *thisClass = (HdcTCPBase *)hSession->classModule; + HdcSessionBase *hSessionBase = (HdcSessionBase *)thisClass->clsMainBase; + bool ret = false; + while (true) { + if (nread == UV_ENOBUFS) { + WRITE_LOG(LOG_DEBUG, "Session IOBuf max"); + break; + } else if (nread < 0) { + // I originally in the IO main thread, no need to send asynchronous messages, close the socket as soon as + // possible + WRITE_LOG(LOG_DEBUG, "HdcTCPBase::ReadStream < 0 %s", uv_strerror(nread)); + break; + } + if (hSessionBase->FetchIOBuf(hSession, hSession->ioBuf, nread) < 0) { + break; + } + ret = true; + break; + } + if (!ret) { + // The first time is closed first, prevent the write function from continuing to write + Base::TryCloseHandle(reinterpret_cast(tcp)); + hSessionBase->FreeSession(hSession->sessionId); + } +} +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/common/tcp.h b/services/flashd/common/tcp.h new file mode 100755 index 00000000..e7f32a27 --- /dev/null +++ b/services/flashd/common/tcp.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_TCP_H +#define HDC_TCP_H +#include "common.h" + +namespace Hdc { +class HdcTCPBase { +public: + HdcTCPBase(const bool serverOrDaemonIn, void *ptrMainBase); + virtual ~HdcTCPBase(); + static void ReadStream(uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf); + +protected: + virtual void RecvUDPEntry(const sockaddr *addrSrc, uv_udp_t *handle, const uv_buf_t *rcvbuf) + { + } + static void RecvUDP( + uv_udp_t *handle, ssize_t nread, const uv_buf_t *rcvbuf, const struct sockaddr *addr, unsigned flags); + static void SendUDPFinish(uv_udp_send_t *req, int status); + static void AllocStreamUDP(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf); + + void *clsMainBase; + bool serverOrDaemon; + +private: + void InitialChildClass(const bool serverOrDaemonIn, void *ptrMainBase); +}; +} // namespace Hdc + +#endif \ No newline at end of file diff --git a/services/flashd/common/transfer.cpp b/services/flashd/common/transfer.cpp new file mode 100755 index 00000000..fc983cfd --- /dev/null +++ b/services/flashd/common/transfer.cpp @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "transfer.h" +#include "serial_struct.h" +#include +#ifdef HARMONY_PROJECT +#include +#endif + +namespace Hdc { +constexpr uint64_t HDC_TIME_CONVERT_BASE = 1000000000; + +HdcTransferBase::HdcTransferBase(HTaskInfo hTaskInfo) + : HdcTaskBase(hTaskInfo) +{ + ResetCtx(&ctxNow, true); + commandBegin = 0; + commandData = 0; +} + +HdcTransferBase::~HdcTransferBase() +{ + WRITE_LOG(LOG_DEBUG, "~HdcTransferBase"); +}; + +bool HdcTransferBase::ResetCtx(CtxFile *context, bool full) +{ + context->fsOpenReq.data = context; + context->fsCloseReq.data = context; + context->thisClass = this; + context->closeNotify = false; + context->indexIO = 0; + context->loop = loopTask; + context->cb = OnFileIO; + if (full) { + context->localPath = ""; + context->remotePath = ""; + context->transferBegin = 0; + context->taskQueue.clear(); + Base::ZeroStruct(ctxNow.transferConfig); + } + return true; +} + +int HdcTransferBase::SimpleFileIO(CtxFile *context, uint64_t index, uint8_t *sendBuf, int bytes) +{ + // The first 8 bytes file offset + uint8_t *buf = new uint8_t[bytes](); + CtxFileIO *ioContext = new CtxFileIO(); + bool ret = false; + while (true) { + if (!buf || !ioContext || bytes < 0) { + break; + } + uv_fs_t *req = &ioContext->fs; + ioContext->bufIO = buf; + ioContext->context = context; + req->data = ioContext; + ++refCount; + if (context->master) { // master just read, and slave just write.when master/read, sendBuf can be nullptr + uv_buf_t iov = uv_buf_init(reinterpret_cast(buf), bytes); + uv_fs_read(context->loop, req, context->fsOpenReq.result, &iov, 1, index, context->cb); + } else { + // The US_FS_WRITE here must be brought into the actual file offset, which cannot be incorporated with local + // accumulated index because UV_FS_WRITE will be executed multiple times and then trigger a callback. + if (bytes > 0 && memcpy_s(ioContext->bufIO, bytes, sendBuf, bytes) != EOK) { + break; + } + uv_buf_t iov = uv_buf_init(reinterpret_cast(ioContext->bufIO), bytes); + uv_fs_write(context->loop, req, context->fsOpenReq.result, &iov, 1, index, context->cb); + } + ret = true; + break; + } + if (!ret) { + WRITE_LOG(LOG_WARN, "SimpleFileIO error"); + if (buf != nullptr) { + delete[] buf; + buf = nullptr; + } + if (ioContext != nullptr) { + delete ioContext; + ioContext = nullptr; + } + return -1; + } + return bytes; +} + +void HdcTransferBase::OnFileClose(uv_fs_t *req) +{ + uv_fs_req_cleanup(req); + CtxFile *context = (CtxFile *)req->data; + HdcTransferBase *thisClass = (HdcTransferBase *)context->thisClass; + if (context->closeNotify) { + // close-step2 + thisClass->WhenTransferFinish(context); + } + --thisClass->refCount; + return; +} + +void HdcTransferBase::SetFileTime(CtxFile *context) +{ + if (!context->transferConfig.holdTimestamp) { + return; + } + if (!context->transferConfig.mtime) { + return; + } + uv_fs_t fs; + double aTimeSec = static_cast(context->transferConfig.atime) / HDC_TIME_CONVERT_BASE; + double mTimeSec = static_cast(context->transferConfig.mtime) / HDC_TIME_CONVERT_BASE; + uv_fs_futime(nullptr, &fs, context->fsOpenReq.result, aTimeSec, mTimeSec, nullptr); + uv_fs_req_cleanup(&fs); +} + +bool HdcTransferBase::SendIOPayload(CtxFile *context, int index, uint8_t *data, int dataSize) +{ + TransferPayload payloadHead; + string head; + int compressSize = 0; + int sendBufSize = payloadPrefixReserve + dataSize; + uint8_t *sendBuf = new uint8_t[sendBufSize](); + if (!sendBuf) { + return false; + } + payloadHead.compressType = context->transferConfig.compressType; + payloadHead.uncompressSize = dataSize; + payloadHead.index = index; + if (dataSize > 0) { + switch (payloadHead.compressType) { +#ifdef HARMONY_PROJECT + case COMPRESS_LZ4: { + compressSize = LZ4_compress_default((const char *)data, (char *)sendBuf + payloadPrefixReserve, + dataSize, dataSize); + break; + } +#endif + default: { // COMPRESS_NONE + if (memcpy_s(sendBuf + payloadPrefixReserve, sendBufSize - payloadPrefixReserve, data, dataSize) + != EOK) { + delete[] sendBuf; + return false; + } + compressSize = dataSize; + break; + } + } + } + payloadHead.compressSize = compressSize; + head = SerialStruct::SerializeToString(payloadHead); + if (head.size() + 1 > payloadPrefixReserve) { + delete[] sendBuf; + return false; + } + int errCode = memcpy_s(sendBuf, sendBufSize, head.c_str(), head.size() + 1); + if (errCode != EOK) { + delete[] sendBuf; + return false; + } + bool ret = SendToAnother(commandData, sendBuf, payloadPrefixReserve + compressSize) > 0; + delete[] sendBuf; + return ret; +} + +void HdcTransferBase::OnFileIO(uv_fs_t *req) +{ + bool tryFinishIO = false; + CtxFileIO *contextIO = (CtxFileIO *)req->data; + CtxFile *context = (CtxFile *)contextIO->context; + HdcTransferBase *thisClass = (HdcTransferBase *)context->thisClass; + uint8_t *bufIO = contextIO->bufIO; + uv_fs_req_cleanup(req); + --thisClass->refCount; + while (true) { + if (req->result < 0) { + WRITE_LOG(LOG_DEBUG, "OnFileIO error: %s", uv_strerror((int)req->result)); + context->closeNotify = true; + tryFinishIO = true; + break; + } + context->indexIO += req->result; + if (req->fs_type == UV_FS_READ) { + if (!thisClass->SendIOPayload(context, context->indexIO - req->result, bufIO, req->result)) { + tryFinishIO = true; + break; + } + if (context->indexIO < context->fileSize) { + // read continue until result >0, let single file packet +packet header less than GetMaxBufSize() + constexpr auto maxBufFactor = 0.8; + thisClass->SimpleFileIO(context, context->indexIO, nullptr, Base::GetMaxBufSize() * maxBufFactor); + } + } else if (req->fs_type == UV_FS_WRITE) { // write + if (context->indexIO >= context->fileSize) { + // The active end must first read it first, but you can't make Finish first, because Slave may not + // end.Only slave receives complete talents Finish + context->closeNotify = true; + tryFinishIO = true; + thisClass->SetFileTime(context); + } + } else { + tryFinishIO = true; + } + break; + } + delete[] bufIO; + delete contextIO; // Req is part of the Contextio structure, no free release + if (tryFinishIO) { + // close-step1 + ++thisClass->refCount; + uv_fs_close(thisClass->loopTask, &context->fsCloseReq, context->fsOpenReq.result, OnFileClose); + } +} + +void HdcTransferBase::OnFileOpen(uv_fs_t *req) +{ + CtxFile *context = (CtxFile *)req->data; + HdcTransferBase *thisClass = (HdcTransferBase *)context->thisClass; + uv_fs_req_cleanup(req); + WRITE_LOG(LOG_DEBUG, "Filemod openfile:%s", context->localPath.c_str()); + --thisClass->refCount; + if (req->result < 0) { + thisClass->LogMsg(MSG_FAIL, "Error opening file: %s, path:%s", uv_strerror((int)req->result), + context->localPath.c_str()); + thisClass->TaskFinish(); + return; + } + thisClass->ResetCtx(context); + if (context->master) { + // init master + uv_fs_t fs; + Base::ZeroStruct(fs.statbuf); + uv_fs_fstat(nullptr, &fs, context->fsOpenReq.result, nullptr); + TransferConfig &st = context->transferConfig; + st.fileSize = fs.statbuf.st_size; + st.optionalName = context->localName; + if (st.holdTimestamp) { + st.atime = fs.statbuf.st_atim.tv_sec * HDC_TIME_CONVERT_BASE + fs.statbuf.st_atim.tv_nsec; + st.mtime = fs.statbuf.st_mtim.tv_sec * HDC_TIME_CONVERT_BASE + fs.statbuf.st_mtim.tv_nsec; + } + st.path = context->remotePath; + // update ctxNow=context child value + context->fileSize = st.fileSize; + + uv_fs_req_cleanup(&fs); + thisClass->CheckMaster(context); + } else { // write + thisClass->SendToAnother(thisClass->commandBegin, nullptr, 0); + } +} + +bool HdcTransferBase::MatchPackageExtendName(string fileName, string extName) +{ + bool match = false; + int subfixIndex = fileName.rfind(extName); + if ((fileName.size() - subfixIndex) != extName.size()) { + return false; + } + match = true; + return match; +} + +// filter can be empty +int HdcTransferBase::GetSubFiles(const char *path, string filter, vector *out) +{ + int retNum = 0; + uv_fs_t req; + Base::ZeroStruct(req); + uv_dirent_t dent; + vector filterStrings; + if (!strlen(path)) { + return retNum; + } + if (filter.size()) { + Base::SplitString(filter, ";", filterStrings); + } + + if (uv_fs_scandir(nullptr, &req, path, 0, nullptr) < 0) { + uv_fs_req_cleanup(&req); + return retNum; + } + while (uv_fs_scandir_next(&req, &dent) != UV_EOF) { + // Skip. File + if (strcmp(dent.name, ".") == 0 || strcmp(dent.name, "..") == 0) + continue; + if (!(static_cast(dent.type) & UV_DIRENT_FILE)) + continue; + string fileName = dent.name; + for (auto &&s : filterStrings) { + int subfixIndex = fileName.rfind(s); + if ((fileName.size() - subfixIndex) != s.size()) + continue; + string fullPath = string(path) + "/"; + fullPath += fileName; + out->push_back(fullPath); + ++retNum; + } + } + uv_fs_req_cleanup(&req); + return retNum; +} + +// https://en.cppreference.com/w/cpp/filesystem/is_directory +// return true if file exist, false if file not exist +bool HdcTransferBase::SmartSlavePath(string &cwd, string &localPath, const char *optName) +{ + if (taskInfo->serverOrDaemon) { + // slave and server + ExtractRelativePath(cwd, localPath); + } + if (Base::CheckDirectoryOrPath(localPath.c_str(), true, false)) { + return true; + } + uv_fs_t req; + int r = uv_fs_lstat(nullptr, &req, localPath.c_str(), nullptr); + uv_fs_req_cleanup(&req); + if (r == 0 && req.statbuf.st_mode & S_IFDIR) { // is dir + localPath = Base::StringFormat("%s%c%s", localPath.c_str(), Base::GetPathSep(), optName); + } + return false; +} + +bool HdcTransferBase::RecvIOPayload(CtxFile *context, uint8_t *data, int dataSize) +{ + uint8_t *clearBuf = nullptr; + string serialStrring((char *)data, payloadPrefixReserve); + TransferPayload pld; + bool ret = false; + SerialStruct::ParseFromString(pld, serialStrring); + clearBuf = new uint8_t[pld.uncompressSize](); + if (!clearBuf) { + return false; + } + int clearSize = 0; + if (pld.compressSize > 0) { + switch (pld.compressType) { +#ifdef HARMONY_PROJECT + case COMPRESS_LZ4: { + clearSize = LZ4_decompress_safe((const char *)data + payloadPrefixReserve, (char *)clearBuf, + pld.compressSize, pld.uncompressSize); + break; + } +#endif + default: { // COMPRESS_NONE + if (memcpy_s(clearBuf, pld.uncompressSize, data + payloadPrefixReserve, pld.compressSize) != EOK) { + delete[] clearBuf; + return false; + } + clearSize = pld.compressSize; + break; + } + } + } + while (true) { + if ((uint32_t)clearSize != pld.uncompressSize) { + break; + } + if (SimpleFileIO(context, pld.index, clearBuf, clearSize) < 0) { + break; + } + ret = true; + break; + } + delete[] clearBuf; + return ret; +} + +bool HdcTransferBase::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ + bool ret = true; + while (true) { + if (command == commandBegin) { + CtxFile *context = &ctxNow; + SimpleFileIO(context, context->indexIO, nullptr, Base::GetMaxBufSize()); + context->transferBegin = Base::GetRuntimeMSec(); + } else if (command == commandData) { + // The size of the actual HOST end may be larger than maxbuf + constexpr auto doubleSize = 2; + if (payloadSize > MAX_SIZE_IOBUF * doubleSize || payloadSize < 0) { + ret = false; + break; + } + // Note, I will trigger FileIO after multiple times. + CtxFile *context = &ctxNow; + if (!RecvIOPayload(context, payload, payloadSize)) { + ret = false; + break; + } + } else { + // Other subclass commands + } + break; + } + return ret; +} + +void HdcTransferBase::ExtractRelativePath(string &cwd, string &path) +{ + bool absPath = Base::IsAbsolutePath(path); + if (!absPath) { + path = cwd + path; + } +} +} // namespace Hdc diff --git a/services/flashd/common/transfer.h b/services/flashd/common/transfer.h new file mode 100755 index 00000000..c03b3dea --- /dev/null +++ b/services/flashd/common/transfer.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_TRANSFER_H +#define HDC_TRANSFER_H +#include "common.h" + +namespace Hdc { +class HdcTransferBase : public HdcTaskBase { +public: + enum CompressType { COMPRESS_NONE, COMPRESS_LZ4, COMPRESS_LZ77, COMPRESS_LZMA, COMPRESS_BROTLI }; + // used for child class + struct TransferConfig { + uint64_t fileSize; + uint64_t atime; // ns + uint64_t mtime; // ns + string options; + string path; + string optionalName; + bool updateIfNew; + uint8_t compressType; + bool holdTimestamp; + string functionName; + string clientCwd; + string reserve1; + string reserve2; + }; + // used for HdcTransferBase. just base class use, not public + struct TransferPayload { + uint64_t index; + uint8_t compressType; + uint32_t compressSize; + uint32_t uncompressSize; + }; + HdcTransferBase(HTaskInfo hTaskInfo); + virtual ~HdcTransferBase(); + virtual void StopTask() + { + } + bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); + +protected: + // Static file context + struct CtxFile { // The structure cannot be initialized by MEMSET + bool master; // Document transmission initiative + bool closeNotify; + void *thisClass; + uint64_t fileSize; + uint64_t indexIO; // Id or written IO bytes + uv_loop_t *loop; + uv_fs_cb cb; + string localName; + string localPath; + string remotePath; + uv_fs_t fsOpenReq; + uv_fs_t fsCloseReq; + uint64_t transferBegin; + vector taskQueue; + TransferConfig transferConfig; // Used for network IO configuration initialization + }; + // Just app-mode use + enum AppModType { + APPMOD_NONE, + APPMOD_INSTALL, + APPMOD_UNINSTALL, + APPMOD_SIDELOAD, + }; + + static void OnFileOpen(uv_fs_t *req); + static void OnFileClose(uv_fs_t *req); + int GetSubFiles(const char *path, string filter, vector *out); + virtual void CheckMaster(CtxFile *context) + { + } + virtual void WhenTransferFinish(CtxFile *context) + { + } + bool MatchPackageExtendName(string fileName, string extName); + bool ResetCtx(CtxFile *context, bool full = false); + bool SmartSlavePath(string &cwd, string &localPath, const char *optName); + void SetFileTime(CtxFile *context); + void ExtractRelativePath(string &cwd, string &path); + + CtxFile ctxNow; + uint16_t commandBegin; + uint16_t commandData; + const string CMD_OPTION_CLIENTCWD = "-cwd"; + const uint8_t payloadPrefixReserve = 64; +private: + // dynamic IO context + struct CtxFileIO { + uv_fs_t fs; + uint8_t *bufIO; + CtxFile *context; + }; + static void OnFileIO(uv_fs_t *req); + int SimpleFileIO(CtxFile *context, uint64_t index, uint8_t *sendBuf, int bytesIO); + bool SendIOPayload(CtxFile *context, int index, uint8_t *data, int dataSize); + bool RecvIOPayload(CtxFile *context, uint8_t *data, int dataSize); +}; +} // namespace Hdc + +#endif \ No newline at end of file diff --git a/services/flashd/common/usb.cpp b/services/flashd/common/usb.cpp new file mode 100755 index 00000000..db39a445 --- /dev/null +++ b/services/flashd/common/usb.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "usb.h" + +namespace Hdc { +HdcUSBBase::HdcUSBBase(const bool serverOrDaemonIn, void *ptrMainBase) +{ + serverOrDaemon = serverOrDaemonIn; + clsMainBase = ptrMainBase; + modRunning = true; +} + +HdcUSBBase::~HdcUSBBase() +{ +} + +void HdcUSBBase::ReadUSB(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) +{ + HSession hSession = (HSession)stream->data; + HdcSessionBase *hSessionBase = (HdcSessionBase *)hSession->classInstance; + if (hSessionBase->FetchIOBuf(hSession, hSession->ioBuf, nread) < 0) { + hSessionBase->FreeSession(hSession->sessionId); + } +} + +bool HdcUSBBase::ReadyForWorkThread(HSession hSession) +{ + // Server-end USB IO is handed over to each sub-thread, only the daemon is still read by the main IO to distribute + // to each sub-thread by DataPipe. + if (uv_tcp_init(&hSession->childLoop, &hSession->dataPipe[STREAM_WORK]) + || uv_tcp_open(&hSession->dataPipe[STREAM_WORK], hSession->dataFd[STREAM_WORK])) { + WRITE_LOG(LOG_FATAL, "USBBase ReadyForWorkThread init child TCP failed"); + return false; + } + hSession->dataPipe[STREAM_WORK].data = hSession; + HdcSessionBase *pSession = (HdcSessionBase *)hSession->classInstance; + Base::SetTcpOptions(&hSession->dataPipe[STREAM_WORK]); + if (uv_read_start((uv_stream_t *)&hSession->dataPipe[STREAM_WORK], pSession->AllocCallback, ReadUSB)) { + WRITE_LOG(LOG_FATAL, "USBBase ReadyForWorkThread child TCP read failed"); + return false; + } + WRITE_LOG(LOG_DEBUG, "USBBase ReadyForWorkThread finish"); + return true; +}; + +// USB big data stream, block transmission, mainly to prevent accidental data packets from writing through EP port, +// inserting the send queue causes the program to crash +int HdcUSBBase::SendUSBBlock(HSession hSession, uint8_t *data, const int length) +{ + // Format:USBPacket1 payload1...USBPacketn payloadn; + // [USBHead1(PayloadHead1+Payload1)]+[USBHead2(Payload2)]+...+[USBHeadN(PayloadN)] + int maxIOSize = Base::GetMaxBufSize(); + int sizeUSBPacketHead = sizeof(USBHead); + int singleSize = maxIOSize - sizeUSBPacketHead; + int iMod = length % singleSize; + int iCount = (length - iMod) / singleSize + 1; + int offset = 0; + int i = 0; // It doesn't matter of 0 or 1, start from 1 to send it according to the serial number. + uint8_t *ioBuf = new uint8_t[maxIOSize](); + if (!ioBuf) { + return ERR_BUF_ALLOC; + } + for (i = 0; i < iCount; ++i) { + USBHead *pUSBHead = (USBHead *)ioBuf; + int errCode = memcpy_s(pUSBHead->flag, sizeof(pUSBHead->flag), PACKET_FLAG.c_str(), PACKET_FLAG.size()); + if (errCode != EOK) { + offset = ERR_BUF_COPY; + break; + } + pUSBHead->sessionId = hSession->sessionId; + if (i != iCount - 1) { + pUSBHead->dataSize = static_cast(singleSize); + } else { + pUSBHead->dataSize = static_cast(iMod); + pUSBHead->option = pUSBHead->option | USB_OPTION_TAIL; + } + uint8_t *payload = ioBuf + sizeUSBPacketHead; + if (EOK != memcpy_s(payload, maxIOSize - sizeUSBPacketHead, (uint8_t *)data + offset, pUSBHead->dataSize)) { + offset = ERR_BUF_COPY; + break; + } + offset += pUSBHead->dataSize; + if (SendUSBRaw(hSession, ioBuf, sizeUSBPacketHead + pUSBHead->dataSize) <= 0) { + offset = ERR_IO_FAIL; + break; + } + } + delete[] ioBuf; + return offset; +} + +int HdcUSBBase::SendToHdcStream(HSession hSession, uv_stream_t *stream, uint8_t *appendData, int dataSize) +{ + HUSB hUSB = hSession->hUSB; + vector &bufRecv = hUSB->bufRecv; + bufRecv.insert(bufRecv.end(), appendData, appendData + dataSize); + int ret = RET_SUCCESS; + while (bufRecv.size() > sizeof(USBHead)) { + USBHead *usbHeader = (USBHead *)bufRecv.data(); + if (memcmp(usbHeader->flag, PACKET_FLAG.c_str(), PACKET_FLAG.size())) { + WRITE_LOG(LOG_FATAL, "Error usb packet"); + ret = ERR_BUF_CHECK; + break; + } + if (bufRecv.size() < sizeof(USBHead) + usbHeader->dataSize) { + WRITE_LOG(LOG_DEBUG, "SendToHdcStream not enough"); + break; // successful , but not enough + } + if (usbHeader->sessionId != hSession->sessionId) { + // Only server do it here, daemon 'SendUsbSoftReset' no use + // hilog + ctrl^C to reproduction scene + // + // Because the USB-reset API does not work on all platforms, the last session IO data may be + // recveived, we need to ignore it. + if (hSession->serverOrDaemon && !hUSB->resetIO) { + WRITE_LOG(LOG_WARN, "SendToHdcStream sessionId not matched"); + SendUsbSoftReset(hUSB, usbHeader->sessionId); + hUSB->resetIO = true; + } + } else { + // usb data to logic + if (Base::SendToStream(stream, bufRecv.data() + sizeof(USBHead), usbHeader->dataSize) < 0) { + ret = ERR_IO_FAIL; + WRITE_LOG(LOG_FATAL, "Error usb send to stream"); + break; + } + } + bufRecv.erase(bufRecv.begin(), bufRecv.begin() + sizeof(USBHead) + usbHeader->dataSize); + } + return ret; +} +} \ No newline at end of file diff --git a/services/flashd/common/usb.h b/services/flashd/common/usb.h new file mode 100755 index 00000000..8b49c54c --- /dev/null +++ b/services/flashd/common/usb.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_USB_H +#define HDC_USB_H +#include "common.h" + +namespace Hdc { +class HdcUSBBase { +public: + HdcUSBBase(const bool serverOrDaemonIn, void *ptrMainBase); + virtual ~HdcUSBBase(); + virtual int SendUSBRaw(HSession hSession, uint8_t *data, const int length) + { + return 0; + } + virtual bool ReadyForWorkThread(HSession hSession); + virtual void SendUsbSoftReset(HUSB hUSB, uint32_t sessionId) {}; + int SendUSBBlock(HSession hSession, uint8_t *data, const int length); + static void ReadUSB(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); + int SendToHdcStream(HSession hSession, uv_stream_t *stream, uint8_t *appendData, int dataSize); + +protected: + void *clsMainBase; + bool serverOrDaemon; + bool modRunning; +}; +} // namespace Hdc + +#endif \ No newline at end of file diff --git a/services/flashd/daemon/daemon.cpp b/services/flashd/daemon/daemon.cpp new file mode 100755 index 00000000..fa34ef8b --- /dev/null +++ b/services/flashd/daemon/daemon.cpp @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "daemon.h" +#include "../common/serial_struct.h" +#include + +namespace Hdc { +HdcDaemon::HdcDaemon(bool serverOrDaemonIn) + : HdcSessionBase(serverOrDaemonIn) +{ + clsTCPServ = nullptr; + clsUSBServ = nullptr; + clsJdwp = nullptr; + enableSecure = false; +} + +HdcDaemon::~HdcDaemon() +{ + WRITE_LOG(LOG_DEBUG, "~HdcDaemon"); +} + +void HdcDaemon::ClearInstanceResource() +{ + TryStopInstance(); + Base::TryCloseLoop(&loopMain, "HdcDaemon::~HdcDaemon"); + if (clsTCPServ) { + delete (HdcDaemonTCP *)clsTCPServ; + clsTCPServ = nullptr; + } + if (clsUSBServ) { + delete (HdcDaemonUSB *)clsUSBServ; + clsUSBServ = nullptr; + } + if (clsJdwp) { + delete (HdcJdwp *)clsJdwp; + clsJdwp = nullptr; + } + WRITE_LOG(LOG_DEBUG, "~HdcDaemon finish"); +} + +void HdcDaemon::TryStopInstance() +{ + ClearSessions(); + if (clsTCPServ) { + WRITE_LOG(LOG_DEBUG, "Stop TCP"); + ((HdcDaemonTCP *)clsTCPServ)->Stop(); + } + if (clsUSBServ) { + WRITE_LOG(LOG_DEBUG, "Stop USB"); + ((HdcDaemonUSB *)clsUSBServ)->Stop(); + } + ((HdcJdwp *)clsJdwp)->Stop(); + // workaround temply remove MainLoop instance clear + ReMainLoopForInstanceClear(); + WRITE_LOG(LOG_DEBUG, "Stop loopmain"); +} + +void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB) +{ + WRITE_LOG(LOG_DEBUG, "HdcDaemon InitMod"); + if (bEnableTCP) { + // tcp + clsTCPServ = new HdcDaemonTCP(false, this); + ((HdcDaemonTCP *)clsTCPServ)->Initial(); + } + if (bEnableUSB) { + // usb + clsUSBServ = new HdcDaemonUSB(false, this); + ((HdcDaemonUSB *)clsUSBServ)->Initial(); + } + + clsJdwp = new HdcJdwp(&loopMain); + ((HdcJdwp *)clsJdwp)->Initial(); + + // enable security + char value[4] = "0"; + Base::GetHdcProperty("ro.hdc.secure", value, sizeof(value)); + string secure = value; + enableSecure = (Base::Trim(secure) == "1"); +} + +void HdcDaemon::SendAndCloseChannel(HSession hSession, const uint32_t channelId, const std::string &info) +{ + Send(hSession->sessionId, channelId, CMD_KERNEL_ECHO_RAW, (uint8_t *)info.data(), info.size()); + uint8_t count = 1; + Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1); +} + +// clang-format off +#ifdef HDC_SUPPORT_FLASHD +bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, + const uint16_t command, uint8_t *payload, const int payloadSize) +{ + bool ret = true; + hTaskInfo->ownerSessionClass = this; + switch (command) { + case CMD_UNITY_REBOOT: + case CMD_UNITY_RUNMODE: + ret = TaskCommandDispatch(hTaskInfo, TYPE_UNITY, command, payload, payloadSize); + break; + case CMD_UPDATER_UPDATE_INIT: + case CMD_UPDATER_FLASH_INIT: + case CMD_UPDATER_CHECK: + case CMD_UPDATER_BEGIN: + case CMD_UPDATER_DATA: + case CMD_UPDATER_FINISH: + case CMD_UPDATER_ERASE: + case CMD_UPDATER_FORMAT: + case CMD_UPDATER_PROGRESS: + ret = TaskCommandDispatch(hTaskInfo, TASK_UPDATER, command, payload, payloadSize); + break; + default: + SendAndCloseChannel(hSession, channelId, "Command not support in flashd\n"); + break; + } + return ret; +} +#else +bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, + const uint16_t command, uint8_t *payload, const int payloadSize) +{ + bool ret = true; + hTaskInfo->ownerSessionClass = this; + switch (command) { + case CMD_UNITY_EXECUTE: + case CMD_UNITY_REMOUNT: + case CMD_UNITY_REBOOT: + case CMD_UNITY_RUNMODE: + case CMD_UNITY_HILOG: + case CMD_UNITY_ROOTRUN: + case CMD_UNITY_TERMINATE: + case CMD_UNITY_BUGREPORT_INIT: + case CMD_UNITY_JPID: + ret = TaskCommandDispatch(hTaskInfo, TYPE_UNITY, command, payload, payloadSize); + break; + case CMD_SHELL_INIT: + case CMD_SHELL_DATA: + ret = TaskCommandDispatch(hTaskInfo, TYPE_SHELL, command, payload, payloadSize); + break; + case CMD_FILE_CHECK: + case CMD_FILE_DATA: + case CMD_FILE_FINISH: + case CMD_FILE_INIT: + case CMD_FILE_BEGIN: + ret = TaskCommandDispatch(hTaskInfo, TASK_FILE, command, payload, payloadSize); + break; + // One-way function, so fewer options + case CMD_APP_CHECK: + case CMD_APP_DATA: + case CMD_APP_UNINSTALL: + ret = TaskCommandDispatch(hTaskInfo, TASK_APP, command, payload, payloadSize); + break; + case CMD_FORWARD_INIT: + case CMD_FORWARD_CHECK: + case CMD_FORWARD_ACTIVE_SLAVE: + case CMD_FORWARD_DATA: + case CMD_FORWARD_FREE_CONTEXT: + case CMD_FORWARD_CHECK_RESULT: + ret = TaskCommandDispatch(hTaskInfo, TASK_FORWARD, command, payload, payloadSize); + break; + case CMD_UPDATER_CHECK: + case CMD_UPDATER_ERASE: + case CMD_UPDATER_FORMAT: + SendAndCloseChannel(hSession, channelId, "Command not support in hdcd\n"); + break; + default: + ret = false; + break; + } + return ret; +} +// clang-format on +#endif + +bool HdcDaemon::HandDaemonAuth(HSession hSession, const uint32_t channelId, SessionHandShake &handshake) +{ + bool ret = false; + switch (handshake.authType) { + case AUTH_NONE: { // AUTH_NONE -> AUTH + hSession->tokenRSA = Base::GetRandomString(SHA_DIGEST_LENGTH); + handshake.authType = AUTH_TOKEN; + handshake.buf = hSession->tokenRSA; + string bufString = SerialStruct::SerializeToString(handshake); + Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), bufString.size()); + ret = true; + break; + } + case AUTH_SIGNATURE: { + // When Host is first connected to the device, the signature authentication is inevitable, and the + // certificate verification must be triggered. + // + // When the certificate is verified, the client sends a public key to the device, triggered the system UI + // jump out dialog, and click the system, the system will store the Host public key certificate in the + // device locally, and the signature authentication will be correct when the subsequent connection is + // connected. + if (!HdcAuth::AuthVerify((uint8_t *)hSession->tokenRSA.c_str(), (uint8_t *)handshake.buf.c_str(), + handshake.buf.size())) { + // Next auth + handshake.authType = AUTH_TOKEN; + handshake.buf = hSession->tokenRSA; + string bufString = SerialStruct::SerializeToString(handshake); + Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), + bufString.size()); + break; + } + ret = true; + break; + } + case AUTH_PUBLICKEY: { + ret = HdcAuth::PostUIConfirm(handshake.buf); + WRITE_LOG(LOG_DEBUG, "Auth host OK, postUIConfirm"); + break; + } + default: + break; + } + return ret; +} + +bool HdcDaemon::DaemonSessionHandshake(HSession hSession, const uint32_t channelId, uint8_t *payload, int payloadSize) +{ + // session handshake step2 + string s = string((char *)payload, payloadSize); + SessionHandShake handshake; + string err; + SerialStruct::ParseFromString(handshake, s); + // banner to check is parse ok... + if (handshake.banner != HANDSHAKE_MESSAGE) { + hSession->availTailIndex = 0; + WRITE_LOG(LOG_FATAL, "Recv server-hello failed"); + return false; + } + if (handshake.authType == AUTH_NONE) { + // daemon handshake 1st packet + uint32_t unOld = hSession->sessionId; + hSession->sessionId = handshake.sessionId; + hSession->connectKey = handshake.connectKey; + AdminSession(OP_UPDATE, unOld, hSession); + if (clsUSBServ != nullptr) { + (reinterpret_cast(clsUSBServ))->OnNewHandshakeOK(hSession->sessionId); + } + + handshake.sessionId = 0; + handshake.connectKey = ""; + } + if (enableSecure && !HandDaemonAuth(hSession, channelId, handshake)) { + return false; + } + // handshake auth OK.Can append the sending device information to HOST + char hostName[BUF_SIZE_MEDIUM] = ""; + size_t len = sizeof(hostName); + uv_os_gethostname(hostName, &len); + handshake.authType = AUTH_OK; + handshake.buf = hostName; + string bufString = SerialStruct::SerializeToString(handshake); + Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), bufString.size()); + hSession->handshakeOK = true; + return true; +} + +bool HdcDaemon::FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, + int payloadSize) +{ + bool ret = true; + if (!hSession->handshakeOK && command != CMD_KERNEL_HANDSHAKE) { + ret = false; + return ret; + } + switch (command) { + case CMD_KERNEL_HANDSHAKE: { + // session handshake step2 + ret = DaemonSessionHandshake(hSession, channelId, payload, payloadSize); + break; + } + case CMD_KERNEL_CHANNEL_CLOSE: { // Daemon is only cleaning up the Channel task + ClearOwnTasks(hSession, channelId); + if (*payload == 1) { + --(*payload); + Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1); + } + ret = true; + break; + } + default: + ret = DispatchTaskData(hSession, channelId, command, payload, payloadSize); + break; + } + return ret; +} + +bool HdcDaemon::RemoveInstanceTask(const uint8_t op, HTaskInfo hTask) +{ + bool ret = true; + switch (hTask->taskType) { + case TYPE_UNITY: + ret = DoTaskRemove(hTask, op); + break; + case TYPE_SHELL: + ret = DoTaskRemove(hTask, op); + break; + case TASK_FILE: + ret = DoTaskRemove(hTask, op); + break; + case TASK_FORWARD: + ret = DoTaskRemove(hTask, op); + break; + case TASK_APP: + ret = DoTaskRemove(hTask, op); + break; +#ifdef HDC_SUPPORT_FLASHD + case TASK_UPDATER: + ret = DoTaskRemove(hTask, op); + break; +#endif + default: + ret = false; + break; + } + return ret; +} + +bool HdcDaemon::ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, + uint8_t *bufPtr, const int size) +{ + return Send(sessionId, channelId, command, (uint8_t *)bufPtr, size) > 0; +} + +void HdcDaemon::JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO) +{ + uint32_t pid = *(uint32_t *)(buf + 1); + uint32_t fd = *(uint32_t *)(buf + 5); // 5 : fd offset + ((HdcJdwp *)clsJdwp)->SendJdwpNewFD(pid, fd); +}; +} // namespace Hdc diff --git a/services/flashd/daemon/daemon.h b/services/flashd/daemon/daemon.h new file mode 100755 index 00000000..4eb7df29 --- /dev/null +++ b/services/flashd/daemon/daemon.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_DAEMON_H +#define HDC_DAEMON_H +#include "daemon_common.h" + +namespace Hdc { +class HdcDaemon : public HdcSessionBase { +public: + HdcDaemon(bool serverOrDaemonIn); + virtual ~HdcDaemon(); + void InitMod(bool bEnableTCP, bool bEnableUSB); + bool FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, + const int payloadSize); + bool ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, uint8_t *bufPtr, + const int size); + void *clsTCPServ; + void *clsUSBServ; + void *clsJdwp; + +private: + bool RemoveInstanceTask(const uint8_t op, HTaskInfo hTask); + bool RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, const uint16_t command, + uint8_t *payload, const int payloadSize); + void SendAndCloseChannel(HSession hSession, const uint32_t channelId, const std::string &info); + void JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO); + bool HandDaemonAuth(HSession hSession, const uint32_t channelId, SessionHandShake &handshake); + void ClearInstanceResource(); + bool DaemonSessionHandshake(HSession hSession, const uint32_t channelId, uint8_t *payload, int payloadSize); + void TryStopInstance(); + + bool enableSecure; +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/daemon/daemon_app.cpp b/services/flashd/daemon/daemon_app.cpp new file mode 100755 index 00000000..4f04dc93 --- /dev/null +++ b/services/flashd/daemon/daemon_app.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "daemon_app.h" + +namespace Hdc { +HdcDaemonApp::HdcDaemonApp(HTaskInfo hTaskInfo) + : HdcTransferBase(hTaskInfo) +{ + commandBegin = CMD_APP_BEGIN; + commandData = CMD_APP_DATA; + funcAppModFinish = nullptr; +} + +HdcDaemonApp::~HdcDaemonApp() +{ + WRITE_LOG(LOG_DEBUG, "~HdcDaemonApp"); +} + +bool HdcDaemonApp::ReadyForRelease() +{ + if (!HdcTaskBase::ReadyForRelease()) { + return false; + } + if (!asyncCommand.ReadyForRelease()) { + return false; + } + return true; +} + +bool HdcDaemonApp::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ + if (!HdcTransferBase::CommandDispatch(command, payload, payloadSize)) { + return false; + } + bool ret = true; + switch (command) { + case CMD_APP_CHECK: { + string tmpData = "/data/local/tmp/"; + string tmpSD = "/sdcard/tmp/"; + string dstPath = tmpData; + string bufString((char *)payload, payloadSize); + SerialStruct::ParseFromString(ctxNow.transferConfig, bufString); + // update transferconfig to main context + ctxNow.master = false; + ctxNow.fsOpenReq.data = &ctxNow; + // -lrtsdpg, -l -r -t -s.., + if (ctxNow.transferConfig.functionName == CMDSTR_APP_INSTALL + && ctxNow.transferConfig.options.find("s") != std::string::npos) { + dstPath = tmpSD; + } +#ifdef HDC_PCDEBUG + char tmpPath[256] = ""; + size_t size = 256; + uv_os_tmpdir(tmpPath, &size); + dstPath = tmpPath; + dstPath += Base::GetPathSep(); +#endif + dstPath += ctxNow.transferConfig.optionalName; + ctxNow.localPath = dstPath; + ctxNow.transferBegin = Base::GetRuntimeMSec(); + ctxNow.fileSize = ctxNow.transferConfig.fileSize; + ++refCount; + uv_fs_open(loopTask, &ctxNow.fsOpenReq, ctxNow.localPath.c_str(), + UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IRUSR, OnFileOpen); + break; + } + case CMD_APP_UNINSTALL: { + // This maybe has a command implanting risk, since it is a controllable device, it can be ignored + string bufString(reinterpret_cast(payload), payloadSize); + PackageShell(false, "", bufString); + break; + } + default: + break; + } + return ret; +}; + +bool HdcDaemonApp::AsyncInstallFinish(bool finish, int64_t exitStatus, const string result) +{ + if (mode == APPMOD_INSTALL) { + unlink(ctxNow.localPath.c_str()); + } + asyncCommand.DoRelease(); + string echo = result; + echo = Base::ReplaceAll(echo, "\n", " "); + vector vecBuf; + vecBuf.push_back(mode); + vecBuf.push_back(exitStatus == 0); + vecBuf.insert(vecBuf.end(), (uint8_t *)echo.c_str(), (uint8_t *)echo.c_str() + echo.size()); + SendToAnother(CMD_APP_FINISH, vecBuf.data(), vecBuf.size()); + --refCount; +#ifdef UNIT_TEST + Base::WriteBinFile((UT_TMP_PATH + "/appinstall.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(), + MESSAGE_SUCCESS.size(), true); +#endif + return true; +} + +void HdcDaemonApp::PackageShell(bool installOrUninstall, const char *options, const string package) +{ + ++refCount; + // asynccmd Other processes, no RunningProtect protection + chmod(package.c_str(), 0644); // 0644 : permission + string doBuf; + if (installOrUninstall) { + doBuf = Base::StringFormat("bm install %s -p %s", options, package.c_str()); + } else { + doBuf = Base::StringFormat("bm uninstall %s -n %s", options, package.c_str()); + } + funcAppModFinish = std::bind(&HdcDaemonApp::AsyncInstallFinish, this, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3); + if (installOrUninstall) { + mode = APPMOD_INSTALL; + } else { + mode = APPMOD_UNINSTALL; + } + asyncCommand.Initial(loopTask, funcAppModFinish); + asyncCommand.ExecuteCommand(doBuf); +} + +void HdcDaemonApp::Sideload(const char *pathOTA) +{ + mode = APPMOD_SIDELOAD; + LogMsg(MSG_OK, "[placeholders] sideload %s", pathOTA); + TaskFinish(); + unlink(pathOTA); +} + +void HdcDaemonApp::WhenTransferFinish(CtxFile *context) +{ + if (ctxNow.transferConfig.functionName == CMDSTR_APP_SIDELOAD) { + Sideload(context->localPath.c_str()); + } else if (ctxNow.transferConfig.functionName == CMDSTR_APP_INSTALL) { + PackageShell(true, context->transferConfig.options.c_str(), context->localPath.c_str()); + } else { + } +}; +} \ No newline at end of file diff --git a/services/flashd/daemon/daemon_app.h b/services/flashd/daemon/daemon_app.h new file mode 100755 index 00000000..7546fc39 --- /dev/null +++ b/services/flashd/daemon/daemon_app.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_DAEMON_APP_H +#define HDC_DAEMON_APP_H +#include "daemon_common.h" + +namespace Hdc { +class HdcDaemonApp : public HdcTransferBase { +public: + HdcDaemonApp(HTaskInfo hTaskInfo); + virtual ~HdcDaemonApp(); + bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); + bool ReadyForRelease(); + +private: + void WhenTransferFinish(CtxFile *context); + void PackageShell(bool installOrUninstall, const char *options, const string package); + bool AsyncInstallFinish(bool finish, int64_t exitStatus, const string result); + void Sideload(const char *pathOTA); + + AsyncCmd asyncCommand; + AsyncCmd::CmdResultCallback funcAppModFinish; + AppModType mode = APPMOD_NONE; +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/daemon/daemon_common.h b/services/flashd/daemon/daemon_common.h new file mode 100755 index 00000000..35786e03 --- /dev/null +++ b/services/flashd/daemon/daemon_common.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_DAEMON_COMMON_H +#define HDC_DAEMON_COMMON_H + +// clang-format off +#include "../common/common.h" +#include "../common/define.h" +#include "../common/file.h" +#include "../common/forward.h" +#include "../common/async_cmd.h" +#include "../common/serial_struct.h" +#include "jdwp.h" +#include "daemon.h" +#include "daemon_unity.h" +#include "daemon_tcp.h" +#include "daemon_app.h" +#include "daemon_usb.h" +#include "daemon_forward.h" +#ifdef HDC_SUPPORT_FLASHD +#include "daemon_updater.h" +#endif +#include "shell.h" + +// clang-format on + +namespace Hdc { +} +#endif \ No newline at end of file diff --git a/services/flashd/daemon/daemon_forward.cpp b/services/flashd/daemon/daemon_forward.cpp new file mode 100755 index 00000000..25ddb710 --- /dev/null +++ b/services/flashd/daemon/daemon_forward.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "daemon_forward.h" + +namespace Hdc { +HdcDaemonForward::HdcDaemonForward(HTaskInfo hTaskInfo) + : HdcForwardBase(hTaskInfo) +{ +} + +HdcDaemonForward::~HdcDaemonForward() +{ +} + +void HdcDaemonForward::SetupJdwpPointCallBack(uv_idle_t *handle) +{ + HCtxForward ctxPoint = (HCtxForward)handle->data; + HdcDaemonForward *thisClass = reinterpret_cast(ctxPoint->thisClass); + thisClass->SetupPointContinue(ctxPoint, 1); // It usually works + Base::TryCloseHandle((const uv_handle_t *)handle, Base::CloseIdleCallback); + WRITE_LOG(LOG_DEBUG, "Setup JdwpPointCallBack finish"); + --thisClass->refCount; + return; +} + +bool HdcDaemonForward::SetupJdwpPoint(HCtxForward ctxPoint) +{ + HdcDaemon *daemon = (HdcDaemon *)taskInfo->ownerSessionClass; + HdcJdwp *clsJdwp = (HdcJdwp *)daemon->clsJdwp; + uint32_t pid = std::stol(ctxPoint->localArgs[1]); + if (ctxPoint->checkPoint) { // checke + bool ret = clsJdwp->CheckPIDExist(pid); + SetupPointContinue(ctxPoint, (int)ret); + WRITE_LOG(LOG_DEBUG, "Jdwp jump checkpoint"); + return true; + } + // do slave connect + // fd[0] for forward, fd[1] for jdwp + // forward to close fd[0], fd[1] for jdwp close + int fds[2] = { 0 }; + bool ret = false; + Base::CreateSocketPair(fds); + if (uv_tcp_init(loopTask, &ctxPoint->tcp)) { + return ret; + } + ctxPoint->tcp.data = ctxPoint; + if (uv_tcp_open(&ctxPoint->tcp, fds[0])) { + return ret; + } + constexpr auto len = sizeof(uint32_t); + uint8_t flag[1 + len + len]; + flag[0] = SP_JDWP_NEWFD; + if (memcpy_s(flag + 1, sizeof(flag) - 1, &pid, len) || + memcpy_s(flag + 1 + len, sizeof(flag) - len - 1, &fds[1], len)) { + return ret; + } + if (ThreadCtrlCommunicate(flag, sizeof(flag)) > 0) { + ret = true; + } + WRITE_LOG(LOG_DEBUG, "SendJdwpNewFD Finish,ret:%d fd0:%d fd1:%d", ret, fds[0], fds[1]); + if (!ret) { + Base::CloseSocketPair(fds); + return ret; + } + + ++refCount; + Base::IdleUvTask(loopTask, ctxPoint, SetupJdwpPointCallBack); + return ret; +} +} \ No newline at end of file diff --git a/services/flashd/daemon/daemon_forward.h b/services/flashd/daemon/daemon_forward.h new file mode 100755 index 00000000..5dfae60a --- /dev/null +++ b/services/flashd/daemon/daemon_forward.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_DAEMON_FORWARD_H +#define HDC_DAEMON_FORWARD_H +#include "daemon_common.h" + +namespace Hdc { +class HdcDaemonForward : public HdcForwardBase { +public: + HdcDaemonForward(HTaskInfo hTaskInfo); + virtual ~HdcDaemonForward(); + +private: + bool SetupJdwpPoint(HCtxForward ctxPoint); + static void SetupJdwpPointCallBack(uv_idle_t *handle); +}; +} // namespace Hdc + +#endif \ No newline at end of file diff --git a/services/flashd/daemon/daemon_tcp.cpp b/services/flashd/daemon/daemon_tcp.cpp new file mode 100755 index 00000000..64d16aeb --- /dev/null +++ b/services/flashd/daemon/daemon_tcp.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "daemon_tcp.h" + +namespace Hdc { +HdcDaemonTCP::HdcDaemonTCP(const bool serverOrDaemonIn, void *ptrMainBase) + : HdcTCPBase(serverOrDaemonIn, ptrMainBase) +{ + // If the listening value for the property setting is obtained, it will be 0 randomly assigned. + char strTCPPort[BUF_SIZE_TINY] = ""; + const uint16_t BUFF_SIZE = 8; + Base::GetHdcProperty("persist.hdc.port", strTCPPort, BUFF_SIZE); + tcpListenPort = atoi(strTCPPort); + if (tcpListenPort <= 0) { + tcpListenPort = 10178; // 10178 def port + } + Base::ZeroStruct(servUDP); + Base::ZeroStruct(servTCP); +#ifdef HDC_DEBUG + const uint16_t DEBUG_TCP_PORT = 10178; + tcpListenPort = DEBUG_TCP_PORT; +#endif +} + +HdcDaemonTCP::~HdcDaemonTCP() +{ +} + +void HdcDaemonTCP::Stop() +{ + Base::TryCloseHandle((const uv_handle_t *)&servUDP); + Base::TryCloseHandle((const uv_handle_t *)&servTCP); + WRITE_LOG(LOG_DEBUG, "~HdcDaemonTCP"); +} + +void HdcDaemonTCP::TransmitConfig(const sockaddr *addrSrc, uv_udp_t *handle) +{ + char srcIP[BUF_SIZE_TINY] = ""; + struct sockaddr addrSrcIPPort; + uv_udp_send_t *req = new uv_udp_send_t(); + if (!req) { + return; + } + string sendBuf = Base::StringFormat("%s-%d", HANDSHAKE_MESSAGE.c_str(), tcpListenPort); + uv_buf_t sndbuf = uv_buf_init((char *)sendBuf.c_str(), sendBuf.size()); + uv_ip4_name((sockaddr_in *)addrSrc, srcIP, sizeof(srcIP)); + uv_ip4_addr(srcIP, DEFAULT_PORT, (sockaddr_in *)&addrSrcIPPort); + uv_udp_send(req, handle, &sndbuf, 1, &addrSrcIPPort, SendUDPFinish); +} + +void HdcDaemonTCP::AcceptClient(uv_stream_t *server, int status) +{ + uv_loop_t *ptrLoop = server->loop; + uv_tcp_t *pServTCP = (uv_tcp_t *)server; + HdcDaemonTCP *thisClass = (HdcDaemonTCP *)pServTCP->data; + HdcSessionBase *ptrConnect = (HdcSessionBase *)thisClass->clsMainBase; + HdcSessionBase *daemon = reinterpret_cast(thisClass->clsMainBase); + const uint16_t maxWaitTime = UV_DEFAULT_INTERVAL; + auto ctrl = daemon->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0); + HSession hSession = ptrConnect->MallocSession(false, CONN_TCP, thisClass); + if (!hSession) { + return; + } + if (uv_accept(server, (uv_stream_t *)&hSession->hWorkTCP) < 0) { + goto Finish; + } + if ((hSession->fdChildWorkTCP = Base::DuplicateUvSocket(&hSession->hWorkTCP)) < 0) { + goto Finish; + }; + Base::TryCloseHandle((uv_handle_t *)&hSession->hWorkTCP); + Base::StartWorkThread(ptrLoop, ptrConnect->SessionWorkThread, Base::FinishWorkThread, hSession); + // wait for thread up + while (hSession->childLoop.active_handles == 0) { + usleep(maxWaitTime); + } + Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); + return; +Finish: + ptrConnect->FreeSession(hSession->sessionId); +} + +void HdcDaemonTCP::RecvUDPEntry(const sockaddr *addrSrc, uv_udp_t *handle, const uv_buf_t *rcvbuf) +{ + TransmitConfig(addrSrc, handle); +} + +void HdcDaemonTCP::SetUDPListen() +{ + struct sockaddr_in addr; + int r; + HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase; + // udp broadcast + servUDP.data = this; + r = uv_udp_init(&ptrConnect->loopMain, &servUDP); + r = uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &addr); + r = uv_udp_bind(&servUDP, (const struct sockaddr *)&addr, UV_UDP_REUSEADDR); + r = uv_udp_recv_start(&servUDP, AllocStreamUDP, RecvUDP); +} + +// Set the daemon-side TCP listening +int HdcDaemonTCP::SetTCPListen() +{ + // tcp listen + HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase; + servTCP.data = this; + struct sockaddr_in addr; + int namelen; + const int DEFAULT_BACKLOG = 128; + + uv_tcp_init(&ptrConnect->loopMain, &servTCP); + uv_ip4_addr("0.0.0.0", tcpListenPort, &addr); // tcpListenPort == 0 + uv_tcp_bind(&servTCP, (const struct sockaddr *)&addr, 0); + if (uv_listen((uv_stream_t *)&servTCP, DEFAULT_BACKLOG, (uv_connection_cb)AcceptClient)) { + return ERR_API_FAIL; + } + // Get listen port + Base::ZeroStruct(addr); + namelen = sizeof(addr); + if (uv_tcp_getsockname(&servTCP, (sockaddr *)&addr, &namelen)) { + return ERR_API_FAIL; + } + tcpListenPort = ntohs(addr.sin_port); + return RET_SUCCESS; +} + +int HdcDaemonTCP::Initial() +{ + WRITE_LOG(LOG_DEBUG, "HdcDaemonTCP init"); + SetUDPListen(); + if (SetTCPListen() != RET_SUCCESS) { + WRITE_LOG(LOG_FATAL, "TCP listen failed"); + return ERR_GENERIC; + } +#ifndef UNIT_TEST + WRITE_LOG(LOG_INFO, "TCP listen on port:[%d]", tcpListenPort); +#endif + return RET_SUCCESS; +} +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/daemon/daemon_tcp.h b/services/flashd/daemon/daemon_tcp.h new file mode 100755 index 00000000..bd399ea6 --- /dev/null +++ b/services/flashd/daemon/daemon_tcp.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_DAEMON_TCP_H +#define HDC_DAEMON_TCP_H +#include "daemon_common.h" + +namespace Hdc { +class HdcDaemonTCP : public HdcTCPBase { +public: + HdcDaemonTCP(const bool serverOrDaemonIn, void *ptrMainBase); + virtual ~HdcDaemonTCP(); + void RecvUDPEntry(const sockaddr *addrSrc, uv_udp_t *handle, const uv_buf_t *rcvbuf); + uint16_t tcpListenPort; + int Initial(); + void Stop(); + +private: + static void AcceptClient(uv_stream_t *server, int status); + void TransmitConfig(const sockaddr *addrSrc, uv_udp_t *handle); + int SetTCPListen(); + void SetUDPListen(); + + uv_tcp_t servTCP; + uv_udp_t servUDP; +}; +} // namespace Hdc + +#endif diff --git a/services/flashd/daemon/daemon_unity.cpp b/services/flashd/daemon/daemon_unity.cpp new file mode 100755 index 00000000..5a4aa067 --- /dev/null +++ b/services/flashd/daemon/daemon_unity.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "daemon_unity.h" +#include +#ifdef __MUSL__ +extern "C" { +#include "init_reboot.h" +} +#endif + +namespace Hdc { +HdcDaemonUnity::HdcDaemonUnity(HTaskInfo hTaskInfo) + : HdcTaskBase(hTaskInfo) +{ + currentDataCommand = CMD_KERNEL_ECHO_RAW; // Default output to shelldata +} + +HdcDaemonUnity::~HdcDaemonUnity() +{ + WRITE_LOG(LOG_DEBUG, "HdcDaemonUnity::~HdcDaemonUnity finish"); +} + +void HdcDaemonUnity::StopTask() +{ + asyncCommand.DoRelease(); +}; + +bool HdcDaemonUnity::ReadyForRelease() +{ + if (!HdcTaskBase::ReadyForRelease() || !asyncCommand.ReadyForRelease()) { + return false; + } + return true; +} + +bool HdcDaemonUnity::AsyncCmdOut(bool finish, int64_t exitStatus, const string result) +{ +#ifdef UNIT_TEST + Base::WriteBinFile((UT_TMP_PATH + "/execute.result").c_str(), (uint8_t *)result.c_str(), result.size(), + countUt++ == 0); +#endif + bool ret = false; + bool wantFinish = false; + do { + if (finish) { + wantFinish = true; + ret = true; + --refCount; + break; + } + if (!SendToAnother(currentDataCommand, (uint8_t *)result.c_str(), result.size())) { + break; + } + ret = true; + } while (false); + if (wantFinish) { + TaskFinish(); + } + return ret; +} + +int HdcDaemonUnity::ExecuteShell(const char *shellCommand) +{ + do { + AsyncCmd::CmdResultCallback funcResultOutput; + funcResultOutput = std::bind(&HdcDaemonUnity::AsyncCmdOut, this, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3); + if (!asyncCommand.Initial(loopTask, funcResultOutput, + asyncCommand.GetDefaultOption() | asyncCommand.OPTION_READBACK_OUT)) { + break; + } + asyncCommand.ExecuteCommand(shellCommand); + ++refCount; + return RET_SUCCESS; + } while (false); + + TaskFinish(); + WRITE_LOG(LOG_DEBUG, "Shell failed finish"); + return -1; +} + +bool HdcDaemonUnity::FindMountDeviceByPath(const char *toQuery, char *dev) +{ + int fd; + int res; + char *token = nullptr; + const char delims[] = "\n"; + char buf[BUF_SIZE_DEFAULT2]; + + fd = open("/proc/mounts", O_RDONLY | O_CLOEXEC); + if (fd < 0) { + return false; + } + read(fd, buf, sizeof(buf) - 1); + close(fd); + buf[sizeof(buf) - 1] = '\0'; + token = strtok(buf, delims); + + while (token) { + char dir[BUF_SIZE_SMALL] = ""; + int freq; + int passnno; + // clang-format off + res = sscanf_s(token, "%255s %255s %*s %*s %d %d\n", dev, BUF_SIZE_SMALL - 1, + dir, BUF_SIZE_SMALL - 1, &freq, &passnno); + // clang-format on + dev[BUF_SIZE_SMALL - 1] = '\0'; + dir[BUF_SIZE_SMALL - 1] = '\0'; + if (res == 4 && (strcmp(toQuery, dir) == 0)) { // 4 : The correct number of parameters + return true; + } + token = strtok(nullptr, delims); + } + return false; +} + +bool HdcDaemonUnity::RemountPartition(const char *dir) +{ + int fd; + int off = 0; + char dev[BUF_SIZE_SMALL] = ""; + + if (!FindMountDeviceByPath(dir, dev) || strlen(dev) < 4) { // 4 : file count + WRITE_LOG(LOG_DEBUG, "FindMountDeviceByPath failed"); + return false; + } + + if ((fd = open(dev, O_RDONLY | O_CLOEXEC)) < 0) { + WRITE_LOG(LOG_DEBUG, "Open device:%s failed, error:%d", dev, errno); + return false; + } + ioctl(fd, BLKROSET, &off); + close(fd); + + if (mount(dev, dir, "none", MS_REMOUNT, nullptr) < 0) { + WRITE_LOG(LOG_DEBUG, "Mount device failed"); + return false; + } + return true; +} + +bool HdcDaemonUnity::RemountDevice() +{ + if (getuid() != 0) { + LogMsg(MSG_FAIL, "Opearte need running as root"); + return false; + } + struct stat info; + if (!lstat("/vendor", &info) && (info.st_mode & S_IFMT) == S_IFDIR) { + // has vendor + if (!RemountPartition("/vendor")) { + LogMsg(MSG_FAIL, "Mount failed"); + return false; + } + } + if (!lstat("/data", &info) && (info.st_mode & S_IFMT) == S_IFDIR) { + if (!RemountPartition("/data")) { + return false; + } + } + LogMsg(MSG_OK, "Mount finish"); + return true; +} + +bool HdcDaemonUnity::RebootDevice(const string &cmd) +{ + sync(); +#ifndef __MUSL__ + string propertyVal; + if (!cmd.size()) { + propertyVal = "reboot"; + } else { + propertyVal = Base::StringFormat("reboot,%s", cmd.c_str()); + } + return Base::SetHdcProperty(rebootProperty.c_str(), propertyVal.c_str()); +#else + string reason; + if (cmd == "recovery") { + reason = "updater"; + } else if (cmd == "bootloader") { + reason = "NoArgument"; + } else { + reason = cmd; + } + return DoReboot(reason.c_str()); +#endif +} + +bool HdcDaemonUnity::SetDeviceRunMode(void *daemonIn, const char *cmd) +{ + HdcDaemon *daemon = (HdcDaemon *)daemonIn; + WRITE_LOG(LOG_DEBUG, "Set run mode:%s", cmd); + if (!strcmp(CMDSTR_TMODE_USB.c_str(), cmd)) { + Base::SetHdcProperty("persist.hdc.mode", CMDSTR_TMODE_USB.c_str()); + } else if (!strncmp("port", cmd, strlen("port"))) { + Base::SetHdcProperty("persist.hdc.mode", CMDSTR_TMODE_TCP.c_str()); + if (!strncmp("port ", cmd, strlen("port "))) { + const char *port = cmd + 5; + Base::SetHdcProperty("persist.hdc.port", port); + } + } else { + LogMsg(MSG_FAIL, "Unknow command"); + return false; + } + // shutdown + daemon->PostStopInstanceMessage(true); + LogMsg(MSG_OK, "Set device run mode successful."); + return true; +} + +inline bool HdcDaemonUnity::GetHiLog(const char *cmd) +{ + string cmdDo = "hilog"; + if (cmd && !strcmp((char *)cmd, "v")) { + cmdDo += " -v long"; + } + ExecuteShell(cmdDo.c_str()); + return true; +} + +inline bool HdcDaemonUnity::ListJdwpProcess(void *daemonIn) +{ + HdcDaemon *daemon = (HdcDaemon *)daemonIn; + string result = ((HdcJdwp *)daemon->clsJdwp)->GetProcessList(); + if (!result.size()) { + result = EMPTY_ECHO; + } else { + result.erase(result.end() - 1); // remove tail \n + } + LogMsg(MSG_OK, result.c_str()); + return true; +} + +bool HdcDaemonUnity::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ + bool ret = true; + HdcDaemon *daemon = (HdcDaemon *)taskInfo->ownerSessionClass; + // Both are not executed, do not need to be detected 'childReady' + string strPayload = string((char *)payload, payloadSize); + switch (command) { + case CMD_UNITY_EXECUTE: { + ExecuteShell((char *)strPayload.c_str()); + break; + } + case CMD_UNITY_REMOUNT: { + ret = false; + RemountDevice(); + break; + } + case CMD_UNITY_REBOOT: { + ret = false; + RebootDevice(strPayload); + break; + } + case CMD_UNITY_RUNMODE: { + ret = false; + SetDeviceRunMode(daemon, strPayload.c_str()); + break; + } + case CMD_UNITY_HILOG: { + GetHiLog(strPayload.c_str()); + break; + } + case CMD_UNITY_ROOTRUN: { + ret = false; + if (payloadSize != 0 && !strcmp((char *)strPayload.c_str(), "r")) { + Base::SetHdcProperty("persist.hdc.root", "0"); + } else { + Base::SetHdcProperty("persist.hdc.root", "1"); + } + daemon->PostStopInstanceMessage(true); + break; + } + case CMD_UNITY_TERMINATE: { + daemon->PostStopInstanceMessage(!strcmp((char *)strPayload.c_str(), "1")); + break; + } + case CMD_UNITY_BUGREPORT_INIT: { + currentDataCommand = CMD_UNITY_BUGREPORT_DATA; + ExecuteShell((char *)CMDSTR_BUGREPORT.c_str()); + break; + } + case CMD_UNITY_JPID: { + ret = false; + ListJdwpProcess(daemon); + break; + } + default: + break; + } + return ret; +}; +} // namespace Hdc diff --git a/services/flashd/daemon/daemon_unity.h b/services/flashd/daemon/daemon_unity.h new file mode 100755 index 00000000..c816487f --- /dev/null +++ b/services/flashd/daemon/daemon_unity.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_DAEMON_UNITY_H +#define HDC_DAEMON_UNITY_H +#include "daemon_common.h" + +namespace Hdc { +class HdcDaemonUnity : public HdcTaskBase { +public: + HdcDaemonUnity(HTaskInfo hTaskInfo); + virtual ~HdcDaemonUnity(); + bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); + void StopTask(); + bool ReadyForRelease(); + +private: + static void OnFdRead(uv_fs_t *req); + int ExecuteShell(const char *shellCommand); + bool FindMountDeviceByPath(const char *toQuery, char *dev); + bool RemountPartition(const char *dir); + bool RemountDevice(); + bool RebootDevice(const string &cmd); + bool SetDeviceRunMode(void *daemonIn, const char *cmd); + bool GetHiLog(const char *cmd); + bool ListJdwpProcess(void *daemonIn); + bool AsyncCmdOut(bool finish, int64_t exitStatus, const string result); + + const string rebootProperty = "sys.powerctl"; + AsyncCmd asyncCommand; + uint16_t currentDataCommand; +#ifdef UNIT_TEST + int countUt = 0; +#endif +}; +} // namespace Hdc +#endif // HDC_DAEMON_UNITY_H diff --git a/services/flashd/daemon/daemon_usb.cpp b/services/flashd/daemon/daemon_usb.cpp new file mode 100755 index 00000000..6f5a33b6 --- /dev/null +++ b/services/flashd/daemon/daemon_usb.cpp @@ -0,0 +1,498 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "daemon_usb.h" +#include "usb_ffs.h" + +namespace Hdc { +HdcDaemonUSB::HdcDaemonUSB(const bool serverOrDaemonIn, void *ptrMainBase) + : HdcUSBBase(serverOrDaemonIn, ptrMainBase) +{ + Base::ZeroStruct(sendEP); + Base::ZeroStruct(usbHandle); + uv_mutex_init(&sendEP); +} + +HdcDaemonUSB::~HdcDaemonUSB() +{ + // Closed in the IO loop, no longer closing CLOSE ENDPOINT + uv_mutex_destroy(&sendEP); + if (controlEp > 0) { + close(controlEp); + } +} + +void HdcDaemonUSB::Stop() +{ + WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB Stop"); + // Here only clean up the IO-related resources, session related resources clear reason to clean up the session + // module + modRunning = false; + WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB Stop free main session"); + Base::TryCloseHandle((uv_handle_t *)&checkEP); + CloseEndpoint(&usbHandle); + WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB Stop free main session finish"); +} + +string HdcDaemonUSB::GetDevPath(const std::string &path) +{ + DIR *dir = ::opendir(path.c_str()); + if (dir == nullptr) { + WRITE_LOG(LOG_WARN, "%s: cannot open devpath: errno: %d", path.c_str(), errno); + return ""; + } + + string res = USB_FFS_BASE; + string node; + int count = 0; + struct dirent *entry = nullptr; + while ((entry = ::readdir(dir))) { + if (*entry->d_name == '.') { + continue; + } + node = entry->d_name; + ++count; + } + if (count > 1) { + res += "hdc"; + } else { + res += node; + } + ::closedir(dir); + return res; +} + +int HdcDaemonUSB::Initial() +{ + // after Linux-3.8,kernel switch to the USB Function FS + // Implement USB hdc function in user space + WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB init"); + basePath = GetDevPath(USB_FFS_BASE); + if (access((basePath + "/ep0").c_str(), F_OK) != 0) { + WRITE_LOG(LOG_DEBUG, "Only support usb-ffs, make sure kernel3.8+ and usb-ffs enabled, usbmode disabled"); + return -1; + } + HdcDaemon *daemon = (HdcDaemon *)clsMainBase; + WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB::Initiall"); + uv_timer_init(&daemon->loopMain, &checkEP); + checkEP.data = this; + uv_timer_start(&checkEP, WatchEPTimer, 0, TIME_BASE); + return 0; +} + +// DAEMON end USB module USB-FFS EP port connection +int HdcDaemonUSB::ConnectEPPoint(HUSB hUSB) +{ + int ret = ERR_GENERIC; + while (true) { + if (controlEp <= 0) { + // After the control port sends the instruction, the device is initialized by the device to the HOST host, + // which can be found for USB devices. Do not send initialization to the EP0 control port, the USB + // device will not be initialized by Host + WRITE_LOG(LOG_DEBUG, "Begin send to control(EP0) for usb descriptor init"); + string ep0Path = basePath + "/ep0"; + if ((controlEp = open(ep0Path.c_str(), O_RDWR)) < 0) { + WRITE_LOG(LOG_WARN, "%s: cannot open control endpoint: errno=%d", ep0Path.c_str(), errno); + break; + } + if (write(controlEp, &USB_FFS_DESC, sizeof(USB_FFS_DESC)) < 0) { + WRITE_LOG(LOG_WARN, "%s: write ffs configs failed: errno=%d", ep0Path.c_str(), errno); + break; + } + if (write(controlEp, &USB_FFS_VALUE, sizeof(USB_FFS_VALUE)) < 0) { + WRITE_LOG(LOG_WARN, "%s: write USB_FFS_VALUE failed: errno=%d", ep0Path.c_str(), errno); + break; + } + // active usbrc,Send USB initialization singal + Base::SetHdcProperty("sys.usb.ffs.ready", "1"); + WRITE_LOG(LOG_DEBUG, "ConnectEPPoint ctrl init finish, set usb-ffs ready"); + } + string outPath = basePath + "/ep1"; + if ((hUSB->bulkOut = open(outPath.c_str(), O_RDWR)) < 0) { + WRITE_LOG(LOG_WARN, "%s: cannot open bulk-out ep: errno=%d", outPath.c_str(), errno); + break; + } + string inPath = basePath + "/ep2"; + if ((hUSB->bulkIn = open(inPath.c_str(), O_RDWR)) < 0) { + WRITE_LOG(LOG_WARN, "%s: cannot open bulk-in ep: errno=%d", inPath.c_str(), errno); + break; + } + // cannot open with O_CLOEXEC, must fcntl + fcntl(controlEp, F_SETFD, FD_CLOEXEC); + fcntl(hUSB->bulkOut, F_SETFD, FD_CLOEXEC); + fcntl(hUSB->bulkIn, F_SETFD, FD_CLOEXEC); + + WRITE_LOG(LOG_DEBUG, "New bulk in\\out open bulkout:%d bulkin:%d", hUSB->bulkOut, hUSB->bulkIn); + hUSB->bufRecv.clear(); + ret = RET_SUCCESS; + break; + } + if (ret != RET_SUCCESS) { + CloseEndpoint(hUSB, true); + } + return ret; +} + +void HdcDaemonUSB::CloseEndpoint(HUSB hUSB, bool closeCtrlEp) +{ + if (hUSB->bulkIn > 0) { + close(hUSB->bulkIn); + hUSB->bulkIn = 0; + } + if (hUSB->bulkOut > 0) { + close(hUSB->bulkOut); + hUSB->bulkOut = 0; + } + if (controlEp > 0 && closeCtrlEp) { + close(controlEp); + controlEp = 0; + } + isAlive = false; + WRITE_LOG(LOG_FATAL, "DaemonUSB close endpoint"); +} + +void HdcDaemonUSB::ResetOldSession(const uint32_t sessionId) +{ + HdcDaemon *daemon = reinterpret_cast(clsMainBase); + HSession hSession = daemon->AdminSession(OP_QUERY, sessionId, nullptr); + if (hSession == nullptr) { + return; + } + hSession->hUSB->resetIO = true; + // The Host side is restarted, but the USB cable is still connected + WRITE_LOG(LOG_WARN, "Hostside softreset to restart daemon, old sessionId:%u", sessionId); + daemon->PushAsyncMessage(sessionId, ASYNC_FREE_SESSION, nullptr, 0); +} + +// Prevent other USB data misfortunes to send the program crash +int HdcDaemonUSB::AvailablePacket(uint8_t *ioBuf, uint32_t *sessionId) +{ + int ret = RET_SUCCESS; + constexpr auto maxBufFactor = 1.2; + while (true) { + struct USBHead *usbPayloadHeader = (struct USBHead *)ioBuf; + if (memcmp(usbPayloadHeader->flag, PACKET_FLAG.c_str(), PACKET_FLAG.size())) { + ret = ERR_BUF_CHECK; + break; + } + if (usbPayloadHeader->dataSize > MAX_SIZE_IOBUF * maxBufFactor + sizeof(USBHead)) { + ret = ERR_BUF_SIZE; + break; + } + if ((usbPayloadHeader->option & USB_OPTION_RESET)) { + ResetOldSession(usbPayloadHeader->sessionId); + ret = ERR_IO_SOFT_RESET; + break; + } + *sessionId = usbPayloadHeader->sessionId; + break; + } + return ret; +} + +// Work in subcrete,Work thread is ready +bool HdcDaemonUSB::ReadyForWorkThread(HSession hSession) +{ + HdcUSBBase::ReadyForWorkThread(hSession); + return true; +}; + +int HdcDaemonUSB::CloseBulkEp(bool bulkInOut, int bulkFd, uv_loop_t *loop) +{ + struct CtxCloseBulkEp { + uv_fs_t req; + HdcDaemonUSB *thisClass; + bool bulkInOut; + }; + CtxCloseBulkEp *ctx = new CtxCloseBulkEp(); + uv_fs_t *req = &ctx->req; + req->data = ctx; + ctx->bulkInOut = bulkInOut; + ctx->thisClass = this; + isAlive = false; + uv_fs_close(loop, req, bulkFd, [](uv_fs_t *req) { + auto ctx = (CtxCloseBulkEp *)req->data; + if (ctx->bulkInOut) { + ctx->thisClass->usbHandle.bulkIn = 0; + } else { + ctx->thisClass->usbHandle.bulkOut = 0; + } + WRITE_LOG(LOG_DEBUG, "Try to abort blukin write callback %s", ctx->bulkInOut ? "bulkin" : "bulkout"); + uv_fs_req_cleanup(req); + delete ctx; + }); + return 0; +} + +int HdcDaemonUSB::SendUSBIOSync(HSession hSession, HUSB hMainUSB, const uint8_t *data, const int length) +{ + int bulkIn = hMainUSB->bulkIn; + int childRet = 0; + int ret = ERR_IO_FAIL; + int offset = 0; + while (modRunning && isAlive && !hSession->isDead && !hSession->hUSB->resetIO) { + childRet = write(bulkIn, (uint8_t *)data + offset, length - offset); + if (childRet <= 0) { + int err = errno; + if (err == EINTR) { + WRITE_LOG(LOG_DEBUG, "BulkinWrite write EINTR, try again"); + continue; + } else { + WRITE_LOG(LOG_FATAL, "BulkinWrite write fatal errno %d", err); + isAlive = false; + } + break; + } + offset += childRet; + if (offset >= length) { + break; + } + } + if (offset == length) { + ret = length; + } else { + WRITE_LOG(LOG_FATAL, + "BulkinWrite write failed, nsize:%d really:%d modRunning:%d isAlive:%d SessionDead:%d usbReset:%d", + length, offset, modRunning, isAlive, hSession->isDead, hSession->hUSB->resetIO); + } + USBHead *pUSBHead = (USBHead *)data; + if ((pUSBHead->option & USB_OPTION_TAIL) || ret < 0) { + // tail or failed, dec Ref + hSession->sendRef--; + } + return ret; +} + +int HdcDaemonUSB::SendUSBRaw(HSession hSession, uint8_t *data, const int length) +{ + HdcDaemon *daemon = (HdcDaemon *)hSession->classInstance; + // Prevent memory stacking, send temporary way to use asynchronous + // Generally sent in the same thread, but when new session is created, there is a possibility that the old session + // is not retired. + // At present, the radical transmission method is currently opened directly in various threads, and + // it can be used exclusive File-DESC transmission mode in each thread. The late stage can be used as asynchronous + + // SendPipe to the main thread transmission. + uv_mutex_lock(&sendEP); + int ret = SendUSBIOSync(hSession, &usbHandle, data, length); + if (ret < 0) { + daemon->FreeSession(hSession->sessionId); + WRITE_LOG(LOG_DEBUG, "SendUSBRaw try to freesession"); + } + uv_mutex_unlock(&sendEP); + return ret; +} + +// cross thread call +void HdcDaemonUSB::OnNewHandshakeOK(const uint32_t sessionId) +{ + currentSessionId = sessionId; // real Id +} + +HSession HdcDaemonUSB::PrepareNewSession(uint32_t sessionId, uint8_t *pRecvBuf, int recvBytesIO) +{ + HdcDaemon *daemon = reinterpret_cast(clsMainBase); + HSession hChildSession = daemon->MallocSession(false, CONN_USB, this, sessionId); + if (!hChildSession) { + return nullptr; + } + if (currentSessionId != 0) { + // reset old session + // The Host side is restarted, but the USB cable is still connected + WRITE_LOG(LOG_WARN, "New session coming, restart old sessionId:%u", currentSessionId); + daemon->PushAsyncMessage(currentSessionId, ASYNC_FREE_SESSION, nullptr, 0); + } + Base::StartWorkThread(&daemon->loopMain, daemon->SessionWorkThread, Base::FinishWorkThread, hChildSession); + auto funcNewSessionUp = [](uv_timer_t *handle) -> void { + HSession hChildSession = reinterpret_cast(handle->data); + HdcDaemon *daemon = reinterpret_cast(hChildSession->classInstance); + if (hChildSession->childLoop.active_handles == 0) { + return; + } + if (!hChildSession->isDead) { + auto ctrl = daemon->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0); + Base::SendToStream((uv_stream_t *)&hChildSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); + WRITE_LOG(LOG_DEBUG, "Main thread usbio mirgate finish"); + } + Base::TryCloseHandle(reinterpret_cast(handle), Base::CloseTimerCallback); + }; + Base::TimerUvTask(&daemon->loopMain, hChildSession, funcNewSessionUp); + return hChildSession; +} + +int HdcDaemonUSB::DispatchToWorkThread(const uint32_t sessionId, uint8_t *readBuf, int readBytes) +{ + // Format:USBPacket1 payload1...USBPacketn + // payloadn-[USBHead1(PayloadHead1+Payload1)]+[USBHead2(Payload2)]+...+[USBHeadN(PayloadN)] + HSession hChildSession = nullptr; + HdcDaemon *daemon = reinterpret_cast(clsMainBase); + hChildSession = daemon->AdminSession(OP_QUERY, sessionId, nullptr); + if (!hChildSession) { + hChildSession = PrepareNewSession(sessionId, readBuf, readBytes); + if (!hChildSession) { + return ERR_SESSION_NOFOUND; + } + } + if (hChildSession->childCleared) { + return ERR_SESSION_DEAD; + } + if (SendToHdcStream(hChildSession, reinterpret_cast(&hChildSession->dataPipe[STREAM_MAIN]), readBuf, + readBytes) + != RET_SUCCESS) { + return ERR_IO_FAIL; + } + return readBytes; +} + +bool HdcDaemonUSB::JumpAntiquePacket(const uint8_t &buf, ssize_t bytes) const +{ + constexpr size_t antiqueFlagSize = 4; + constexpr size_t antiqueFullSize = 24; + // anti CNXN 0x4e584e43 + uint8_t flag[] = { 0x43, 0x4e, 0x58, 0x4e }; + if (bytes == antiqueFullSize && !memcmp(&buf, flag, antiqueFlagSize)) { + return true; + } + return false; +} + +// Only physically swap EP ports will be reset +void HdcDaemonUSB::OnUSBRead(uv_fs_t *req) +{ // Only read at the main thread + auto ctxIo = reinterpret_cast(req->data); + auto hUSB = reinterpret_cast(ctxIo->data); + auto thisClass = reinterpret_cast(ctxIo->thisClass); + uint8_t *bufPtr = ctxIo->buf; + ssize_t bytesIOBytes = req->result; + uint32_t sessionId = 0; + bool ret = false; + int childRet = 0; + --thisClass->ref; + while (thisClass->isAlive) { + // Don't care is module running, first deal with this + if (bytesIOBytes < 0) { + WRITE_LOG(LOG_WARN, "USBIO failed1 %s", uv_strerror(bytesIOBytes)); + break; + } else if (bytesIOBytes == 0) { + // zero packet + ret = true; + break; + } + if (thisClass->JumpAntiquePacket(*bufPtr, bytesIOBytes)) { + WRITE_LOG(LOG_DEBUG, "JumpAntiquePacket auto jump"); + ret = true; + break; + } + // guess is head of packet + if ((childRet = thisClass->AvailablePacket((uint8_t *)bufPtr, &sessionId)) != RET_SUCCESS) { + if (childRet != ERR_IO_SOFT_RESET) { + WRITE_LOG(LOG_WARN, "AvailablePacket check failed, ret:%d buf:%-50s", bytesIOBytes, bufPtr); + break; + } + // reset packet + } else { + // AvailablePacket case + if (thisClass->DispatchToWorkThread(sessionId, bufPtr, bytesIOBytes) < 0) { + WRITE_LOG(LOG_FATAL, "DispatchToWorkThread failed"); + break; + } + } + if (thisClass->LoopUSBRead(hUSB) < 0) { + WRITE_LOG(LOG_FATAL, "LoopUSBRead failed"); + break; + } + ret = true; + break; + } + if (!ret) { + thisClass->isAlive = false; + } + delete[] ctxIo->buf; + uv_fs_req_cleanup(req); + delete ctxIo; +} + +int HdcDaemonUSB::LoopUSBRead(HUSB hUSB) +{ + int ret = -1; + HdcDaemon *daemon = reinterpret_cast(clsMainBase); + // must > available size, or it will be incorrect + int readMax = Base::GetMaxBufSize() + sizeof(USBHead) + EXTRA_ALLOC_SIZE; + auto ctxIo = new CtxUvFileCommonIo(); + auto buf = new uint8_t[readMax](); + uv_fs_t *req = nullptr; + uv_buf_t iov; + if (ctxIo == nullptr || buf == nullptr) { + goto FAILED; + } + ctxIo->buf = buf; + ctxIo->bufSize = readMax; + ctxIo->data = hUSB; + ctxIo->thisClass = this; + req = &ctxIo->req; + req->data = ctxIo; + iov = uv_buf_init(reinterpret_cast(ctxIo->buf), ctxIo->bufSize); + ret = uv_fs_read(&daemon->loopMain, req, hUSB->bulkOut, &iov, 1, -1, OnUSBRead); + if (ret < 0) { + WRITE_LOG(LOG_FATAL, "uv_fs_read < 0"); + goto FAILED; + } + ++this->ref; + return 0; +FAILED: + if (ctxIo != nullptr) { + delete ctxIo; + } + if (buf != nullptr) { + delete[] buf; + } + return -1; +} + +// Because USB can connect to only one host,daemonUSB is only one Session by default +void HdcDaemonUSB::WatchEPTimer(uv_timer_t *handle) +{ + HdcDaemonUSB *thisClass = (HdcDaemonUSB *)handle->data; + HUSB hUSB = &thisClass->usbHandle; + HdcDaemon *daemon = reinterpret_cast(thisClass->clsMainBase); + if (thisClass->isAlive || thisClass->ref > 0) { + return; + } + bool resetEp = false; + do { + if (hUSB->bulkIn > 0) { + thisClass->CloseBulkEp(true, thisClass->usbHandle.bulkIn, &daemon->loopMain); + resetEp = true; + } + if (hUSB->bulkOut > 0) { + thisClass->CloseBulkEp(false, thisClass->usbHandle.bulkOut, &daemon->loopMain); + resetEp = true; + } + if (thisClass->controlEp > 0) { + close(thisClass->controlEp); + thisClass->controlEp = 0; + resetEp = true; + } + } while (false); + if (resetEp || thisClass->usbHandle.bulkIn != 0 || thisClass->usbHandle.bulkOut != 0) { + return; + } + // until all bulkport reset + if (thisClass->ConnectEPPoint(hUSB) != RET_SUCCESS) { + return; + } + // connect OK + thisClass->isAlive = true; + thisClass->LoopUSBRead(hUSB); +} +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/daemon/daemon_usb.h b/services/flashd/daemon/daemon_usb.h new file mode 100755 index 00000000..38dc5244 --- /dev/null +++ b/services/flashd/daemon/daemon_usb.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_DAEMON_USB_H +#define HDC_DAEMON_USB_H +#include "daemon_common.h" + +namespace Hdc { +class HdcDaemonUSB : public HdcUSBBase { +public: + HdcDaemonUSB(const bool serverOrDaemonIn, void *ptrMainBase); + virtual ~HdcDaemonUSB(); + int Initial(); + void Stop(); + int SendUSBRaw(HSession hSession, uint8_t *data, const int length); + void OnNewHandshakeOK(const uint32_t sessionId); + +private: + struct CtxUvFileCommonIo { + uv_fs_t req; + uint8_t *buf; + int bufSize; + void *thisClass; + void *data; + }; + static void OnUSBRead(uv_fs_t *req); + static void WatchEPTimer(uv_timer_t *handle); + int ConnectEPPoint(HUSB hUSB); + int DispatchToWorkThread(const uint32_t sessionId, uint8_t *readBuf, int readBytes); + int AvailablePacket(uint8_t *ioBuf, uint32_t *sessionId); + void CloseEndpoint(HUSB hUSB, bool closeCtrlEp = false); + string GetDevPath(const std::string &path); + bool ReadyForWorkThread(HSession hSession); + int LoopUSBRead(HUSB hUSB); + HSession PrepareNewSession(uint32_t sessionId, uint8_t *pRecvBuf, int recvBytesIO); + bool JumpAntiquePacket(const uint8_t &buf, ssize_t bytes) const; + int SendUSBIOSync(HSession hSession, HUSB hMainUSB, const uint8_t *data, const int length); + int CloseBulkEp(bool bulkInOut, int bulkFd, uv_loop_t *loop); + void ResetOldSession(const uint32_t sessionId); + + HdcUSB usbHandle; + string basePath; // usb device's base path + uint32_t currentSessionId = 0; // USB mode,limit only one session + std::atomic ref = 0; + uv_timer_t checkEP; // server-use + uv_mutex_t sendEP; + bool isAlive = false; + int controlEp = 0; // EP0 +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/daemon/flashd_main.cpp b/services/flashd/daemon/flashd_main.cpp index 18d8ebd6..56e801b8 100755 --- a/services/flashd/daemon/flashd_main.cpp +++ b/services/flashd/daemon/flashd_main.cpp @@ -24,13 +24,18 @@ int flashd_main(int argc, char **argv) std::vector args = updater::ParseParams(argc, argv); bool enableUsb = false; bool enableTcp = false; + WRITE_LOG(LOG_DEBUG, "flashd main run %d", argc); + const int size = 64; + char modeSet[size] = ""; + Base::GetHdcProperty("persist.hdc.mode", modeSet, size); + WRITE_LOG(LOG_DEBUG, "Background mode, persist.hdc.mode %s", modeSet); for (std::string arg : args) { if (arg.find("-l") != std::string::npos) { int logLevel = atoi(arg.c_str() + strlen("-l")); FLASHDAEMON_CHECK(!(logLevel < 0 || logLevel > LOG_LAST), logLevel = LOG_LAST, "Loglevel error %d", logLevel); Base::SetLogLevel(logLevel); - } else if (arg.find("-t") != std::string::npos) { + } else if (arg.find("-t") != std::string::npos || strncmp(modeSet, "tcp", 3) == 0) { // 3 tcp enableTcp = true; } else if (arg.find("-u") != std::string::npos) { enableUsb = true; @@ -41,8 +46,6 @@ int flashd_main(int argc, char **argv) Base::PrintMessage("Both TCP and USB are disable, default enable usb"); enableUsb = true; } - - WRITE_LOG(LOG_DEBUG, "flashd main run"); HdcDaemon daemon(false); daemon.InitMod(enableTcp, enableUsb); #ifndef UPDATER_UT diff --git a/services/flashd/daemon/jdwp.cpp b/services/flashd/daemon/jdwp.cpp new file mode 100755 index 00000000..7a3b1526 --- /dev/null +++ b/services/flashd/daemon/jdwp.cpp @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "jdwp.h" + +namespace Hdc { +HdcJdwp::HdcJdwp(uv_loop_t *loopIn) +{ + Base::ZeroStruct(listenPipe); + listenPipe.data = this; + loop = loopIn; + refCount = 0; + uv_rwlock_init(&lockMapContext); +} + +HdcJdwp::~HdcJdwp() +{ + uv_rwlock_destroy(&lockMapContext); +} + +bool HdcJdwp::ReadyForRelease() +{ + return refCount == 0; +} + +void HdcJdwp::Stop() +{ + auto funcListenPipeClose = [](uv_handle_t *handle) -> void { + HdcJdwp *thisClass = (HdcJdwp *)handle->data; + --thisClass->refCount; + }; + Base::TryCloseHandle((const uv_handle_t *)&listenPipe, funcListenPipeClose); + for (auto &&obj : mapCtxJdwp) { + HCtxJdwp v = obj.second; + FreeContext(v); + } + AdminContext(OP_CLEAR, 0, nullptr); +} + +void *HdcJdwp::MallocContext() +{ + HCtxJdwp ctx = nullptr; + if ((ctx = new ContextJdwp()) == nullptr) { + return nullptr; + } + ctx->thisClass = this; + ctx->pipe.data = ctx; + ++refCount; + return ctx; +} + +// Single thread, two parameters can be used +void HdcJdwp::FreeContext(HCtxJdwp ctx) +{ + if (ctx->finish) { + return; + } + Base::TryCloseHandle((const uv_handle_t *)&ctx->pipe); + ctx->finish = true; + AdminContext(OP_REMOVE, ctx->pid, nullptr); + auto funcReqClose = [](uv_idle_t *handle) -> void { + HCtxJdwp ctx = (HCtxJdwp)handle->data; + --ctx->thisClass->refCount; + Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseIdleCallback); + delete ctx; + }; + Base::IdleUvTask(loop, ctx, funcReqClose); +} + +void HdcJdwp::ReadStream(uv_stream_t *pipe, ssize_t nread, const uv_buf_t *buf) +{ + bool ret = true; + HCtxJdwp ctxJdwp = (HCtxJdwp)pipe->data; + HdcJdwp *thisClass = (HdcJdwp *)ctxJdwp->thisClass; + char *p = ctxJdwp->buf; + uint32_t pid = 0; + + if (nread == UV_ENOBUFS) { // It is definite enough, usually only 4 bytes + ret = false; + WRITE_LOG(LOG_DEBUG, "HdcJdwp::ReadStream IOBuf max"); + } else if (nread == 0) { + return; + } else if (nread < 0 || nread != 4) { // 4 : 4 bytes + ret = false; + WRITE_LOG(LOG_DEBUG, "HdcJdwp::ReadStream program exit pid:%d", ctxJdwp->pid); + } + if (ret) { + pid = atoi(p); + if (pid > 0) { + WRITE_LOG(LOG_DEBUG, "JDWP accept pid:%d", pid); + ctxJdwp->pid = pid; + thisClass->AdminContext(OP_ADD, pid, ctxJdwp); + ret = true; + } + } + Base::ZeroArray(ctxJdwp->buf); + if (!ret) { + thisClass->FreeContext(ctxJdwp); + } +} + +void HdcJdwp::AcceptClient(uv_stream_t *server, int status) +{ + uv_pipe_t *listenPipe = (uv_pipe_t *)server; + HdcJdwp *thisClass = (HdcJdwp *)listenPipe->data; + HCtxJdwp ctxJdwp = (HCtxJdwp)thisClass->MallocContext(); + if (!ctxJdwp) { + return; + } + uv_pipe_init(thisClass->loop, &ctxJdwp->pipe, 1); + if (uv_accept(server, (uv_stream_t *)&ctxJdwp->pipe) < 0) { + WRITE_LOG(LOG_DEBUG, "uv_accept failed"); + thisClass->FreeContext(ctxJdwp); + return; + } + auto funAlloc = [](uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf) -> void { + HCtxJdwp ctxJdwp = (HCtxJdwp)handle->data; + buf->base = (char *)ctxJdwp->buf ; + buf->len = sizeof(ctxJdwp->buf); + }; + uv_read_start((uv_stream_t *)&ctxJdwp->pipe, funAlloc, ReadStream); +} + +// Test bash connnet(UNIX-domain sockets):nc -U path/jdwp-control < hexpid.file +// Test uv connect(pipe): 'uv_pipe_connect' +bool HdcJdwp::JdwpListen() +{ +#ifdef HDC_PCDEBUG + // if test, canbe enable + return true; + const char jdwpCtrlName[] = { 'j', 'd', 'w', 'p', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', 0 }; + unlink(jdwpCtrlName); +#else + const char jdwpCtrlName[] = { '\0', 'j', 'd', 'w', 'p', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', 0 }; +#endif + const int DEFAULT_BACKLOG = 4; + bool ret = false; + while (true) { + uv_pipe_init(loop, &listenPipe, 0); + listenPipe.data = this; + if ((uv_pipe_bind(&listenPipe, jdwpCtrlName))) { + WRITE_LOG(LOG_WARN, "Bind error : %d: %s", errno, strerror(errno)); + return 1; + } + if (uv_listen((uv_stream_t *)&listenPipe, DEFAULT_BACKLOG, AcceptClient)) { + break; + } + ++refCount; + ret = true; + break; + } + // listenPipe close by stop + return ret; +} + +// Working in the main thread, but will be accessed by each session thread, so we need to set thread lock +void *HdcJdwp::AdminContext(const uint8_t op, const uint32_t pid, HCtxJdwp ctxJdwp) +{ + HCtxJdwp hRet = nullptr; + switch (op) { + case OP_ADD: { + uv_rwlock_wrlock(&lockMapContext); + mapCtxJdwp[pid] = ctxJdwp; + uv_rwlock_wrunlock(&lockMapContext); + break; + } + case OP_REMOVE: + uv_rwlock_wrlock(&lockMapContext); + mapCtxJdwp.erase(pid); + uv_rwlock_wrunlock(&lockMapContext); + break; + case OP_QUERY: { + uv_rwlock_rdlock(&lockMapContext); + if (mapCtxJdwp.count(pid)) { + hRet = mapCtxJdwp[pid]; + } + uv_rwlock_rdunlock(&lockMapContext); + break; + } + case OP_CLEAR: { + uv_rwlock_wrlock(&lockMapContext); + mapCtxJdwp.clear(); + uv_rwlock_wrunlock(&lockMapContext); + break; + } + default: + break; + } + return hRet; +} + +// work on main thread +void HdcJdwp::SendCallbackJdwpNewFD(uv_write_t *req, int status) +{ + // It usually works successful, not notify session work + HCtxJdwp ctx = (HCtxJdwp)req->data; + if (status >= 0) { + WRITE_LOG(LOG_DEBUG, "SendCallbackJdwpNewFD successful %d, active jdwp forward", ctx->pid); + } else { + WRITE_LOG(LOG_WARN, "SendCallbackJdwpNewFD failed %d", ctx->pid); + } + // close my process's fd + Base::TryCloseHandle((const uv_handle_t *)&ctx->jvmTCP); + delete req; + --ctx->thisClass->refCount; +} + +// Each session calls the interface through the main thread message queue, which cannot be called directly across +// threads +// work on main thread +bool HdcJdwp::SendJdwpNewFD(uint32_t targetPID, int fd) +{ + bool ret = false; + while (true) { + HCtxJdwp ctx = (HCtxJdwp)AdminContext(OP_QUERY, targetPID, nullptr); + if (!ctx) { + break; + } + ctx->dummy = (uint8_t)'!'; + if (uv_tcp_init(loop, &ctx->jvmTCP)) { + break; + } + if (uv_tcp_open(&ctx->jvmTCP, fd)) { + break; + } + // transfer fd to jvm + // clang-format off + if (Base::SendToStreamEx((uv_stream_t *)&ctx->pipe, (uint8_t *)&ctx->dummy, 1, (uv_stream_t *)&ctx->jvmTCP, + (void *)SendCallbackJdwpNewFD, (const void *)ctx) < 0) { + break; + } + // clang-format on + ++refCount; + ret = true; + WRITE_LOG(LOG_DEBUG, "SendJdwpNewFD successful targetPID:%d fd%d", targetPID, fd); + break; + } + return ret; +} + +// cross thread call begin +bool HdcJdwp::CheckPIDExist(uint32_t targetPID) +{ + HCtxJdwp ctx = (HCtxJdwp)AdminContext(OP_QUERY, targetPID, nullptr); + return ctx != nullptr; +} + +string HdcJdwp::GetProcessList() +{ + string ret; + uv_rwlock_rdlock(&lockMapContext); + for (auto &&v : mapCtxJdwp) { + ret += std::to_string(v.first) + "\n"; + } + uv_rwlock_rdunlock(&lockMapContext); + return ret; +} +// cross thread call finish + +// jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8000 +int HdcJdwp::Initial() +{ + if (!JdwpListen()) { + return ERR_MODULE_JDWP_FAILED; + } + return RET_SUCCESS; +} +} \ No newline at end of file diff --git a/services/flashd/daemon/jdwp.h b/services/flashd/daemon/jdwp.h new file mode 100755 index 00000000..93b3b902 --- /dev/null +++ b/services/flashd/daemon/jdwp.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_JDWP_H +#define HDC_JDWP_H +#include "daemon_common.h" + +namespace Hdc { +class HdcJdwp { +public: + HdcJdwp(uv_loop_t *loopIn); + virtual ~HdcJdwp(); + int Initial(); + void Stop(); + bool ReadyForRelease(); + + string GetProcessList(); + bool SendJdwpNewFD(uint32_t targetPID, int fd); + bool CheckPIDExist(uint32_t targetPID); + +private: + struct ContextJdwp { + uint32_t pid; + uv_pipe_t pipe; + HdcJdwp *thisClass; + bool finish; + char buf[sizeof(uint32_t)]; + uint8_t dummy; + uv_tcp_t jvmTCP; + }; + using HCtxJdwp = struct ContextJdwp *; + + bool JdwpListen(); + static void AcceptClient(uv_stream_t *server, int status); + static void ReadStream(uv_stream_t *pipe, ssize_t nread, const uv_buf_t *buf); + static void SendCallbackJdwpNewFD(uv_write_t *req, int status); + void *MallocContext(); + void FreeContext(HCtxJdwp ctx); + void *AdminContext(const uint8_t op, const uint32_t pid, HCtxJdwp ctxJdwp); + + uv_loop_t *loop; + uv_pipe_t listenPipe; + uint32_t refCount; + map mapCtxJdwp; + uv_rwlock_t lockMapContext; +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/daemon/main.cpp b/services/flashd/daemon/main.cpp new file mode 100755 index 00000000..fcd82e87 --- /dev/null +++ b/services/flashd/daemon/main.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "daemon_common.h" +using namespace Hdc; + +static bool g_enableUsb = false; +static bool g_enableTcp = false; +static bool g_rootRun = false; +static bool g_backgroundRun = false; +namespace Hdc { +bool RestartDaemon(bool forkchild) +{ + char path[256] = ""; + size_t nPathSize = 256; + uv_exepath(path, &nPathSize); + execl(path, "hdcd", forkchild ? "-forkchild" : nullptr, nullptr); + return true; +} + +bool ForkChildCheck(int argc, const char *argv[]) +{ + // hdcd #service start forground + // hdcd -b #service start backgroundRun + // hdcd -fork #fork + char modeSet[BUF_SIZE_TINY] = ""; + Base::GetHdcProperty("persist.hdc.mode", modeSet, BUF_SIZE_TINY); + Base::PrintMessage("Background mode, persist.hdc.mode"); + string workMode = modeSet; + workMode = Base::Trim(workMode); + if (workMode == CMDSTR_TMODE_TCP) { + WRITE_LOG(LOG_DEBUG, "Property enable TCP"); + g_enableTcp = true; + } else if (workMode == CMDSTR_TMODE_USB) { + WRITE_LOG(LOG_DEBUG, "Property enable USB"); + g_enableUsb = true; + } else if (workMode == "all") { + WRITE_LOG(LOG_DEBUG, "Property enable USB and TCP"); + g_enableUsb = true; + g_enableTcp = true; + } else { + WRITE_LOG(LOG_DEBUG, "Default USB mode"); + g_enableUsb = true; + } + if (argc == CMD_ARG1_COUNT) { + if (!strcmp(argv[1], "-forkchild")) { + g_backgroundRun = false; // forkchild,Forced foreground + } else if (!strcmp(argv[1], "-b")) { + g_backgroundRun = true; + } + } + return true; +} + +int BackgroundRun() +{ + pid_t pc = fork(); // create process as daemon process + if (pc < 0) { + return -1; + } else if (!pc) { + int i; + const int MAX_NUM = 64; + for (i = 0; i < MAX_NUM; ++i) { + close(i); + } + RestartDaemon(true); + } else { // >0 orig process + } + return 0; +} + +string DaemonUsage() +{ + string ret; + ret = "\n Harmony device connector daemon(HDCD) Usage: hdcd [options]...\n\n" + "\n" + "general options:\n" + " -h - Print help\n" + " -l 0-5 - Print runtime log\n" + "\n" + "daemon mode options:\n" + " -b - Daemon run in background/fork mode\n" + " -u - Enable USB mode\n" + " -t - Enable TCP mode\n"; + return ret; +} + +bool GetDaemonCommandlineOptions(int argc, const char *argv[]) +{ + int ch; + // hdcd -l4 ... + WRITE_LOG(LOG_DEBUG, "Fgcli mode"); + // Both settings are running with parameters + while ((ch = getopt(argc, (char *const *)argv, "utl:")) != -1) { + switch (ch) { + case 'l': { + int logLevel = atoi(optarg); + if (logLevel < 0 || logLevel > LOG_LAST) { + WRITE_LOG(LOG_DEBUG, "Loglevel error!\n"); + return -1; + } + Base::SetLogLevel(logLevel); + break; + } + case 'u': { + Base::PrintMessage("Option USB enabled"); + g_enableUsb = true; + break; + } + case 't': { + Base::PrintMessage("Option TCP enabled"); + g_enableTcp = true; + break; + } + default: + Base::PrintMessage("Option:%c non-supported!", ch); + exit(0); + break; + } + } + return true; +} + +void NeedDropPriv() +{ + char droprootSet[BUF_SIZE_TINY] = ""; + Base::GetHdcProperty("persist.hdc.root", droprootSet, BUF_SIZE_TINY); + droprootSet[sizeof(droprootSet) - 1] = '\0'; + string rootMode = droprootSet; + if (Base::Trim(rootMode) == "1") { + setuid(0); + g_rootRun = true; + WRITE_LOG(LOG_DEBUG, "Root run"); + } else if (Base::Trim(rootMode) == "0") { + setuid(AID_SHELL); + } +} +} // namespace Hdc + +#ifndef UNIT_TEST +// daemon running with default behavior. options also can be given to custom its behavior including b/t/u/l etc. +int main(int argc, const char *argv[]) +{ + // check property + if (argc == 2 && !strcmp(argv[1], "-h")) { + string usage = DaemonUsage(); + fprintf(stderr, "%s", usage.c_str()); + return 0; + } + if (argc == CMD_ARG1_COUNT && !strcmp(argv[1], "-v")) { + string ver = Hdc::Base::GetVersion(); + fprintf(stderr, "%s\n", ver.c_str()); + return 0; + } + if (argc == 1 || (argc == CMD_ARG1_COUNT && (!strcmp(argv[1], "-forkchild") || !strcmp(argv[1], "-b")))) { + Base::SetLogLevel(LOG_LEVEL_FULL); + ForkChildCheck(argc, argv); + } else { + GetDaemonCommandlineOptions(argc, argv); + } + if (!g_enableTcp && !g_enableUsb) { + Base::PrintMessage("Both TCP and USB are disable, cannot run continue\n"); + return -1; + } + if (g_backgroundRun) { + return BackgroundRun(); + } + NeedDropPriv(); + umask(0); + signal(SIGPIPE, SIG_IGN); + signal(SIGCHLD, SIG_IGN); + WRITE_LOG(LOG_DEBUG, "HdcDaemon main run"); + HdcDaemon daemon(false); + daemon.InitMod(g_enableTcp, g_enableUsb); + daemon.WorkerPendding(); + bool wantRestart = daemon.WantRestart(); + WRITE_LOG(LOG_DEBUG, "Daemon finish"); + // There is no daemon, we can only restart myself. + if (g_rootRun && wantRestart) { + // just root can self restart, low privilege will be exit and start by service(root) + WRITE_LOG(LOG_INFO, "Daemon restart"); + RestartDaemon(false); + } + return 0; +} +#endif diff --git a/services/flashd/daemon/shell.cpp b/services/flashd/daemon/shell.cpp new file mode 100755 index 00000000..8a434221 --- /dev/null +++ b/services/flashd/daemon/shell.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "shell.h" +#include + +namespace Hdc { +std::mutex HdcShell::mutexPty; + +HdcShell::HdcShell(HTaskInfo hTaskInfo) + : HdcTaskBase(hTaskInfo) +{ + childShell = nullptr; + fdPTY = 0; +} + +HdcShell::~HdcShell() +{ + WRITE_LOG(LOG_DEBUG, "HdcShell deinit"); +}; + +bool HdcShell::ReadyForRelease() +{ + if (!HdcTaskBase::ReadyForRelease()) { + return false; + } + if (!childReady) { + return true; + } + if (!childShell->ReadyForRelease()) { + return false; + } + delete childShell; + childShell = nullptr; + if (fdPTY > 0) { + close(fdPTY); + } + return true; +} + +void HdcShell::StopTask() +{ + singalStop = true; + WRITE_LOG(LOG_DEBUG, "HdcShell::StopTask"); + if (!childReady) { + return; + } + if (childShell) { + childShell->StopWork(false, nullptr); + } + kill(pidShell, SIGKILL); + int status; + waitpid(pidShell, &status, 0); + WRITE_LOG(LOG_DEBUG, "StopTask, kill pidshell:%d", pidShell); +}; + +bool HdcShell::SpecialSignal(uint8_t ch) +{ + const uint8_t TXT_SIGNAL_ETX = 0x3; + bool ret = true; + switch (ch) { + case TXT_SIGNAL_ETX: { // Ctrl+C + pid_t tpgid = tcgetpgrp(fdPTY); + kill(tpgid, SIGINT); + break; + } + default: + ret = false; + break; + } + return ret; +} + +bool HdcShell::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ + switch (command) { + case CMD_SHELL_INIT: { // initial + if (StartShell()) { + LogMsg(MSG_FAIL, "Shell initialize failed"); + } + break; + } + case CMD_SHELL_DATA: + if (!childReady) { + WRITE_LOG(LOG_DEBUG, "Shell not running"); + return false; + } + if (payloadSize == 1 && SpecialSignal(payload[0])) { + } else { + childShell->Write(payload, payloadSize); + } + break; + default: + break; + } + return true; +} + +int HdcShell::ChildForkDo(int pts, const char *cmd, const char *arg0, const char *arg1) +{ + dup2(pts, STDIN_FILENO); + dup2(pts, STDOUT_FILENO); + dup2(pts, STDERR_FILENO); + close(pts); + string text = "/proc/self/oom_score_adj"; + int fd = 0; + if ((fd = open(text.c_str(), O_WRONLY)) >= 0) { + write(fd, "0", 1); + close(fd); + } + char *env = nullptr; + if ((env = getenv("HOME")) && chdir(env) < 0) { + } + execl(cmd, cmd, arg0, arg1, nullptr); + _Exit(1); + return 0; +} + +int HdcShell::ShellFork(const char *cmd, const char *arg0, const char *arg1) +{ + pid_t pid; + pid = fork(); + if (pid < 0) { + WRITE_LOG(LOG_DEBUG, "Fork shell failed:%s", strerror(errno)); + return ERR_GENERIC; + } + if (pid == 0) { + HdcShell::mutexPty.unlock(); + setsid(); + close(ptm); + int pts = 0; + if ((pts = open(devname, O_RDWR | O_CLOEXEC)) < 0) { + return -1; + } + ChildForkDo(pts, cmd, arg0, arg1); + // proc finish + } else { + return pid; + } + return 0; +} + +int HdcShell::CreateSubProcessPTY(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) +{ + ptm = open(devPTMX.c_str(), O_RDWR | O_CLOEXEC); + if (ptm < 0) { + WRITE_LOG(LOG_DEBUG, "Cannot open ptmx, error:%s", strerror(errno)); + return ERR_FILE_OPEN; + } + if (grantpt(ptm) || unlockpt(ptm)) { + WRITE_LOG(LOG_DEBUG, "Cannot open2 ptmx, error:%s", strerror(errno)); + close(ptm); + return ERR_API_FAIL; + } + if (ptsname_r(ptm, devname, sizeof(devname)) != 0) { + WRITE_LOG(LOG_DEBUG, "Trouble with ptmx, error:%s", strerror(errno)); + close(ptm); + return ERR_API_FAIL; + } + *pid = ShellFork(cmd, arg0, arg1); + return ptm; +} + +bool HdcShell::FinishShellProc(const void *context, const bool result, const string exitMsg) +{ + WRITE_LOG(LOG_DEBUG, "FinishShellProc finish"); + HdcShell *thisClass = (HdcShell *)context; + thisClass->TaskFinish(); + --thisClass->refCount; + return true; +}; + +bool HdcShell::ChildReadCallback(const void *context, uint8_t *buf, const int size) +{ + HdcShell *thisClass = (HdcShell *)context; + return thisClass->SendToAnother(CMD_KERNEL_ECHO_RAW, (uint8_t *)buf, size); +}; + +int HdcShell::StartShell() +{ + WRITE_LOG(LOG_DEBUG, "StartShell..."); + int ret = 0; + HdcShell::mutexPty.lock(); + do { + if ((fdPTY = CreateSubProcessPTY(Base::GetShellPath().c_str(), "-", 0, &pidShell)) < 0) { + ret = ERR_PROCESS_SUB_FAIL; + break; + } + childShell = new HdcFileDescriptor(loopTask, fdPTY, this, ChildReadCallback, FinishShellProc); + if (!childShell->StartWork()) { + ret = ERR_API_FAIL; + break; + } + childReady = true; + ++refCount; + } while (false); + if (ret != RET_SUCCESS) { + if (pidShell > 0) { + kill(pidShell, SIGKILL); + } + // fdPTY close by ~clase + } + HdcShell::mutexPty.unlock(); + return ret; +} +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/daemon/shell.h b/services/flashd/daemon/shell.h new file mode 100755 index 00000000..1c2cda83 --- /dev/null +++ b/services/flashd/daemon/shell.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_SHELL_H +#define HDC_SHELL_H +#include "daemon_common.h" +#include + +namespace Hdc { +class HdcShell : public HdcTaskBase { +public: + HdcShell(HTaskInfo hTaskInfo); + virtual ~HdcShell(); + bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); + void StopTask(); + bool ReadyForRelease(); + +private: + static bool FinishShellProc(const void *context, const bool result, const string exitMsg); + static bool ChildReadCallback(const void *context, uint8_t *buf, const int size); + int StartShell(); + int CreateSubProcessPTY(const char *cmd, const char *arg0, const char *arg1, pid_t *pid); + int ChildForkDo(int pts, const char *cmd, const char *arg0, const char *arg1); + bool SpecialSignal(uint8_t ch); + int ShellFork(const char *cmd, const char *arg0, const char *arg1); + + HdcFileDescriptor *childShell; + pid_t pidShell = 0; + int fdPTY; + int ptm = 0; + const string devPTMX = "/dev/ptmx"; + static std::mutex mutexPty; + char devname[BUF_SIZE_SMALL] = ""; +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/daemon/usb_ffs.h b/services/flashd/daemon/usb_ffs.h new file mode 100755 index 00000000..1998daaf --- /dev/null +++ b/services/flashd/daemon/usb_ffs.h @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_USBFFS_H +#define HDC_USBFFS_H +// clang-format off +#include +#include "daemon_common.h" +// clang-format on + +namespace Hdc { +constexpr auto HDC_USBDR_SND = 0x0; +constexpr auto HDC_USBDR_RCV = 0x80; +constexpr auto HDC_USBMD_BLK = 0X02; +constexpr auto HDC_USBMD_RCV = 0X03; +constexpr auto HDC_CLASS = 0xff; +constexpr auto HDC_SUBCLASS = 0x50; +constexpr auto HDC_FSPKT_SIZE_MAX = 64; +constexpr auto HDC_HSPKT_SIZE_MAX = 512; +constexpr uint16_t HDC_SSPKT_SIZE_MAX = 1024; +constexpr auto USB_FFS_BASE = "/dev/usb-ffs/"; +constexpr auto HDC_USBTF_DEV = 0x01; +constexpr auto HDC_USBTF_CFG = 0x02; +constexpr auto HDC_USBTF_STR = 0x03; +constexpr auto HDC_USBTF_ITF = 0x04; +constexpr auto HDC_USBTF_EPS = 0x05; + +#define SHORT_LE(x) htole16(x) +#define LONG_LE(x) htole32(x) +#define HDC_INTERFACE_NAME "HDC Interface" + +struct UsbFunctionDesc { + struct usb_interface_descriptor ifDesc; + struct usb_endpoint_descriptor_no_audio from; + struct usb_endpoint_descriptor_no_audio to; +} __attribute__((packed)); + +static const struct { + struct usb_functionfs_strings_head head; + struct { + __le16 code; + const char name[sizeof(HDC_INTERFACE_NAME)]; + } __attribute__((packed)) firstItem; +} __attribute__((packed)) USB_FFS_VALUE = { + .head = + { + .magic = LONG_LE(FUNCTIONFS_STRINGS_MAGIC), + .length = LONG_LE(sizeof(USB_FFS_VALUE)), + .str_count = LONG_LE(1), + .lang_count = LONG_LE(1), + }, + .firstItem = + { + SHORT_LE(0x0409), + HDC_INTERFACE_NAME, + }, +}; + +struct UsbFunctionfsDescsHeadOld { + __le32 magic; + __le32 length; + __le32 config1Count; + __le32 config2Count; +} __attribute__((packed)); + +struct UsbFuncConfig { + struct usb_interface_descriptor ifDesc; + struct usb_endpoint_descriptor_no_audio from; + struct usb_ss_ep_comp_descriptor pairFrom; + struct usb_endpoint_descriptor_no_audio to; + struct usb_ss_ep_comp_descriptor pairTo; +} __attribute__((packed)); + +static struct UsbFuncConfig config3 = { + .ifDesc = { + .bLength = sizeof(config3.ifDesc), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bNumEndpoints = 2, + .bInterfaceClass = HDC_CLASS, + .bInterfaceSubClass = HDC_SUBCLASS, + .bInterfaceProtocol = VER_PROTOCOL, + .iInterface = 1 + }, + .from = { + .bLength = sizeof(config3.from), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 1 | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = HDC_SSPKT_SIZE_MAX, + }, + .pairFrom = { + .bLength = sizeof(config3.pairFrom), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 4, + }, + .to = { + .bLength = sizeof(config3.to), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 2 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = HDC_SSPKT_SIZE_MAX, + }, + .pairTo = { + .bLength = sizeof(config3.pairTo), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 4, + }, +}; + +static struct UsbFunctionDesc config1 = { + .ifDesc = { + .bLength = sizeof(config1.ifDesc), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bNumEndpoints = 2, + .bInterfaceClass = HDC_CLASS, + .bInterfaceSubClass = HDC_SUBCLASS, + .bInterfaceProtocol = VER_PROTOCOL, + .iInterface = 1 + }, + .from = { + .bLength = sizeof(config1.from), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 1 | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = HDC_FSPKT_SIZE_MAX, + }, + .to = { + .bLength = sizeof(config1.to), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 2 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = HDC_FSPKT_SIZE_MAX, + }, +}; + +static struct UsbFunctionDesc config2 = { + .ifDesc = { + .bLength = sizeof(config2.ifDesc), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bNumEndpoints = 2, + .bInterfaceClass = HDC_CLASS, + .bInterfaceSubClass = HDC_SUBCLASS, + .bInterfaceProtocol = VER_PROTOCOL, + .iInterface = 1 + }, + .from = { + .bLength = sizeof(config2.from), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 1 | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = HDC_HSPKT_SIZE_MAX, + }, + .to = { + .bLength = sizeof(config2.to), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 2 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = HDC_HSPKT_SIZE_MAX, + }, +}; + +static const struct { + struct usb_functionfs_descs_head_v2 head; + __le32 config1Count; + __le32 config2Count; + __le32 config3Count; + __le32 configWosCount; + struct UsbFunctionDesc config1Desc, config2Desc; + struct UsbFuncConfig config3Desc; + struct usb_os_desc_header wosHead; + struct usb_ext_compat_desc wosDesc; +} __attribute__((packed)) USB_FFS_DESC = { + .head = + { + .magic = LONG_LE(FUNCTIONFS_DESCRIPTORS_MAGIC_V2), + .length = LONG_LE(sizeof(USB_FFS_DESC)), + .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC | + FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC + }, + .config1Count = 3, + .config2Count = 3, + .config3Count = 5, + .configWosCount = 1, + .config1Desc = config1, + .config2Desc = config2, + .config3Desc = config3, + .wosHead = { + .interface = 1, + .dwLength = LONG_LE(sizeof(USB_FFS_DESC.wosHead) + sizeof(USB_FFS_DESC.wosDesc)), + .bcdVersion = SHORT_LE(1), + .wIndex = SHORT_LE(4), + .bCount = 1, + .Reserved = 0, + }, + .wosDesc = { + .bFirstInterfaceNumber = 0, + .Reserved1 = 1, + .CompatibleID = { 'W', 'I', 'N', 'U', 'S', 'B', '\0', '\0'}, + .SubCompatibleID = {0}, + .Reserved2 = {0}, + } +}; +} // namespace Hdc +#endif diff --git a/services/flashd/host/client.cpp b/services/flashd/host/client.cpp new file mode 100755 index 00000000..efefabc5 --- /dev/null +++ b/services/flashd/host/client.cpp @@ -0,0 +1,371 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "client.h" +#include "server.h" + +namespace Hdc { +HdcClient::HdcClient(const bool serverOrClient, const string &addrString, uv_loop_t *loopMainIn) + : HdcChannelBase(serverOrClient, addrString, loopMainIn) +{ + MallocChannel(&channel); // free by logic + debugRetryCount = 0; +} + +HdcClient::~HdcClient() +{ +#ifndef _WIN32 + if (terminalChanged) { + tcsetattr(STDIN_FILENO, TCSAFLUSH, &terminalState); + terminalChanged = false; + } +#endif + Base::TryCloseLoop(loopMain, "ExecuteCommand finish"); +} + +void HdcClient::NotifyInstanceChannelFree(HChannel hChannel) +{ + if (bShellInteractive) { + WRITE_LOG(LOG_DEBUG, "Restore tty"); + ModifyTty(false, &hChannel->stdinTty); + } +} + +uint32_t HdcClient::GetLastPID() +{ + char bufPath[BUF_SIZE_MEDIUM] = ""; + size_t size = BUF_SIZE_MEDIUM; + char pidBuf[BUF_SIZE_TINY] = ""; + // get running pid to kill it + if (uv_os_tmpdir(bufPath, &size) < 0) { + WRITE_LOG(LOG_FATAL, "Tmppath failed"); + return 0; + } + string path = Base::StringFormat("%s%c.%s.pid", bufPath, Base::GetPathSep(), SERVER_NAME.c_str()); + Base::ReadBinFile(path.c_str(), (void **)&pidBuf, BUF_SIZE_TINY); + int pid = atoi(pidBuf); // pid maybe 0 + return pid; +} + +bool HdcClient::StartKillServer(const char *cmd, bool startOrKill) +{ + bool isNowRunning = Base::ProgramMutex(SERVER_NAME.c_str(), true) != 0; + const int SIGN_NUM = 9; + uint32_t pid = GetLastPID(); + if (!pid) { + return false; + } + if (startOrKill) { + if (isNowRunning) { + // already running + if (!strstr(cmd, " -r")) { + return true; + } + if (pid) { + uv_kill(pid, SIGN_NUM); + } + } + HdcServer::PullupServer(channelHostPort.c_str()); + } else { + if (isNowRunning && pid) { + uv_kill(pid, SIGN_NUM); + Base::PrintMessage("Kill server finish"); + } + // already running + if (!strstr(cmd, " -r")) { + return true; + } + HdcServer::PullupServer(channelHostPort.c_str()); + } + return true; +} + +void HdcClient::DoCtrlServiceWork(uv_check_t *handle) +{ + HdcClient *thisClass = (HdcClient *)handle->data; + const char *cmd = thisClass->command.c_str(); + string &strCmd = thisClass->command; + while (true) { + if (!strncmp(cmd, CMDSTR_SERVICE_START.c_str(), CMDSTR_SERVICE_START.size())) { + thisClass->StartKillServer(cmd, true); + } else if (!strncmp(cmd, CMDSTR_SERVICE_KILL.c_str(), CMDSTR_SERVICE_KILL.size())) { + thisClass->StartKillServer(cmd, false); + // clang-format off + } else if (!strncmp(cmd, CMDSTR_GENERATE_KEY.c_str(), CMDSTR_GENERATE_KEY.size()) && + strCmd.find(" ") != std::string::npos) { + // clang-format on + string keyPath = strCmd.substr(CMDSTR_GENERATE_KEY.size() + 1, strCmd.size()); + HdcAuth::GenerateKey(keyPath.c_str()); + } else { + Base::PrintMessage("Unknow command"); + } + break; + } + Base::TryCloseHandle((const uv_handle_t *)handle); +} + +int HdcClient::CtrlServiceWork(const char *commandIn) +{ + command = commandIn; + ctrlServerWork.data = this; + uv_check_init(loopMain, &ctrlServerWork); + uv_check_start(&ctrlServerWork, DoCtrlServiceWork); + uv_run(loopMain, UV_RUN_NOWAIT); + return 0; +} + +string HdcClient::AutoConnectKey(string &doCommand, const string &preConnectKey) const +{ + string key = preConnectKey; + bool isNoTargetCommand = false; + vector vecNoConnectKeyCommand; + vecNoConnectKeyCommand.push_back(CMDSTR_SOFTWARE_VERSION); + vecNoConnectKeyCommand.push_back(CMDSTR_SOFTWARE_HELP); + vecNoConnectKeyCommand.push_back(CMDSTR_TARGET_DISCOVER); + vecNoConnectKeyCommand.push_back(CMDSTR_LIST_TARGETS); + vecNoConnectKeyCommand.push_back(CMDSTR_CONNECT_TARGET); + vecNoConnectKeyCommand.push_back(CMDSTR_KILL_SERVER); + vecNoConnectKeyCommand.push_back(CMDSTR_FORWARD_FPORT + " ls"); + vecNoConnectKeyCommand.push_back(CMDSTR_FORWARD_FPORT + " rm"); + for (string v : vecNoConnectKeyCommand) { + if (!doCommand.compare(0, v.size(), v)) { + isNoTargetCommand = true; + break; + } + } + if (isNoTargetCommand) { + key = ""; + } else { + if (!preConnectKey.size()) { + key = CMDSTR_CONNECT_ANY; + } + } + return key; +} + +int HdcClient::ExecuteCommand(const string &commandIn) +{ + char ip[BUF_SIZE_TINY] = ""; + uint16_t port = 0; + if (Base::ConnectKey2IPPort(channelHostPort.c_str(), ip, &port) < 0) { + return -1; + } + command = commandIn; + connectKey = AutoConnectKey(command, connectKey); + ConnectServerForClient(ip, port); + uv_timer_init(loopMain, &waitTimeDoCmd); + waitTimeDoCmd.data = this; + uv_timer_start(&waitTimeDoCmd, CommandWorker, 10, 10); + WorkerPendding(); + return 0; +} + +int HdcClient::Initial(const string &connectKeyIn) +{ + connectKey = connectKeyIn; + if (!channelHostPort.size() || !channelHost.size() || !channelPort) { + WRITE_LOG(LOG_FATAL, "Listen string initial failed"); + return ERR_PARM_FAIL; + } + return 0; +} + +int HdcClient::ConnectServerForClient(const char *ip, uint16_t port) +{ + if (uv_is_closing((const uv_handle_t *)&channel->hWorkTCP)) { + return ERR_SOCKET_FAIL; + } + WRITE_LOG(LOG_DEBUG, "Try to connect %s:%d", ip, port); + struct sockaddr_in dest; + uv_ip4_addr(ip, port, &dest); + uv_connect_t *conn = new uv_connect_t(); + conn->data = this; + uv_tcp_connect(conn, (uv_tcp_t *)&channel->hWorkTCP, (const struct sockaddr *)&dest, Connect); + return 0; +} + +void HdcClient::CommandWorker(uv_timer_t *handle) +{ + const uint16_t maxWaitRetry = 500; + HdcClient *thisClass = (HdcClient *)handle->data; + if (++thisClass->debugRetryCount > maxWaitRetry) { + uv_timer_stop(handle); + uv_stop(thisClass->loopMain); + WRITE_LOG(LOG_DEBUG, "Connect server failed"); + return; + } + if (!thisClass->channel->handshakeOK) { + return; + } + uv_timer_stop(handle); + WRITE_LOG(LOG_DEBUG, "Connect server successful"); + bool closeInput = false; + if (!HostUpdater::ConfirmCommand(thisClass->command, closeInput)) { + uv_timer_stop(handle); + uv_stop(thisClass->loopMain); + WRITE_LOG(LOG_DEBUG, "Cmd \'%s\' has been canceld", thisClass->command.c_str()); + return; + } + if (closeInput) { + thisClass->CloseInput(); + } + thisClass->Send(thisClass->channel->channelId, (uint8_t *)thisClass->command.c_str(), + thisClass->command.size() + 1); +} + +void HdcClient::AllocStdbuf(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) +{ + if (sizeWanted <= 0) { + return; + } + HChannel context = (HChannel)handle->data; + int availSize = strlen(context->bufStd); + buf->base = (char *)context->bufStd + availSize; + buf->len = sizeof(context->bufStd) - availSize - 2; // reserve 2bytes +} + +void HdcClient::ReadStd(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) +{ + HChannel hChannel = (HChannel)stream->data; + HdcClient *thisClass = (HdcClient *)hChannel->clsChannel; + char *command = hChannel->bufStd; + if (nread <= 0) { + return; // error + } + thisClass->Send(hChannel->channelId, (uint8_t *)command, strlen(command)); + Base::ZeroArray(hChannel->bufStd); +} + +void HdcClient::ModifyTty(bool setOrRestore, uv_tty_t *tty) +{ + if (setOrRestore) { +#ifdef _WIN32 + uv_tty_set_mode(tty, UV_TTY_MODE_RAW); +#else + CloseInput(); +#endif + } else { +#ifndef _WIN32 + tcsetattr(STDIN_FILENO, TCSAFLUSH, &terminalState); + terminalChanged = false; +#endif + } +} + +void HdcClient::BindLocalStd(HChannel hChannel) +{ + if (command == CMDSTR_SHELL) { + bShellInteractive = true; + } + if (uv_guess_handle(STDIN_FILENO) != UV_TTY) { + WRITE_LOG(LOG_FATAL, "Not support std mode"); + return; + } + + WRITE_LOG(LOG_DEBUG, "Tty std mode"); + if (uv_tty_init(loopMain, &hChannel->stdoutTty, STDOUT_FILENO, 0) + || uv_tty_init(loopMain, &hChannel->stdinTty, STDIN_FILENO, 1)) { + WRITE_LOG(LOG_DEBUG, "uv_tty_init failed"); + return; + } + hChannel->stdoutTty.data = hChannel; + ++hChannel->uvRef; + hChannel->stdinTty.data = hChannel; + ++hChannel->uvRef; + if (bShellInteractive) { + WRITE_LOG(LOG_DEBUG, "uv_tty_init uv_tty_set_mode"); + ModifyTty(true, &hChannel->stdinTty); + uv_read_start((uv_stream_t *)&hChannel->stdinTty, AllocStdbuf, ReadStd); + } +} + +void HdcClient::Connect(uv_connect_t *connection, int status) +{ + HdcClient *thisClass = (HdcClient *)connection->data; + delete connection; + HChannel hChannel = (HChannel)thisClass->channel; + if (status < 0 || uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP)) { + WRITE_LOG(LOG_FATAL, "connect failed"); + thisClass->FreeChannel(hChannel->channelId); + return; + } + thisClass->BindLocalStd(hChannel); + Base::SetTcpOptions((uv_tcp_t *)&hChannel->hWorkTCP); + uv_read_start((uv_stream_t *)&hChannel->hWorkTCP, AllocCallback, ReadStream); +} + +int HdcClient::PreHandshake(HChannel hChannel, const uint8_t *buf) +{ + ChannelHandShake *hShake = (ChannelHandShake *)buf; + if (strncmp(hShake->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) { + hChannel->availTailIndex = 0; + WRITE_LOG(LOG_DEBUG, "Channel Hello failed"); + return ERR_BUF_CHECK; + } + // sync remote session id to local + uint32_t unOld = hChannel->channelId; + hChannel->channelId = ntohl(hShake->channelId); + AdminChannel(OP_UPDATE, unOld, hChannel); + WRITE_LOG(LOG_DEBUG, "Client channel handshake finished, use connectkey:%s", connectKey.c_str()); + // send config + // channel handshake step2 + if (memset_s(hShake->connectKey, sizeof(hShake->connectKey), 0, sizeof(hShake->connectKey)) != EOK + || memcpy_s(hShake->connectKey, sizeof(hShake->connectKey), connectKey.c_str(), connectKey.size()) != EOK) { + hChannel->availTailIndex = 0; + WRITE_LOG(LOG_DEBUG, "Channel Hello failed"); + return ERR_BUF_COPY; + } + Send(hChannel->channelId, reinterpret_cast(hShake), sizeof(ChannelHandShake)); + hChannel->handshakeOK = true; +#ifdef HDC_CHANNEL_KEEP_ALIVE + // Evaluation method, non long-term support + Send(hChannel->channelId, reinterpret_cast(CMDSTR_INNER_ENABLE_KEEPALIVE.c_str()), + CMDSTR_INNER_ENABLE_KEEPALIVE.size()); +#endif + return RET_SUCCESS; +} + +// read serverForClient(server)TCP data +int HdcClient::ReadChannel(HChannel hChannel, uint8_t *buf, const int bytesIO) +{ + if (!hChannel->handshakeOK) { + return PreHandshake(hChannel, buf); + } +#ifdef UNIT_TEST + // Do not output to console when the unit test + return 0; +#endif + WRITE_LOG(LOG_DEBUG, "Client ReadChannel :%d", bytesIO); + string s(reinterpret_cast(buf), bytesIO); + fprintf(stdout, "%s", s.c_str()); + fflush(stdout); + return 0; +} + +void HdcClient::CloseInput() +{ +#ifndef _WIN32 + if (tcgetattr(STDIN_FILENO, &terminalState)) + return; + termios tio; + if (tcgetattr(STDIN_FILENO, &tio)) + return; + cfmakeraw(&tio); + tio.c_cc[VTIME] = 0; + tio.c_cc[VMIN] = 1; + tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); + terminalChanged = true; +#endif +} +} // namespace Hdc diff --git a/services/flashd/host/client.h b/services/flashd/host/client.h new file mode 100755 index 00000000..3efc5700 --- /dev/null +++ b/services/flashd/host/client.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_CLIENT_H +#define HDC_CLIENT_H +#include "host_common.h" + +namespace Hdc { +class HdcClient : public HdcChannelBase { +public: + HdcClient(const bool serverOrClient, const string &addrString, uv_loop_t *loopMainIn); + virtual ~HdcClient(); + int Initial(const string &connectKeyIn); + int ExecuteCommand(const string &commandIn); + int CtrlServiceWork(const char *commandIn); + void CloseInput(); +protected: +private: + static void DoCtrlServiceWork(uv_check_t *handle); + static void Connect(uv_connect_t *connection, int status); + static void AllocStdbuf(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf); + static void ReadStd(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); + static void CommandWorker(uv_timer_t *handle); + int ConnectServerForClient(const char *ip, uint16_t port); + int ReadChannel(HChannel hChannel, uint8_t *buf, const int bytesIO); + int PreHandshake(HChannel hChannel, const uint8_t *buf); + string AutoConnectKey(string &doCommand, const string &preConnectKey) const; + uint32_t GetLastPID(); + bool StartKillServer(const char *cmd, bool startOrKill); + void BindLocalStd(); + void BindLocalStd(HChannel hChannel); + void ModifyTty(bool setOrRestore, uv_tty_t *tty); + void NotifyInstanceChannelFree(HChannel hChannel); + +#ifndef _WIN32 + termios terminalState; + bool terminalChanged = false; +#endif + string connectKey; + string command; + uint16_t debugRetryCount; + bool bShellInteractive = false; + uv_timer_t waitTimeDoCmd; + uv_check_t ctrlServerWork; + HChannel channel; +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/host/host_app.cpp b/services/flashd/host/host_app.cpp new file mode 100755 index 00000000..938af005 --- /dev/null +++ b/services/flashd/host/host_app.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "host_app.h" + +namespace Hdc { +HdcHostApp::HdcHostApp(HTaskInfo hTaskInfo) + : HdcTransferBase(hTaskInfo) +{ + commandBegin = CMD_APP_BEGIN; + commandData = CMD_APP_DATA; +} + +HdcHostApp::~HdcHostApp() +{ +} + +bool HdcHostApp::BeginInstall(CtxFile *context, const char *command) +{ + int argc = 0; + bool ret = false; + string options; + char **argv = Base::SplitCommandToArgs(command, &argc); + if (argc < 1) { + goto Finish; + } + + for (int i = 0; i < argc; ++i) { + if (!strcmp(argv[i], CMD_OPTION_CLIENTCWD.c_str())) { + if (i + 1 < argc) { + context->transferConfig.clientCwd = argv[i + 1]; + i += 1; // add content index + } + } else if (!strncmp(argv[i], "-", 1)) { + if (options.size()) { + options += " "; + } + options += argv[i]; + } else { + string path = argv[i]; + ExtractRelativePath(context->transferConfig.clientCwd, path); + if (MatchPackageExtendName(path, ".hap")) { + context->taskQueue.push_back(path); + } else { + GetSubFiles(argv[i], ".hap", &context->taskQueue); + } + } + } + if (!context->taskQueue.size()) { + LogMsg(MSG_FAIL, "Not any installation package was found"); + return false; + } + // remove repeate + sort(context->taskQueue.begin(), context->taskQueue.end()); + context->taskQueue.erase(unique(context->taskQueue.begin(), context->taskQueue.end()), context->taskQueue.end()); + + context->transferConfig.options = options; + context->transferConfig.functionName = CMDSTR_APP_INSTALL; + RunQueue(context); + ret = true; +Finish: + if (argv) { + delete[]((char *)argv); + } + return ret; +} + +bool HdcHostApp::BeginSideload(CtxFile *context, const char *localPath) +{ + bool ret = false; + context->transferConfig.functionName = CMDSTR_APP_SIDELOAD; + context->taskQueue.push_back(localPath); + RunQueue(context); + ret = true; + return ret; +} + +void HdcHostApp::RunQueue(CtxFile *context) +{ + ++refCount; + context->localPath = context->taskQueue.back(); + uv_fs_open(loopTask, &context->fsOpenReq, context->localPath.c_str(), O_RDONLY, 0, OnFileOpen); + context->master = true; +} + +void HdcHostApp::CheckMaster(CtxFile *context) +{ + uv_fs_t fs; + Base::ZeroStruct(fs.statbuf); + uv_fs_fstat(nullptr, &fs, context->fsOpenReq.result, nullptr); + context->transferConfig.fileSize = fs.statbuf.st_size; + uv_fs_req_cleanup(&fs); + + context->transferConfig.optionalName + = Base::GetRandomString(9); // Prevent the name of illegal APP leads to pm unable to install + if (context->localPath.find(".hap") != (size_t)-1) { + context->transferConfig.optionalName += ".hap"; + } else { + context->transferConfig.optionalName += ".bundle"; + } + string bufString = SerialStruct::SerializeToString(context->transferConfig); + SendToAnother(CMD_APP_CHECK, (uint8_t *)bufString.c_str(), bufString.size()); +} + +bool HdcHostApp::CheckInstallContinue(AppModType mode, bool lastResult, const char *msg) +{ + string modeDesc; + switch (mode) { + case APPMOD_INSTALL: + modeDesc = "App install"; + break; + case APPMOD_UNINSTALL: + modeDesc = "App uninstall"; + break; + case APPMOD_SIDELOAD: + modeDesc = "Side load"; + break; + default: + modeDesc = "Unknow"; + break; + } + ctxNow.taskQueue.pop_back(); + LogMsg(MSG_INFO, "%s path:%s, queuesize:%d, msg:%s", modeDesc.c_str(), ctxNow.localPath.c_str(), + ctxNow.taskQueue.size(), msg); + if (singalStop || !ctxNow.taskQueue.size()) { + LogMsg(MSG_OK, "AppMod finish"); + return false; + } + RunQueue(&ctxNow); + return true; +} + +bool HdcHostApp::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ + if (!HdcTransferBase::CommandDispatch(command, payload, payloadSize)) { + return false; + } + bool ret = true; + constexpr int cmdOffset = 2; + switch (command) { + case CMD_APP_INIT: { + ret = BeginInstall(&ctxNow, (const char *)payload); + break; + } + case CMD_APP_FINISH: { + AppModType mode = (AppModType)payload[0]; + bool result = (bool)payload[1]; + string s(reinterpret_cast(payload + cmdOffset), payloadSize - cmdOffset); + ret = CheckInstallContinue(mode, result, s.c_str()); + break; + } + case CMD_APP_UNINSTALL: { + SendToAnother(CMD_APP_UNINSTALL, payload, payloadSize); + ctxNow.taskQueue.push_back(reinterpret_cast(payload)); // just compatible + break; + } + case CMD_APP_SIDELOAD: { + BeginSideload(&ctxNow, (const char *)payload); + break; + } + default: + break; + } + return ret; +}; +} \ No newline at end of file diff --git a/services/flashd/host/host_app.h b/services/flashd/host/host_app.h new file mode 100755 index 00000000..ad3c8845 --- /dev/null +++ b/services/flashd/host/host_app.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_HOST_APP_H +#define HDC_HOST_APP_H +#include "host_common.h" + +namespace Hdc { +class HdcHostApp : public HdcTransferBase { +public: + HdcHostApp(HTaskInfo hTaskInfo); + virtual ~HdcHostApp(); + bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); + +private: + bool BeginInstall(CtxFile *context, const char *command); + void CheckMaster(CtxFile *context); + bool CheckInstallContinue(AppModType mode, bool lastResult, const char *msg); + void RunQueue(CtxFile *context); + bool BeginSideload(CtxFile *context, const char *localPath); +}; +} +#endif \ No newline at end of file diff --git a/services/flashd/host/host_common.h b/services/flashd/host/host_common.h new file mode 100755 index 00000000..e6be2ba5 --- /dev/null +++ b/services/flashd/host/host_common.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_HOST_COMMON_H +#define HDC_HOST_COMMON_H + +// clang-format off +#include "../common/common.h" +#include "../common/file.h" +#include "../common/transfer.h" +#include "../common/forward.h" +#include "../common/async_cmd.h" +#include "../common/serial_struct.h" + +#include "host_tcp.h" +#include "host_usb.h" +#include "translate.h" +#include "server_for_client.h" +#include "client.h" +#include "host_app.h" +#include "host_forward.h" +#include "host_unity.h" +#include "host_updater.h" +// clang-format on + +#endif \ No newline at end of file diff --git a/services/flashd/host/host_forward.cpp b/services/flashd/host/host_forward.cpp new file mode 100755 index 00000000..72cd3f83 --- /dev/null +++ b/services/flashd/host/host_forward.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "host_forward.h" + +namespace Hdc { +HdcHostForward::HdcHostForward(HTaskInfo hTaskInfo) + : HdcForwardBase(hTaskInfo) +{ +} + +HdcHostForward::~HdcHostForward() +{ +} +} \ No newline at end of file diff --git a/services/flashd/host/host_forward.h b/services/flashd/host/host_forward.h new file mode 100755 index 00000000..5c984106 --- /dev/null +++ b/services/flashd/host/host_forward.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_HOST_FORWARD_H +#define HDC_HOST_FORWARD_H +#include "host_common.h" + +namespace Hdc { +class HdcHostForward : public HdcForwardBase { +public: + HdcHostForward(HTaskInfo hTaskInfo); + virtual ~HdcHostForward(); + +private: +}; +} // namespace Hdc + +#endif \ No newline at end of file diff --git a/services/flashd/host/host_tcp.cpp b/services/flashd/host/host_tcp.cpp new file mode 100755 index 00000000..49463605 --- /dev/null +++ b/services/flashd/host/host_tcp.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "host_tcp.h" +#include "server.h" + +namespace Hdc { +HdcHostTCP::HdcHostTCP(const bool serverOrDaemonIn, void *ptrMainBase) + : HdcTCPBase(serverOrDaemonIn, ptrMainBase) +{ + broadcastFindWorking = false; +} + +HdcHostTCP::~HdcHostTCP() +{ + WRITE_LOG(LOG_DEBUG, "~HdcHostTCP"); +} + +void HdcHostTCP::Stop() +{ +} + +void HdcHostTCP::RecvUDPEntry(const sockaddr *addrSrc, uv_udp_t *handle, const uv_buf_t *rcvbuf) +{ + char bufString[BUF_SIZE_TINY]; + uint16_t port = 0; + char *p = strstr(rcvbuf->base, "-"); + if (!p) { + return; + } + port = atoi(p + 1); + if (!port) { + return; + } + uv_ip4_name((sockaddr_in *)addrSrc, bufString, sizeof(bufString)); + string addrPort = string(bufString); + addrPort += string(":") + std::to_string(port); + lstDaemonResult.push_back(addrPort); +} + +void HdcHostTCP::BroadcastTimer(uv_idle_t *handle) +{ + uv_stop(handle->loop); +} + +// Executive Administration Network Broadcast Discovery, broadcastLanIP==which interface to broadcast +void HdcHostTCP::BroadcatFindDaemon(const char *broadcastLanIP) +{ + if (broadcastFindWorking) { + return; + } + broadcastFindWorking = true; + lstDaemonResult.clear(); + + uv_loop_t loopBroadcast; + uv_loop_init(&loopBroadcast); + struct sockaddr_in addr; + uv_udp_send_t req; + uv_udp_t client; + // send + uv_ip4_addr(broadcastLanIP, 0, &addr); + uv_udp_init(&loopBroadcast, &client); + uv_udp_bind(&client, (const struct sockaddr *)&addr, 0); + uv_udp_set_broadcast(&client, 1); + uv_ip4_addr("255.255.255.255", DEFAULT_PORT, &addr); + uv_buf_t buf = uv_buf_init((char *)HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size()); + uv_udp_send(&req, &client, &buf, 1, (const struct sockaddr *)&addr, nullptr); + // recv + uv_udp_t server; + server.data = this; + uv_ip4_addr(broadcastLanIP, DEFAULT_PORT, &addr); + uv_udp_init(&loopBroadcast, &server); + uv_udp_bind(&server, (const struct sockaddr *)&addr, UV_UDP_REUSEADDR); + uv_udp_recv_start(&server, AllocStreamUDP, RecvUDP); + // find timeout + uv_timer_t tLastCheck; + uv_timer_init(&loopBroadcast, &tLastCheck); + uv_timer_start(&tLastCheck, (uv_timer_cb)BroadcastTimer, TIME_BASE, 0); // timeout debug 1s + + uv_run(&loopBroadcast, UV_RUN_DEFAULT); + uv_loop_close(&loopBroadcast); + broadcastFindWorking = false; +} + +void HdcHostTCP::Connect(uv_connect_t *connection, int status) +{ + HSession hSession = (HSession)connection->data; + delete connection; + HdcSessionBase *ptrConnect = (HdcSessionBase *)hSession->classInstance; + auto ctrl = ptrConnect->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0); + if (status < 0) { + goto Finish; + } + if ((hSession->fdChildWorkTCP = Base::DuplicateUvSocket(&hSession->hWorkTCP)) < 0) { + goto Finish; + } + uv_read_stop((uv_stream_t *)&hSession->hWorkTCP); + Base::SetTcpOptions((uv_tcp_t *)&hSession->hWorkTCP); + WRITE_LOG(LOG_DEBUG, "HdcHostTCP::Connect"); + Base::StartWorkThread(&ptrConnect->loopMain, ptrConnect->SessionWorkThread, Base::FinishWorkThread, hSession); + // wait for thread up + while (hSession->childLoop.active_handles == 0) { + uv_sleep(MINOR_TIMEOUT); + } + Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); + return; +Finish: + WRITE_LOG(LOG_FATAL, "Connect failed"); + ptrConnect->FreeSession(hSession->sessionId); +} + +HSession HdcHostTCP::ConnectDaemon(const string &connectKey) +{ + char ip[BUF_SIZE_TINY] = ""; + uint16_t port = 0; + if (Base::ConnectKey2IPPort(connectKey.c_str(), ip, &port) < 0) { + return nullptr; + } + + HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase; + HSession hSession = ptrConnect->MallocSession(true, CONN_TCP, this); + if (!hSession) { + return nullptr; + } + hSession->connectKey = connectKey; + struct sockaddr_in dest; + uv_ip4_addr(ip, port, &dest); + uv_connect_t *conn = new uv_connect_t(); + conn->data = hSession; + uv_tcp_connect(conn, (uv_tcp_t *)&hSession->hWorkTCP, (const struct sockaddr *)&dest, Connect); + return hSession; +} + +void HdcHostTCP::FindLanDaemon() +{ + uv_interface_address_t *info; + int count, i; + char ipAddr[BUF_SIZE_TINY] = ""; + if (broadcastFindWorking) { + return; + } + lstDaemonResult.clear(); + uv_interface_addresses(&info, &count); + i = count; + while (--i) { + uv_interface_address_t interface = info[i]; + if (interface.address.address4.sin_family == AF_INET6) { + continue; + } + uv_ip4_name(&interface.address.address4, ipAddr, sizeof(ipAddr)); + BroadcatFindDaemon(ipAddr); + } + uv_free_interface_addresses(info, count); +} +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/host/host_tcp.h b/services/flashd/host/host_tcp.h new file mode 100755 index 00000000..b5b85ab6 --- /dev/null +++ b/services/flashd/host/host_tcp.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_HOST_TCP_H +#define HDC_HOST_TCP_H +#include "host_common.h" + +namespace Hdc { +class HdcHostTCP : public HdcTCPBase { +public: + HdcHostTCP(const bool serverOrDaemonIn, void *ptrMainBase); + virtual ~HdcHostTCP(); + void FindLanDaemon(); + HSession ConnectDaemon(const string &connectKey); + void Stop(); + list lstDaemonResult; + +private: + static void BroadcastTimer(uv_idle_t *handle); + static void Connect(uv_connect_t *connection, int status); + void BroadcatFindDaemon(const char *broadcastLanIP); + void RecvUDPEntry(const sockaddr *addrSrc, uv_udp_t *handle, const uv_buf_t *rcvbuf); + + bool broadcastFindWorking; +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/host/host_unity.cpp b/services/flashd/host/host_unity.cpp new file mode 100755 index 00000000..276682eb --- /dev/null +++ b/services/flashd/host/host_unity.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "host_unity.h" + +namespace Hdc { +HdcHostUnity::HdcHostUnity(HTaskInfo hTaskInfo) + : HdcTaskBase(hTaskInfo) +{ + Base::ZeroStruct(opContext); + opContext.thisClass = this; +} + +HdcHostUnity::~HdcHostUnity() +{ + WRITE_LOG(LOG_DEBUG, "HdcHostUnity::~HdcHostUnity finish"); +} + +bool HdcHostUnity::ReadyForRelease() +{ + if (!HdcTaskBase::ReadyForRelease()) { + return false; + } + if (opContext.enableLog && !opContext.hasFilelogClosed) { + return false; + } + return true; +} + +void HdcHostUnity::StopTask() +{ + // Do not detect RunningProtect, force to close + if (opContext.hasFilelogClosed) { + return; + } + if (opContext.enableLog) { + ++refCount; + opContext.fsClose.data = &opContext; + uv_fs_close(loopTask, &opContext.fsClose, opContext.fileLog, OnFileClose); + } +}; + +void HdcHostUnity::OnFileClose(uv_fs_t *req) +{ + uv_fs_req_cleanup(req); + ContextUnity *context = (ContextUnity *)req->data; + HdcHostUnity *thisClass = (HdcHostUnity *)context->thisClass; + context->hasFilelogClosed = true; + --thisClass->refCount; + return; +} + +bool HdcHostUnity::InitLocalLog(const char *path) +{ + uv_fs_t reqFs; + // block open + if (uv_fs_open(nullptr, &reqFs, path, UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, nullptr) + < 0) + return false; + uv_fs_req_cleanup(&reqFs); + opContext.fileLog = reqFs.result; + return true; +} + +void HdcHostUnity::OnFileIO(uv_fs_t *req) +{ + CtxUnityIO *contextIO = (CtxUnityIO *)req->data; + ContextUnity *context = (ContextUnity *)contextIO->context; + HdcHostUnity *thisClass = (HdcHostUnity *)context->thisClass; + uint8_t *bufIO = contextIO->bufIO; + uv_fs_req_cleanup(req); + --thisClass->refCount; + while (true) { + if (req->result <= 0) { + if (req->result < 0) { + WRITE_LOG(LOG_DEBUG, "Error OnFileIO: %s", uv_strerror((int)req->result)); + } + break; + } + context->fileIOIndex += req->result; + break; + } + delete[] bufIO; + delete contextIO; // req is part of contextIO, no need to release +} + +bool HdcHostUnity::AppendLocalLog(const char *bufLog, const int sizeLog) +{ + auto buf = new uint8_t[sizeLog]; + auto contextIO = new CtxUnityIO(); + if (!buf || !contextIO) { + if (buf) { + delete[] buf; + } + if (contextIO) { + delete contextIO; + } + return false; + } + uv_fs_t *req = &contextIO->fs; + contextIO->bufIO = buf; + contextIO->context = &opContext; + req->data = contextIO; + ++refCount; + + if (memcpy_s(buf, sizeLog, bufLog, sizeLog)) { + } + uv_buf_t iov = uv_buf_init((char *)buf, sizeLog); + uv_fs_write(loopTask, req, opContext.fileLog, &iov, 1, opContext.fileBufIndex, OnFileIO); + opContext.fileBufIndex += sizeLog; + return true; +} + +bool HdcHostUnity::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ + bool ret = true; + // Both are executed, do not need to detect ChildReady + switch (command) { + case CMD_UNITY_BUGREPORT_INIT: { + if (strlen((char *)payload)) { // enable local log + if (!InitLocalLog((const char *)payload)) { + LogMsg(MSG_FAIL, "Cannot set locallog"); + ret = false; + break; + }; + opContext.enableLog = true; + } + SendToAnother(CMD_UNITY_BUGREPORT_INIT, nullptr, 0); + break; + } + case CMD_UNITY_BUGREPORT_DATA: { + if (opContext.enableLog) { + AppendLocalLog((const char *)payload, payloadSize); + } else { + ServerCommand(CMD_KERNEL_ECHO_RAW, payload, payloadSize); + } + break; + } + default: + break; + } + return ret; +}; +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/host/host_unity.h b/services/flashd/host/host_unity.h new file mode 100755 index 00000000..e4cb08f8 --- /dev/null +++ b/services/flashd/host/host_unity.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_HOST_UNITY_H +#define HDC_HOST_UNITY_H +#include "host_common.h" + +namespace Hdc { +class HdcHostUnity : public HdcTaskBase { +public: + HdcHostUnity(HTaskInfo hTaskInfo); + virtual ~HdcHostUnity(); + bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); + void StopTask(); + bool ReadyForRelease(); + +private: + struct ContextUnity { + bool enableLog; + uv_file fileLog; + uint64_t fileIOIndex; + uint64_t fileBufIndex; + bool hasFilelogClosed; + uv_fs_t fsClose; + HdcHostUnity *thisClass; + }; + struct CtxUnityIO { + uv_fs_t fs; + uint8_t *bufIO; + ContextUnity *context; + }; + static void OnFileIO(uv_fs_t *req); + static void OnFileClose(uv_fs_t *req); + bool InitLocalLog(const char *path); + bool AppendLocalLog(const char *bufLog, const int sizeLog); + + ContextUnity opContext; +}; +} // namespace Hdc +#endif // HDC_HOST_UNITY_H \ No newline at end of file diff --git a/services/flashd/host/host_updater.cpp b/services/flashd/host/host_updater.cpp index 00beb0f8..1092abc0 100755 --- a/services/flashd/host/host_updater.cpp +++ b/services/flashd/host/host_updater.cpp @@ -254,28 +254,10 @@ bool HostUpdater::CheckUpdateContinue(const uint16_t command, const uint8_t *pay return true; } -std::string HostUpdater::GetFlashdHelp() -{ - string help = "\n---------------------------------flash commands:-------------------------------------\n" - "flash commands:\n" - " target boot [-flashd] - Reboot the device or boot into flashd\n" - " update packagename - Update system by package\n" - " flash [-f] partition imagename - Flash partition by image\n" - " erase [-f] partition - Erase partition\n" - " format [-f] partition -t fs_type - Format partition -t [ext4 | f2fs]\n"; - return help; -} - bool HostUpdater::CheckMatchUpdate(const std::string &input, std::string &stringError, uint16_t &cmdFlag, bool &bJumpDo) { WRITE_LOG(LOG_DEBUG, "CheckMatchUpdate command:%s", input.c_str()); - if (!strcmp(input.c_str(), helpCmd.c_str())) { - cmdFlag = CMD_KERNEL_HELP; - stringError = HostUpdater::GetFlashdHelp(); - bJumpDo = true; - return true; - } size_t cmdLen = updateCmd.size(); if (!strncmp(input.c_str(), updateCmd.c_str(), updateCmd.size())) { cmdFlag = CMD_UPDATER_UPDATE_INIT; @@ -365,4 +347,4 @@ bool HostUpdater::ConfirmCommand(const string &commandIn, bool &closeInput) } return true; } -} // namespace Hdc +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/host/host_updater.h b/services/flashd/host/host_updater.h index 2e627782..174dfd4f 100755 --- a/services/flashd/host/host_updater.h +++ b/services/flashd/host/host_updater.h @@ -30,7 +30,6 @@ public: virtual ~HostUpdater(); bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) override; - static std::string GetFlashdHelp(); static bool CheckMatchUpdate(const std::string &input, std::string &stringError, uint16_t &cmdFlag, bool &bJumpDo); static bool ConfirmCommand(const string &commandIn, bool &closeInput); #ifdef UPDATER_UT diff --git a/services/flashd/host/host_usb.cpp b/services/flashd/host/host_usb.cpp new file mode 100755 index 00000000..2b9a9f6d --- /dev/null +++ b/services/flashd/host/host_usb.cpp @@ -0,0 +1,550 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "host_usb.h" +#include "server.h" + +namespace Hdc { +HdcHostUSB::HdcHostUSB(const bool serverOrDaemonIn, void *ptrMainBase, void *ctxUSBin) + : HdcUSBBase(serverOrDaemonIn, ptrMainBase) +{ + modRunning = false; + if (!ctxUSBin) { + return; + } + HdcServer *pServer = (HdcServer *)ptrMainBase; + uv_idle_init(&pServer->loopMain, &usbWork); + ctxUSB = (libusb_context *)ctxUSBin; + uv_timer_init(&pServer->loopMain, &devListWatcher); +} + +HdcHostUSB::~HdcHostUSB() +{ + if (modRunning) { + Stop(); + } + WRITE_LOG(LOG_DEBUG, "~HdcHostUSB"); +} + +void HdcHostUSB::Stop() +{ + if (!ctxUSB) { + return; + } + Base::TryCloseHandle((uv_handle_t *)&usbWork); + Base::TryCloseHandle((uv_handle_t *)&devListWatcher); + modRunning = false; +} + +int HdcHostUSB::Initial() +{ + if (!ctxUSB) { + WRITE_LOG(LOG_FATAL, "USB mod ctxUSB is nullptr, recompile please"); + return -1; + } + WRITE_LOG(LOG_DEBUG, "HdcHostUSB init"); + modRunning = true; + StartupUSBWork(); // Main thread registration, IO in sub-thread + return 0; +} + +// windows/mac's control port reset seems invalid? So we try to use soft interrupt +// if all platform 'libusb_reset_device()' work ok, commit this function and use it replace +// main thread call +void HdcHostUSB::SendUsbSoftReset(HUSB hUSB, uint32_t sessionId) +{ + struct ResetCtx { + USBHead usbPayloadHeader; + HUSB hUSB; + }; + ResetCtx *ctxReset = new ResetCtx(); + ctxReset->hUSB = hUSB; + + USBHead &usbPayloadHeader = ctxReset->usbPayloadHeader; + usbPayloadHeader.option = USB_OPTION_RESET; + usbPayloadHeader.sessionId = sessionId; + if (memcpy_s(usbPayloadHeader.flag, sizeof(usbPayloadHeader.flag), PACKET_FLAG.c_str(), + sizeof(usbPayloadHeader.flag)) + != EOK) { + delete ctxReset; + return; + } + auto resetUsbCallback = [](struct libusb_transfer *transfer) -> void LIBUSB_CALL { + ResetCtx *ctxReset = (ResetCtx *)transfer->user_data; + if (LIBUSB_TRANSFER_COMPLETED != transfer->status) { + WRITE_LOG(LOG_FATAL, "SendUSBRaw status:%d", transfer->status); + } + ctxReset->hUSB->sendIOComplete = true; + delete ctxReset; + libusb_free_transfer(transfer); + // has send soft reset, next reset daemon's send + WRITE_LOG(LOG_DEBUG, "Device reset singal send"); + }; + hUSB->lockDeviceHandle.lock(); + libusb_transfer *transferUsb = libusb_alloc_transfer(0); + libusb_fill_bulk_transfer(transferUsb, hUSB->devHandle, hUSB->epHost, (uint8_t *)&usbPayloadHeader, sizeof(USBHead), + resetUsbCallback, ctxReset, GLOBAL_TIMEOUT * TIME_BASE); + int err = libusb_submit_transfer(transferUsb); + if (err < 0) { + WRITE_LOG(LOG_FATAL, "libusb_submit_transfer failed, err:%d", err); + delete ctxReset; + } else { + hUSB->sendIOComplete = false; + } + hUSB->lockDeviceHandle.unlock(); +} + +bool HdcHostUSB::DetectMyNeed(libusb_device *device, string &sn) +{ + bool ret = false; + HUSB hUSB = new HdcUSB(); + hUSB->device = device; + // just get usb SN, close handle immediately + int childRet = OpenDeviceMyNeed(hUSB); + if (childRet < 0) { + delete hUSB; + return false; + } + libusb_release_interface(hUSB->devHandle, hUSB->interfaceNumber); + libusb_close(hUSB->devHandle); + hUSB->devHandle = nullptr; + + WRITE_LOG(LOG_INFO, "Needed device found, busid:%d devid:%d connectkey:%s", hUSB->busId, hUSB->devId, + hUSB->serialNumber.c_str()); + // USB device is automatically connected after recognition, auto connect USB + UpdateUSBDaemonInfo(hUSB, nullptr, STATUS_READY); + HdcServer *hdcServer = (HdcServer *)clsMainBase; + HSession hSession = hdcServer->MallocSession(true, CONN_USB, this); + hSession->connectKey = hUSB->serialNumber; + uv_timer_t *waitTimeDoCmd = new uv_timer_t; + uv_timer_init(&hdcServer->loopMain, waitTimeDoCmd); + waitTimeDoCmd->data = hSession; + constexpr uint16_t PRECONNECT_INTERVAL = 3000; + uv_timer_start(waitTimeDoCmd, hdcServer->UsbPreConnect, 0, PRECONNECT_INTERVAL); + mapIgnoreDevice[sn] = HOST_USB_REGISTER; + ret = true; + delete hUSB; + return ret; +} + +// sub-thread all called +void HdcHostUSB::PenddingUSBIO(uv_idle_t *handle) +{ + libusb_context *ctxUSB = (libusb_context *)handle->data; + // every plug,handle,libusb_handle_events + struct timeval zerotime; + int nComplete = 0; + zerotime.tv_sec = 0; + zerotime.tv_usec = 1; // if == 0,windows will be high CPU load + libusb_handle_events_timeout_completed(ctxUSB, &zerotime, &nComplete); +} + +void HdcHostUSB::KickoutZombie(HSession hSession) +{ + HdcServer *ptrConnect = (HdcServer *)hSession->classInstance; + HUSB hUSB = hSession->hUSB; + if (!hUSB->devHandle || hSession->isDead) { + return; + } + if (LIBUSB_ERROR_NO_DEVICE != libusb_kernel_driver_active(hUSB->devHandle, hUSB->interfaceNumber)) { + return; + } + ptrConnect->FreeSession(hSession->sessionId); +} + +void HdcHostUSB::RemoveIgnoreDevice(string &mountInfo) +{ + if (mapIgnoreDevice.count(mountInfo)) { + mapIgnoreDevice.erase(mountInfo); + } +} + +void HdcHostUSB::ReviewUsbNodeLater(string &nodeKey) +{ + HdcServer *hdcServer = (HdcServer *)clsMainBase; + // add to ignore list + mapIgnoreDevice[nodeKey] = HOST_USB_IGNORE; + int delayRemoveFromList = intervalDevCheck * MINOR_TIMEOUT; // wait little time for daemon reinit + Base::DelayDo(&hdcServer->loopMain, delayRemoveFromList, 0, nodeKey, nullptr, + [this](const uint8_t flag, string &msg, const void *) -> void { RemoveIgnoreDevice(msg); }); +} + +void HdcHostUSB::WatchDevPlugin(uv_timer_t *handle) +{ + HdcHostUSB *thisClass = (HdcHostUSB *)handle->data; + HdcServer *ptrConnect = (HdcServer *)thisClass->clsMainBase; + libusb_device **devs = nullptr; + libusb_device *dev = nullptr; + // kick zombie + ptrConnect->EnumUSBDeviceRegister(KickoutZombie); + // find new + ssize_t cnt = libusb_get_device_list(thisClass->ctxUSB, &devs); + if (cnt < 0) { + WRITE_LOG(LOG_FATAL, "Failed to get device list"); + return; + } + int i = 0; + // linux replug devid increment,windows will be not + while ((dev = devs[i++]) != nullptr) { // must postfix++ + string szTmpKey = Base::StringFormat("%d-%d", libusb_get_bus_number(dev), libusb_get_device_address(dev)); + // check is in ignore list + UsbCheckStatus statusCheck = thisClass->mapIgnoreDevice[szTmpKey]; + if (statusCheck == HOST_USB_IGNORE || statusCheck == HOST_USB_REGISTER) { + continue; + } + string sn = szTmpKey; + if (!thisClass->DetectMyNeed(dev, sn)) { + thisClass->ReviewUsbNodeLater(szTmpKey); + } + } + libusb_free_device_list(devs, 1); +} + +int HdcHostUSB::StartupUSBWork() +{ + // Because libusb(winusb backend) does not support hotplug under win32, we use list mode for all platforms + WRITE_LOG(LOG_DEBUG, "USBHost loopfind mode"); + devListWatcher.data = this; + uv_timer_start(&devListWatcher, WatchDevPlugin, 0, intervalDevCheck); + // Running pendding in independent threads does not significantly improve the efficiency + usbWork.data = ctxUSB; + uv_idle_start(&usbWork, PenddingUSBIO); + return 0; +} + +int HdcHostUSB::CheckDescriptor(HUSB hUSB) +{ + char serialNum[BUF_SIZE_MEDIUM] = ""; + int childRet = 0; + struct libusb_device_descriptor desc; + int curBus = libusb_get_bus_number(hUSB->device); + int curDev = libusb_get_device_address(hUSB->device); + hUSB->busId = curBus; + hUSB->devId = curDev; + if (libusb_get_device_descriptor(hUSB->device, &desc)) { + WRITE_LOG(LOG_DEBUG, "CheckDescriptor libusb_get_device_descriptor failed"); + return -1; + } + // Get the serial number of the device, if there is no serial number, use the ID number to replace + // If the device is not in time, occasionally can't get it, this is determined by the external factor, cannot be + // changed. LIBUSB_SUCCESS + childRet = libusb_get_string_descriptor_ascii(hUSB->devHandle, desc.iSerialNumber, (uint8_t *)serialNum, + sizeof(serialNum)); + if (childRet < 0) { + hUSB->serialNumber = Base::StringFormat("%d-%d", curBus, curDev); + } else { + hUSB->serialNumber = serialNum; + } + return 0; +} + +// hSession can be null +void HdcHostUSB::UpdateUSBDaemonInfo(HUSB hUSB, HSession hSession, uint8_t connStatus) +{ + // add to list + HdcServer *pServer = (HdcServer *)clsMainBase; + HdcDaemonInformation di; + di.connectKey = hUSB->serialNumber; + di.connType = CONN_USB; + di.connStatus = connStatus; + di.hSession = hSession; + di.usbMountPoint = ""; + di.usbMountPoint = Base::StringFormat("%d-%d", hUSB->busId, hUSB->devId); + + HDaemonInfo pDi = nullptr; + HDaemonInfo hdiNew = &di; + pServer->AdminDaemonMap(OP_QUERY, hUSB->serialNumber, pDi); + if (!pDi) { + pServer->AdminDaemonMap(OP_ADD, hUSB->serialNumber, hdiNew); + } else { + pServer->AdminDaemonMap(OP_UPDATE, hUSB->serialNumber, hdiNew); + } +} + +bool HdcHostUSB::IsDebuggableDev(const struct libusb_interface_descriptor *ifDescriptor) +{ + constexpr uint8_t harmonyEpNum = 2; + constexpr uint8_t harmonyClass = 0xff; + constexpr uint8_t harmonySubClass = 0x50; + constexpr uint8_t harmonyProtocol = 0x01; + + if (ifDescriptor->bInterfaceClass != harmonyClass || ifDescriptor->bInterfaceSubClass != harmonySubClass + || ifDescriptor->bInterfaceProtocol != harmonyProtocol) { + return false; + } + if (ifDescriptor->bNumEndpoints != harmonyEpNum) { + return false; + } + return true; +} + +int HdcHostUSB::CheckActiveConfig(libusb_device *device, HUSB hUSB) +{ + unsigned int j = 0; + int ret = -1; + struct libusb_config_descriptor *descConfig = nullptr; + if (libusb_get_active_config_descriptor(device, &descConfig)) { + return -1; + } + for (j = 0; j < descConfig->bNumInterfaces; ++j) { + const struct libusb_interface *interface = &descConfig->interface[j]; + if (interface->num_altsetting >= 1) { + const struct libusb_interface_descriptor *ifDescriptor = &interface->altsetting[0]; + if (!IsDebuggableDev(ifDescriptor)) { + continue; + } + hUSB->interfaceNumber = ifDescriptor->bInterfaceNumber; + unsigned int k = 0; + for (k = 0; k < ifDescriptor->bNumEndpoints; ++k) { + const struct libusb_endpoint_descriptor *ep_desc = &ifDescriptor->endpoint[k]; + if ((ep_desc->bmAttributes & 0x03) == LIBUSB_TRANSFER_TYPE_BULK) { + if (ep_desc->bEndpointAddress & LIBUSB_ENDPOINT_IN) { + hUSB->epDevice = ep_desc->bEndpointAddress; + } else { + hUSB->epHost = ep_desc->bEndpointAddress; + } + hUSB->wMaxPacketSize = ep_desc->wMaxPacketSize; + } + } + if (hUSB->epDevice == 0 || hUSB->epHost == 0) { + break; + } + ret = 0; + } + } + libusb_free_config_descriptor(descConfig); + return ret; +} + +void LIBUSB_CALL HdcHostUSB::ReadUSBBulkCallback(struct libusb_transfer *transfer) +{ + HSession hSession = (HSession)transfer->user_data; + HdcHostUSB *thisClass = (HdcHostUSB *)hSession->classModule; + HUSB hUSB = hSession->hUSB; + bool bOK = false; + int childRet = 0; + constexpr int infinity = 0; // ignore timeout + while (true) { + if (!thisClass->modRunning || (hSession->isDead && 0 == hSession->sendRef)) + break; + if (LIBUSB_TRANSFER_COMPLETED != transfer->status) { + WRITE_LOG(LOG_FATAL, "Host usb not LIBUSB_TRANSFER_COMPLETED, status:%d", transfer->status); + break; + } + childRet + = thisClass->SendToHdcStream(hSession, reinterpret_cast(&hSession->dataPipe[STREAM_MAIN]), + hUSB->bufDevice, transfer->actual_length); + if (childRet != RET_SUCCESS && childRet != ERR_SESSION_NOFOUND) { + break; + } + hUSB->lockDeviceHandle.lock(); + // loop self + libusb_fill_bulk_transfer(transfer, hUSB->devHandle, hUSB->epDevice, hUSB->bufDevice, hUSB->sizeEpBuf, + ReadUSBBulkCallback, hSession, infinity); + childRet = libusb_submit_transfer(transfer); + hUSB->lockDeviceHandle.unlock(); + if (childRet < 0) { + WRITE_LOG(LOG_FATAL, "libusb_submit_transfer failed, err:%d", childRet); + break; + } + bOK = true; + break; + } + if (!bOK) { + auto server = reinterpret_cast(thisClass->clsMainBase); + server->FreeSession(hSession->sessionId); + hUSB->recvIOComplete = true; + WRITE_LOG(LOG_WARN, "ReadUSBBulkCallback failed"); + } +} + +void HdcHostUSB::RegisterReadCallback(HSession hSession) +{ + HUSB hUSB = hSession->hUSB; + if (hSession->isDead || !modRunning) { + return; + } + hSession->hUSB->transferRecv->user_data = hSession; + hUSB->lockDeviceHandle.lock(); + // first bulk-read must be Okay and no timeout, otherwise failed. + libusb_fill_bulk_transfer(hSession->hUSB->transferRecv, hUSB->devHandle, hUSB->epDevice, hUSB->bufDevice, + hUSB->sizeEpBuf, ReadUSBBulkCallback, hSession, GLOBAL_TIMEOUT * TIME_BASE); + int childRet = libusb_submit_transfer(hSession->hUSB->transferRecv); + hUSB->lockDeviceHandle.unlock(); + if (childRet == 0) { + hSession->hUSB->recvIOComplete = false; + } +} + +// ==0 Represents new equipment and is what we need,<0 my need +int HdcHostUSB::OpenDeviceMyNeed(HUSB hUSB) +{ + libusb_device *device = hUSB->device; + int ret = -1; + if (LIBUSB_SUCCESS != libusb_open(device, &hUSB->devHandle)) { + return -100; + } + while (modRunning) { + libusb_device_handle *handle = hUSB->devHandle; + if (CheckDescriptor(hUSB)) { + break; + } + if (CheckActiveConfig(device, hUSB)) { + break; + } + // USB filter rules are set according to specific device + // pedding device + libusb_claim_interface(handle, hUSB->interfaceNumber); + ret = 0; + break; + } + if (ret) { + // not my need device + libusb_close(hUSB->devHandle); + hUSB->devHandle = nullptr; + } + return ret; +} + +// at main thread +void LIBUSB_CALL HdcHostUSB::WriteUSBBulkCallback(struct libusb_transfer *transfer) +{ + USBHead *usbHead = reinterpret_cast(transfer->buffer); + HSession hSession = reinterpret_cast(transfer->user_data); + HdcSessionBase *server = reinterpret_cast(hSession->classInstance); + if (usbHead->option & USB_OPTION_TAIL) { + --hSession->sendRef; + } + if (LIBUSB_TRANSFER_COMPLETED != transfer->status || (hSession->isDead && 0 == hSession->sendRef)) { + WRITE_LOG(LOG_FATAL, "SendUSBRaw status:%d", transfer->status); + if (hSession->hUSB->transferRecv != nullptr) { + libusb_cancel_transfer(hSession->hUSB->transferRecv); + } + server->FreeSession(hSession->sessionId); + } + hSession->hUSB->sendIOComplete = true; + hSession->hUSB->cvTransferSend.notify_one(); +} + +// libusb can send directly across threads?!!! +// Just call from child work thread, it will be block when overlap full +int HdcHostUSB::SendUSBRaw(HSession hSession, uint8_t *data, const int length) +{ + int ret = ERR_GENERIC; + int childRet = -1; + HUSB hUSB = hSession->hUSB; + while (true) { + if (memcpy_s(hUSB->bufHost, length, data, length) != EOK) { + ret = ERR_BUF_COPY; + break; + } + hUSB->lockDeviceHandle.lock(); + std::unique_lock lock(hUSB->lockSend); + hUSB->sendIOComplete = false; + libusb_fill_bulk_transfer(hUSB->transferSend, hUSB->devHandle, hUSB->epHost, hUSB->bufHost, length, + WriteUSBBulkCallback, hSession, GLOBAL_TIMEOUT * TIME_BASE); + childRet = libusb_submit_transfer(hUSB->transferSend); + hUSB->lockDeviceHandle.unlock(); + if (childRet < 0) { + ret = ERR_IO_FAIL; + break; + } + ret = length; + hUSB->cvTransferSend.wait(lock, [hUSB]() { return hUSB->sendIOComplete; }); + break; + } + if (ret < 0) { + --hSession->sendRef; + if (hUSB->transferRecv != nullptr) { + libusb_cancel_transfer(hUSB->transferRecv); + } + } + return ret; +} + +bool HdcHostUSB::FindDeviceByID(HUSB hUSB, const char *usbMountPoint, libusb_context *ctxUSB) +{ + libusb_device **listDevices = nullptr; + bool ret = false; + char tmpStr[BUF_SIZE_TINY] = ""; + int busNum = 0; + int devNum = 0; + int curBus = 0; + int curDev = 0; + + int device_num = libusb_get_device_list(ctxUSB, &listDevices); + if (device_num <= 0) { + libusb_free_device_list(listDevices, 1); + return false; + } + if (strchr(usbMountPoint, '-') && EOK == strcpy_s(tmpStr, sizeof(tmpStr), usbMountPoint)) { + *strchr(tmpStr, '-') = '\0'; + busNum = atoi(tmpStr); + devNum = atoi(tmpStr + strlen(tmpStr) + 1); + } else + return false; + + int i = 0; + for (i = 0; i < device_num; ++i) { + struct libusb_device_descriptor desc; + if (LIBUSB_SUCCESS != libusb_get_device_descriptor(listDevices[i], &desc)) { + break; + } + curBus = libusb_get_bus_number(listDevices[i]); + curDev = libusb_get_device_address(listDevices[i]); + if ((curBus == busNum && curDev == devNum)) { + hUSB->device = listDevices[i]; + int childRet = OpenDeviceMyNeed(hUSB); + if (!childRet) { + ret = true; + } + break; + } + } + libusb_free_device_list(listDevices, 1); + return ret; +} + +bool HdcHostUSB::ReadyForWorkThread(HSession hSession) +{ + HdcUSBBase::ReadyForWorkThread(hSession); + return true; +}; + +// Determines that daemonInfo must have the device +HSession HdcHostUSB::ConnectDetectDaemon(const HSession hSession, const HDaemonInfo pdi) +{ + HdcServer *pServer = (HdcServer *)clsMainBase; + HUSB hUSB = hSession->hUSB; + hUSB->usbMountPoint = pdi->usbMountPoint; + hUSB->ctxUSB = ctxUSB; + if (!FindDeviceByID(hUSB, hUSB->usbMountPoint.c_str(), hUSB->ctxUSB)) { + pServer->FreeSession(hSession->sessionId); + return nullptr; + } + UpdateUSBDaemonInfo(hUSB, hSession, STATUS_CONNECTED); + RegisterReadCallback(hSession); + hUSB->usbMountPoint = pdi->usbMountPoint; + WRITE_LOG(LOG_DEBUG, "HSession HdcHostUSB::ConnectDaemon"); + + Base::StartWorkThread(&pServer->loopMain, pServer->SessionWorkThread, Base::FinishWorkThread, hSession); + // wait for thread up + while (hSession->childLoop.active_handles == 0) { + uv_sleep(1); + } + auto ctrl = pServer->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0); + Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); + return hSession; +} +} // namespace Hdc diff --git a/services/flashd/host/host_usb.h b/services/flashd/host/host_usb.h new file mode 100755 index 00000000..edafd789 --- /dev/null +++ b/services/flashd/host/host_usb.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_HOST_USB_H +#define HDC_HOST_USB_H +#include "host_common.h" + +namespace Hdc { +class HdcHostUSB : public HdcUSBBase { +public: + HdcHostUSB(const bool serverOrDaemonIn, void *ptrMainBase, void *ctxUSBin); + virtual ~HdcHostUSB(); + int Initial(); + int SendUSBRaw(HSession hSession, uint8_t *data, const int length); + HSession ConnectDetectDaemon(const HSession hSession, const HDaemonInfo pdi); + void Stop(); + void RemoveIgnoreDevice(string &mountInfo); + +private: + enum UsbCheckStatus { + HOST_USB_IGNORE = 1, + HOST_USB_READY, + HOST_USB_REGISTER, + }; + static int LIBUSB_CALL HotplugHostUSBCallback(libusb_context *ctx, libusb_device *device, + libusb_hotplug_event event, void *userData); + static void PenddingUSBIO(uv_idle_t *handle); + static void WatchDevPlugin(uv_timer_t *handle); + static void KickoutZombie(HSession hSession); + static void LIBUSB_CALL WriteUSBBulkCallback(struct libusb_transfer *transfer); + static void LIBUSB_CALL ReadUSBBulkCallback(struct libusb_transfer *transfer); + int StartupUSBWork(); + int CheckActiveConfig(libusb_device *device, HUSB hUSB); + int OpenDeviceMyNeed(HUSB hUSB); + int CheckDescriptor(HUSB hUSB); + bool IsDebuggableDev(const struct libusb_interface_descriptor *ifDescriptor); + bool ReadyForWorkThread(HSession hSession); + bool FindDeviceByID(HUSB hUSB, const char *usbMountPoint, libusb_context *ctxUSB); + bool DetectMyNeed(libusb_device *device, string &sn); + void SendUsbSoftReset(HUSB hUSB, uint32_t sessionId); + void RestoreHdcProtocol(HUSB hUsb, const uint8_t *buf, int bufSize); + void UpdateUSBDaemonInfo(HUSB hUSB, HSession hSession, uint8_t connStatus); + void RegisterReadCallback(HSession hSession); + void ReviewUsbNodeLater(string &nodeKey); + + uv_idle_t usbWork; + libusb_context *ctxUSB; + uv_timer_t devListWatcher; + map mapIgnoreDevice; + const int intervalDevCheck = 3000; + +private: +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/host/main.cpp b/services/flashd/host/main.cpp new file mode 100755 index 00000000..016e3dc2 --- /dev/null +++ b/services/flashd/host/main.cpp @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "server.h" +#include "server_for_client.h" + +#ifndef HARMONY_PROJECT +#include "../test/ut_command.h" +using namespace HdcTest; +#endif + +#include "server.h" +#include "server_for_client.h" +using namespace Hdc; + +static bool g_isServerMode = false; +static bool g_isPullServer = true; +static bool g_isPcDebugRun = false; +static bool g_isTCPorUSB = false; +static auto g_logLevel = LOG_LEVEL_FULL; +static int g_isTestMethod = 0; +static string g_connectKey = ""; +static string g_serverListenString = DEFAULT_SERVER_ADDR; + +namespace Hdc { +// return value: 0 == not command, 1 == one command, 2 == double command +int IsRegisterCommand(string &outCommand, const char *cmd, const char *cmdnext) +{ + string sCmdNext = cmdnext == nullptr ? string("") : string(cmdnext); + string doubleCommand = cmd + string(" ") + sCmdNext; + vector registerCommand; + registerCommand.push_back(CMDSTR_SOFTWARE_VERSION); + registerCommand.push_back(CMDSTR_SOFTWARE_HELP); + registerCommand.push_back(CMDSTR_TARGET_DISCOVER); + registerCommand.push_back(CMDSTR_LIST_TARGETS); + registerCommand.push_back(CMDSTR_CONNECT_ANY); + registerCommand.push_back(CMDSTR_CONNECT_TARGET); + registerCommand.push_back(CMDSTR_TARGET_REBOOT); + registerCommand.push_back(CMDSTR_SERVICE_KILL); + registerCommand.push_back(CMDSTR_SERVICE_START); + registerCommand.push_back(CMDSTR_TARGET_MODE); + + // flashd + registerCommand.push_back(CMDSTR_UPDATE_SYSTEM); + registerCommand.push_back(CMDSTR_FLASH_PARTITION); + registerCommand.push_back(CMDSTR_ERASE_PARTITION); + registerCommand.push_back(CMDSTR_FORMAT_PARTITION); + for (string v : registerCommand) { + if (doubleCommand == v) { + outCommand = doubleCommand; + return 2; + } + if (cmd == v) { + outCommand = cmd; + return 1; + } + } + return 0; +} + +void AppendCwdWhenTransfer(string &outCommand) +{ + if (outCommand != CMDSTR_FILE_SEND && outCommand != CMDSTR_FILE_RECV && outCommand != CMDSTR_APP_INSTALL + && outCommand != CMDSTR_APP_SIDELOAD) { + return; + } + char path[PATH_MAX] = ""; + size_t size = sizeof(path); + if (uv_cwd(path, &size) < 0) + return; + if (path[strlen(path) - 1] != Base::GetPathSep()) { + path[strlen(path)] = Base::GetPathSep(); + } + outCommand += outCommand.size() ? " -cwd " : "-cwd "; + outCommand += path; +} + +int SplitOptionAndCommand(int argc, const char **argv, string &outOption, string &outCommand) +{ + bool foundCommand = false; + int resultChild = 0; + // we want to start from 1, ignore argv[0], but it has issue + for (int i = 0; i < argc; ++i) { + if (!foundCommand) { + resultChild = IsRegisterCommand(outCommand, argv[i], (i == argc - 1) ? nullptr : argv[i + 1]); + if (resultChild > 0) { + foundCommand = true; + if (resultChild == 2) { + ++i; + } + AppendCwdWhenTransfer(outCommand); + continue; + } + } + if (foundCommand) { + outCommand += outCommand.size() ? " " : ""; + string rawCmd = argv[i]; + string packageCmd = Base::StringFormat("\"%s\"", argv[i]); + outCommand += rawCmd.find(" ") == string::npos ? rawCmd : packageCmd; + } else { + outOption += outOption.size() ? " " : ""; + outOption += argv[i]; + } + } + return 0; +} + +int RunServerMode(string &serverListenString) +{ + HdcServer server(true); + if (!server.Initial(serverListenString.c_str())) { + Base::PrintMessage("Initial failed"); + return -1; + } + server.WorkerPendding(); + return 0; +} + +int RunPcDebugMode(bool isPullServer, bool isTCPorUSB, int isTestMethod) +{ +#ifdef HARMONY_PROJECT + Base::PrintMessage("Not support command..."); +#else + pthread_t pt; + if (isPullServer) { + pthread_create(&pt, nullptr, TestBackgroundServerForClient, nullptr); + uv_sleep(200); // give time to start serverForClient,at least 200ms + } + TestRuntimeCommandSimple(isTCPorUSB, isTestMethod, true); + if (isPullServer) { + pthread_join(pt, nullptr); + WRITE_LOG(LOG_DEBUG, "!!!!!!!!!Server finish"); + } +#endif + return 0; +} + +int RunClientMode(string &commands, string &serverListenString, string &connectKey, bool isPullServer) +{ + uv_loop_t loopMain; + uv_loop_init(&loopMain); + HdcClient client(false, serverListenString, &loopMain); + if (!commands.size()) { + Base::PrintMessage("Unknow operation command..."); + TranslateCommand::Usage(); + return 0; + } + if (!strncmp(commands.c_str(), CMDSTR_SERVICE_START.c_str(), CMDSTR_SERVICE_START.size()) + || !strncmp(commands.c_str(), CMDSTR_SERVICE_KILL.c_str(), CMDSTR_SERVICE_KILL.size()) + || !strncmp(commands.c_str(), CMDSTR_GENERATE_KEY.c_str(), CMDSTR_GENERATE_KEY.size())) { + client.CtrlServiceWork(commands.c_str()); + return 0; + } + if (isPullServer && serverListenString == DEFAULT_SERVER_ADDR + && Base::ProgramMutex(SERVER_NAME.c_str(), true) == 0) { + // default pullup, just default listenstr.If want to customer listen-string, please use 'hdc -m -s lanip:port' + HdcServer::PullupServer(DEFAULT_SERVER_ADDR.c_str()); + uv_sleep(300); // give time to start serverForClient,at least 200ms + } + client.Initial(connectKey); + client.ExecuteCommand(commands.c_str()); + return 0; +} + +bool ParseServerListenString(string &serverListenString, char *optarg) +{ + if (strlen(optarg) > 24) { + Base::PrintMessage("Unknow content of parament '-s'"); + return false; + } + char buf[BUF_SIZE_TINY] = ""; + if (strcpy_s(buf, sizeof(buf), optarg) < 0) { + return false; + } + char *p = strchr(buf, ':'); + if (!p) { // Only port + if (strlen(buf) > 5) { + Base::PrintMessage("The port-string's length must < 5"); + return false; + } + int port = atoi(buf); + if (port <= 0 || port > MAX_IP_PORT) { + Base::PrintMessage("Port range incorrect"); + return false; + } + snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "127.0.0.1:%d", port); + serverListenString = buf; + } else { + *p = '\0'; + int port = atoi(p + 1); + sockaddr_in addr; + if ((port <= 0 || port > MAX_IP_PORT) || uv_ip4_addr(buf, port, &addr) < 0) { + Base::PrintMessage("-s content incorrect."); + return false; + } + serverListenString = optarg; + } + return true; +} + +bool GetCommandlineOptions(int optArgc, const char *optArgv[]) +{ + int ch = 0; + bool needExit = false; + opterr = 0; + // get option parameters first + while ((ch = getopt(optArgc, (char *const *)optArgv, "hvpfms:d:t:l:")) != -1) { + switch (ch) { + case 'h': { + string usage = Hdc::TranslateCommand::Usage(); + fprintf(stderr, "%s", usage.c_str()); + needExit = true; + return needExit; + } + case 'v': { + string ver = Base::GetVersion(); + fprintf(stdout, "%s\n", ver.c_str()); + needExit = true; + return needExit; + } + case 'f': { // [not-publish] + break; + } + case 'l': { + int logLevel = atoi(optarg); + if (logLevel < 0 || logLevel > LOG_LAST) { + Base::PrintMessage("Loglevel error!"); + needExit = true; + return needExit; + } + g_logLevel = logLevel; + Base::SetLogLevel(logLevel); + break; + } + case 'm': { // [not-publish] is server mode,or client mode + g_isServerMode = true; + break; + } + case 'p': { // [not-publish] not pullup server + g_isPullServer = false; + break; + } + case 't': { // key + if (strlen(optarg) > MAX_CONNECTKEY_SIZE) { + Base::PrintMessage("Sizeo of of parament '-t' %d is too long", strlen(optarg)); + needExit = true; + return needExit; + } + g_connectKey = optarg; + break; + } + case 's': { + if (!Hdc::ParseServerListenString(g_serverListenString, optarg)) { + needExit = true; + return needExit; + } + break; + } + case 'd': // [Undisclosed parameters] debug mode + g_isPcDebugRun = true; + if (optarg[0] == 't') { + g_isTCPorUSB = true; + } else if (optarg[0] == 'u') { + g_isTCPorUSB = false; + } else { + Base::PrintMessage("Unknown debug parameters"); + needExit = true; + return needExit; + } + g_isTestMethod = atoi(optarg + 1); + break; + case '?': + break; + default: { + Base::PrintMessage("Unknown parameters"); + needExit = true; + return needExit; + } + } + } + return needExit; +} +} + +#ifndef UNIT_TEST +// hdc -l4 -m -s ip:port|hdc -l4 -m +// hdc -l4 - s ip:port list targets +int main(int argc, const char *argv[]) +{ + string options; + string commands; + Hdc::SplitOptionAndCommand(argc, argv, options, commands); + int optArgc = 0; + char **optArgv = Base::SplitCommandToArgs(options.c_str(), &optArgc); + bool cmdOptionResult = GetCommandlineOptions(optArgc, (const char **)optArgv); + delete[]((char *)optArgv); + if (cmdOptionResult) { + return 0; + } + if (g_isServerMode) { + // -m server.Run alone in the background, no -s will be listen loopback address, + Base::SetLogLevel(g_logLevel); // default level LOG_LEVEL_FULL + Hdc::RunServerMode(g_serverListenString); + } else if (g_isPcDebugRun) { + Hdc::RunPcDebugMode(g_isPullServer, g_isTCPorUSB, g_isTestMethod); + } else { + Hdc::RunClientMode(commands, g_serverListenString, g_connectKey, g_isPullServer); + } + WRITE_LOG(LOG_DEBUG, "!!!!!!!!!Main finish main"); + return 0; +} +#endif // no UNIT_TEST diff --git a/services/flashd/host/server.cpp b/services/flashd/host/server.cpp new file mode 100755 index 00000000..90a4b994 --- /dev/null +++ b/services/flashd/host/server.cpp @@ -0,0 +1,795 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "server.h" + +namespace Hdc { +HdcServer::HdcServer(bool serverOrDaemonIn) + : HdcSessionBase(serverOrDaemonIn) +{ + clsTCPClt = nullptr; + clsUSBClt = nullptr; + clsServerForClient = nullptr; + uv_rwlock_init(&daemonAdmin); + uv_rwlock_init(&forwardAdmin); +} + +HdcServer::~HdcServer() +{ + WRITE_LOG(LOG_DEBUG, "~HdcServer"); + uv_rwlock_destroy(&daemonAdmin); + uv_rwlock_destroy(&forwardAdmin); +} + +void HdcServer::ClearInstanceResource() +{ + TryStopInstance(); + Base::TryCloseLoop(&loopMain, "HdcServer::~HdcServer"); + if (clsTCPClt) { + delete clsTCPClt; + } + if (clsUSBClt) { + delete clsUSBClt; + } + if (clsServerForClient) { + delete (static_cast(clsServerForClient)); + } +} + +void HdcServer::TryStopInstance() +{ + ClearSessions(); + if (clsTCPClt) { + clsTCPClt->Stop(); + } + if (clsUSBClt) { + clsUSBClt->Stop(); + } + if (clsServerForClient) { + ((HdcServerForClient *)clsServerForClient)->Stop(); + } + ReMainLoopForInstanceClear(); + ClearMapDaemonInfo(); +} + +bool HdcServer::Initial(const char *listenString) +{ + if (Base::ProgramMutex(SERVER_NAME.c_str(), false) != 0) { + WRITE_LOG(LOG_FATAL, "Other instance already running, program mutex failed"); + return false; + } + clsServerForClient = new HdcServerForClient(true, listenString, this, &loopMain); + clsTCPClt = new HdcHostTCP(true, this); + clsUSBClt = new HdcHostUSB(true, this, ctxUSB); + if (!clsServerForClient || !clsTCPClt || !clsUSBClt) { + WRITE_LOG(LOG_FATAL, "Class init failed"); + return false; + } + (static_cast(clsServerForClient))->Initial(); + clsUSBClt->Initial(); + return true; +} + +bool HdcServer::PullupServerWin32(const char *path, const char *listenString) +{ +#ifdef _WIN32 + char buf[BUF_SIZE_SMALL] = ""; + char shortPath[MAX_PATH] = ""; + int ret = GetShortPathName(path, shortPath, MAX_PATH); + std::string runPath = shortPath; + if (ret == 0) { + int err = GetLastError(); + WRITE_LOG(LOG_WARN, "GetShortPath path:[%s] err:%d errmsg:%s", path, err, strerror(err)); + string uvPath = path; + runPath = uvPath.substr(uvPath.find_last_of("/\\") + 1); + } + WRITE_LOG(LOG_DEBUG, "server shortpath:[%s] runPath:[%s]", shortPath, runPath.c_str()); + if (sprintf_s(buf, sizeof(buf), "%s -l4 -s %s -m", runPath.c_str(), listenString) < 0) { + return false; + } + WRITE_LOG(LOG_DEBUG, "Run server in debug-forground, cmd:%s", buf); + STARTUPINFO si; + Base::ZeroStruct(si); + si.cb = sizeof(STARTUPINFO); + PROCESS_INFORMATION pi; + Base::ZeroStruct(pi); +#ifndef HDC_DEBUG + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; +#endif + CreateProcess(nullptr, buf, nullptr, nullptr, true, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); +#endif + return true; +} + +// Only detects that the default call is in the loop address, the other tubes are not +bool HdcServer::PullupServer(const char *listenString) +{ + char path[BUF_SIZE_SMALL] = ""; + size_t nPathSize = sizeof(path); + int ret = uv_exepath(path, &nPathSize); + if (ret < 0) { + WRITE_LOG(LOG_WARN, "uvexepath ret:%d error:%s", ret, uv_err_name(ret)); + return false; + } + +#ifdef _WIN32 + if (!PullupServerWin32(path, listenString)) { + return false; + } +#else + pid_t pc = fork(); // create process as daemon process + if (pc < 0) { + return false; + } else if (!pc) { + int i; + const int maxFD = 1024; + for (i = 0; i < maxFD; ++i) { + // close file pipe + close(i); + } + execl(path, "hdc", "-m", "-s", listenString, nullptr); + exit(0); + return true; + } + // orig process +#endif + // wait little time, util backend-server work ready + uv_sleep(TIME_BASE); + return true; +} + +void HdcServer::ClearMapDaemonInfo() +{ + map::iterator iter; + uv_rwlock_rdlock(&daemonAdmin); + for (iter = mapDaemon.begin(); iter != mapDaemon.end();) { + string sKey = iter->first; + HDaemonInfo hDi = iter->second; + delete hDi; + ++iter; + } + uv_rwlock_rdunlock(&daemonAdmin); + uv_rwlock_wrlock(&daemonAdmin); + mapDaemon.clear(); + uv_rwlock_wrunlock(&daemonAdmin); +} + +void HdcServer::BuildDaemonVisableLine(HDaemonInfo hdi, bool fullDisplay, string &out) +{ + if (fullDisplay) { + string sConn; + string sStatus; + switch (hdi->connType) { + case CONN_TCP: + sConn = "TCP"; + break; + case CONN_USB: + sConn = "USB"; + break; + + case CONN_BT: + sConn = "BT"; + break; + default: + sConn = "UNKNOW"; + break; + } + switch (hdi->connStatus) { + case STATUS_READY: + sStatus = "Ready"; + break; + case STATUS_CONNECTED: + sStatus = "Connected"; + break; + case STATUS_OFFLINE: + sStatus = "Offline"; + break; + default: + sStatus = "UNKNOW"; + break; + } + out = Base::StringFormat("%s\t\t%s\t%s\t%s\n", hdi->connectKey.c_str(), sConn.c_str(), sStatus.c_str(), + hdi->devName.c_str()); + } else { + if (hdi->connStatus == STATUS_CONNECTED) { + out = Base::StringFormat("%s\n", hdi->connectKey.c_str()); + } + } +} + +string HdcServer::GetDaemonMapList(uint8_t opType) +{ + string ret; + bool fullDisplay = false; + if (OP_GET_STRLIST_FULL == opType) { + fullDisplay = true; + } + uv_rwlock_rdlock(&daemonAdmin); + map::iterator iter; + string echoLine; + for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) { + HDaemonInfo di = iter->second; + if (!di) { + continue; + } + echoLine = ""; + BuildDaemonVisableLine(di, fullDisplay, echoLine); + ret += echoLine; + } + uv_rwlock_rdunlock(&daemonAdmin); + return ret; +} + +void HdcServer::GetDaemonMapOnlyOne(HDaemonInfo &hDaemonInfoInOut) +{ + uv_rwlock_rdlock(&daemonAdmin); + string key; + for (auto &i : mapDaemon) { + if (i.second->connStatus == STATUS_CONNECTED) { + if (key == STRING_EMPTY) { + key = i.first; + } else { + key = STRING_EMPTY; + break; + } + } + } + if (key.size() > 0) { + hDaemonInfoInOut = mapDaemon[key]; + } + uv_rwlock_rdunlock(&daemonAdmin); +} + +string HdcServer::AdminDaemonMap(uint8_t opType, const string &connectKey, HDaemonInfo &hDaemonInfoInOut) +{ + string sRet; + switch (opType) { + case OP_ADD: { + HDaemonInfo pdiNew = new HdcDaemonInformation(); + *pdiNew = *hDaemonInfoInOut; + uv_rwlock_wrlock(&daemonAdmin); + if (!mapDaemon[hDaemonInfoInOut->connectKey]) { + mapDaemon[hDaemonInfoInOut->connectKey] = pdiNew; + } + uv_rwlock_wrunlock(&daemonAdmin); + break; + } + case OP_GET_STRLIST: + case OP_GET_STRLIST_FULL: { + sRet = GetDaemonMapList(opType); + break; + } + case OP_QUERY: { + uv_rwlock_rdlock(&daemonAdmin); + if (mapDaemon.count(connectKey)) { + hDaemonInfoInOut = mapDaemon[connectKey]; + } + uv_rwlock_rdunlock(&daemonAdmin); + break; + } + case OP_REMOVE: { + uv_rwlock_wrlock(&daemonAdmin); + if (mapDaemon.count(connectKey)) { + mapDaemon.erase(connectKey); + } + uv_rwlock_wrunlock(&daemonAdmin); + break; + } + case OP_GET_ANY: { + uv_rwlock_rdlock(&daemonAdmin); + map::iterator iter; + for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) { + HDaemonInfo di = iter->second; + // usb will be auto connected + if (di->connStatus == STATUS_READY || di->connStatus == STATUS_CONNECTED) { + hDaemonInfoInOut = di; + break; + } + } + uv_rwlock_rdunlock(&daemonAdmin); + break; + } + case OP_GET_ONLY: { + GetDaemonMapOnlyOne(hDaemonInfoInOut); + break; + } + case OP_UPDATE: { // Cannot update the Object HDi lower key value by direct value + uv_rwlock_wrlock(&daemonAdmin); + HDaemonInfo hdi = mapDaemon[hDaemonInfoInOut->connectKey]; + if (hdi) { + *mapDaemon[hDaemonInfoInOut->connectKey] = *hDaemonInfoInOut; + } + uv_rwlock_wrunlock(&daemonAdmin); + break; + } + default: + break; + } + return sRet; +} + +void HdcServer::NotifyInstanceSessionFree(HSession hSession, bool freeOrClear) +{ + HDaemonInfo hdiOld = nullptr; + AdminDaemonMap(OP_QUERY, hSession->connectKey, hdiOld); + if (hdiOld == nullptr) { + return; + } + if (!freeOrClear) { // step1 + // update + HdcDaemonInformation diNew = *hdiOld; + diNew.connStatus = STATUS_OFFLINE; + HDaemonInfo hdiNew = &diNew; + AdminDaemonMap(OP_UPDATE, hSession->connectKey, hdiNew); + } else { // step2 + string usbMountPoint = hdiOld->usbMountPoint; + constexpr int waitDaemonReconnect = UV_DEFAULT_INTERVAL; // wait little time for daemon reinit + auto funcDelayUsbNotify = [this, usbMountPoint](const uint8_t flag, string &msg, const void *) -> void { + string s = usbMountPoint; + clsUSBClt->RemoveIgnoreDevice(s); + }; + if (usbMountPoint.size() > 0) { + // wait time for daemon reconnect + // If removed from maplist, the USB module will be reconnected, so it needs to wait for a while + Base::DelayDoSimple(&loopMain, waitDaemonReconnect, funcDelayUsbNotify); + } + } +} + +bool HdcServer::HandServerAuth(HSession hSession, SessionHandShake &handshake) +{ + bool ret = false; + int retChild = 0; + string bufString; + switch (handshake.authType) { + case AUTH_TOKEN: { + void *ptr = nullptr; + bool retChild = HdcAuth::KeylistIncrement(hSession->listKey, hSession->authKeyIndex, &ptr); + // HdcAuth::FreeKey will be effect at funciton 'FreeSession' + if (!retChild) { + // Iteration call certificate authentication + handshake.authType = AUTH_PUBLICKEY; + ret = HandServerAuth(hSession, handshake); + break; + } + char sign[BUF_SIZE_DEFAULT2] = { 0 }; + retChild = HdcAuth::AuthSign(ptr, (const unsigned char *)handshake.buf.c_str(), handshake.buf.size(), sign); + if (!retChild) { + break; + } + handshake.buf = string(sign, retChild); + handshake.authType = AUTH_SIGNATURE; + bufString = SerialStruct::SerializeToString(handshake); + Send(hSession->sessionId, 0, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), bufString.size()); + ret = true; + break; + } + case AUTH_PUBLICKEY: { + char bufPrivateKey[BUF_SIZE_DEFAULT2] = ""; + retChild = HdcAuth::GetPublicKeyFileBuf((unsigned char *)bufPrivateKey, sizeof(bufPrivateKey)); + if (!retChild) { + break; + } + handshake.buf = string(bufPrivateKey, retChild); + handshake.authType = AUTH_PUBLICKEY; + bufString = SerialStruct::SerializeToString(handshake); + Send(hSession->sessionId, 0, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), bufString.size()); + ret = true; + break; + } + default: + break; + } + return ret; +} + +bool HdcServer::ServerSessionHandshake(HSession hSession, uint8_t *payload, int payloadSize) +{ + // session handshake step3 + string s = string((char *)payload, payloadSize); + Hdc::HdcSessionBase::SessionHandShake handshake; + SerialStruct::ParseFromString(handshake, s); + if (handshake.banner != HANDSHAKE_MESSAGE.c_str()) { + WRITE_LOG(LOG_DEBUG, "Hello failed"); + return false; + } + if (handshake.authType != AUTH_OK) { + if (!HandServerAuth(hSession, handshake)) { + WRITE_LOG(LOG_DEBUG, "Auth failed"); + return false; + } + return true; + } + // handshake auth OK + HDaemonInfo hdiOld = nullptr; + AdminDaemonMap(OP_QUERY, hSession->connectKey, hdiOld); + if (!hdiOld) { + return false; + } + HdcDaemonInformation diNew = *hdiOld; + HDaemonInfo hdiNew = &diNew; + // update + hdiNew->connStatus = STATUS_CONNECTED; + if (handshake.buf.size() > sizeof(hdiNew->devName) || !handshake.buf.size()) { + hdiNew->devName = "unknow..."; + } else { + hdiNew->devName = handshake.buf; + } + AdminDaemonMap(OP_UPDATE, hSession->connectKey, hdiNew); + hSession->handshakeOK = true; + return true; +} + +bool HdcServer::FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, + const int payloadSize) +{ + bool ret = true; + HdcServerForClient *pSfc = static_cast(clsServerForClient); + // When you first initialize, ChannelID may be 0 + HChannel hChannel = pSfc->AdminChannel(OP_QUERY, channelId, nullptr); + if (CMD_KERNEL_HANDSHAKE == command) { + ret = ServerSessionHandshake(hSession, payload, payloadSize); + WRITE_LOG(LOG_DEBUG, "Session handshake %s", ret ? "successful" : "failed"); + return ret; + } + if (!hChannel) { + if (command == CMD_KERNEL_CHANNEL_CLOSE) { + // Daemon close channel and want to notify server close channel also, but it may has been + // closed by herself + } else { + // Client may be ctrl+c and Server remove channel. notify server async + } + Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1); + return true; + } + switch (command) { + case CMD_KERNEL_ECHO_RAW: { // Native shell data output + pSfc->EchoClientRaw(channelId, payload, payloadSize); + break; + } + case CMD_KERNEL_ECHO: { + MessageLevel level = (MessageLevel)*payload; + string s(reinterpret_cast(payload + 1), payloadSize - 1); + pSfc->EchoClient(hChannel, level, s.c_str()); + WRITE_LOG(LOG_DEBUG, "CMD_KERNEL_ECHO size:%d", payloadSize - 1); + break; + } + case CMD_KERNEL_CHANNEL_CLOSE: { + WRITE_LOG(LOG_DEBUG, "CMD_KERNEL_CHANNEL_CLOSE channelid:%d", channelId); + ClearOwnTasks(hSession, channelId); + // Forcibly closing the tcp handle here may result in incomplete data reception on the client side + HdcServerForClient *sfc = static_cast(hChannel->clsChannel); + sfc->FreeChannel(hChannel->channelId); + if (*payload == 1) { + --(*payload); + Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1); + } + break; + } + case CMD_FORWARD_SUCCESS: { + // add to local + HdcForwardInformation di; + HForwardInfo pdiNew = &di; + pdiNew->channelId = channelId; + pdiNew->sessionId = hSession->sessionId; + pdiNew->forwardDirection = ((char *)payload)[0] == '1'; + pdiNew->taskString = (char *)payload + 2; + AdminForwardMap(OP_ADD, STRING_EMPTY, pdiNew); + Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP); // detch client channel + break; + } + default: { + HSession hSession = AdminSession(OP_QUERY, hChannel->targetSessionId, nullptr); + if (!hSession) { + return false; + } + ret = DispatchTaskData(hSession, hChannel->channelId, command, payload, payloadSize); + break; + } + } + return ret; +} + +void HdcServer::BuildForwardVisableLine(bool fullOrSimble, HForwardInfo hfi, string &echo) +{ + string buf; + if (fullOrSimble) { + buf = Base::StringFormat("'%s'\t%s\n", hfi->taskString.c_str(), + hfi->forwardDirection ? "[Forward]" : "[Reverse]"); + } else { + buf = Base::StringFormat("%s\n", hfi->taskString.c_str()); + } + echo += buf; +} + +string HdcServer::AdminForwardMap(uint8_t opType, const string &taskString, HForwardInfo &hForwardInfoInOut) +{ + string sRet; + switch (opType) { + case OP_ADD: { + HForwardInfo pfiNew = new HdcForwardInformation(); + *pfiNew = *hForwardInfoInOut; + uv_rwlock_wrlock(&forwardAdmin); + if (!mapForward[hForwardInfoInOut->taskString]) { + mapForward[hForwardInfoInOut->taskString] = pfiNew; + } + uv_rwlock_wrunlock(&forwardAdmin); + break; + } + case OP_GET_STRLIST: + case OP_GET_STRLIST_FULL: { + uv_rwlock_rdlock(&forwardAdmin); + map::iterator iter; + for (iter = mapForward.begin(); iter != mapForward.end(); ++iter) { + HForwardInfo di = iter->second; + if (!di) { + continue; + } + BuildForwardVisableLine(opType == OP_GET_STRLIST_FULL, di, sRet); + } + uv_rwlock_rdunlock(&forwardAdmin); + break; + } + case OP_QUERY: { + uv_rwlock_rdlock(&forwardAdmin); + if (mapForward.count(taskString)) { + hForwardInfoInOut = mapForward[taskString]; + } + uv_rwlock_rdunlock(&forwardAdmin); + break; + } + case OP_REMOVE: { + uv_rwlock_wrlock(&forwardAdmin); + if (mapForward.count(taskString)) { + mapForward.erase(taskString); + } + uv_rwlock_wrunlock(&forwardAdmin); + break; + } + default: + break; + } + return sRet; +} + +void HdcServer::UsbPreConnect(uv_timer_t *handle) +{ + HSession hSession = (HSession)handle->data; + bool stopLoop = false; + HdcServer *hdcServer = (HdcServer *)hSession->classInstance; + const int usbConnectRetryMax = 5; + while (true) { + WRITE_LOG(LOG_DEBUG, "HdcServer::UsbPreConnect"); + if (++hSession->hUSB->retryCount > usbConnectRetryMax) { // max 15s + hdcServer->FreeSession(hSession->sessionId); + stopLoop = true; + break; + } + HDaemonInfo pDi = nullptr; + if (hSession->connectKey == "any") { + hdcServer->AdminDaemonMap(OP_GET_ANY, hSession->connectKey, pDi); + } else { + hdcServer->AdminDaemonMap(OP_QUERY, hSession->connectKey, pDi); + } + if (!pDi || !pDi->usbMountPoint.size()) { + break; + } + HdcHostUSB *hdcHostUSB = (HdcHostUSB *)hSession->classModule; + hdcHostUSB->ConnectDetectDaemon(hSession, pDi); + stopLoop = true; + break; + } + if (stopLoop && !uv_is_closing((const uv_handle_t *)handle)) { + uv_close((uv_handle_t *)handle, Base::CloseTimerCallback); + } +} + +// -1,has old,-2 error +int HdcServer::CreateConnect(const string &connectKey) +{ + uint8_t connType = 0; + if (connectKey.find(":") != std::string::npos) { // TCP + connType = CONN_TCP; + } else { // USB + connType = CONN_USB; + } + HDaemonInfo hdi = nullptr; + if (connectKey == "any") { + return RET_SUCCESS; + } + AdminDaemonMap(OP_QUERY, connectKey, hdi); + if (hdi == nullptr) { + HdcDaemonInformation di; + Base::ZeroStruct(di); + di.connectKey = connectKey; + di.connType = connType; + di.connStatus = STATUS_UNKNOW; + HDaemonInfo pDi = (HDaemonInfo)&di; + AdminDaemonMap(OP_ADD, "", pDi); + AdminDaemonMap(OP_QUERY, connectKey, hdi); + } + if (!hdi || hdi->connStatus == STATUS_CONNECTED) { + return ERR_GENERIC; + } + HSession hSession = nullptr; + if (CONN_TCP == connType) { + hSession = clsTCPClt->ConnectDaemon(connectKey); + } else { + hSession = MallocSession(true, CONN_USB, clsUSBClt); + hSession->connectKey = connectKey; + uv_timer_t *waitTimeDoCmd = new uv_timer_t; + uv_timer_init(&loopMain, waitTimeDoCmd); + waitTimeDoCmd->data = hSession; + uv_timer_start(waitTimeDoCmd, UsbPreConnect, 10, 100); + } + if (!hSession) { + return ERR_BUF_ALLOC; + } + HDaemonInfo hdiQuery = nullptr; + AdminDaemonMap(OP_QUERY, connectKey, hdiQuery); + if (hdiQuery) { + HdcDaemonInformation diNew = *hdiQuery; + diNew.hSession = hSession; + HDaemonInfo hdiNew = &diNew; + AdminDaemonMap(OP_UPDATE, hdiQuery->connectKey, hdiNew); + } + return RET_SUCCESS; +} + +void HdcServer::AttachChannel(HSession hSession, const uint32_t channelId) +{ + HdcServerForClient *hSfc = static_cast(clsServerForClient); + HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr); + int ret = 0; + if (!hChannel) { + return; + } + uv_tcp_init(&hSession->childLoop, &hChannel->hChildWorkTCP); + hChannel->hChildWorkTCP.data = hChannel; + hChannel->targetSessionId = hSession->sessionId; + if ((ret = uv_tcp_open((uv_tcp_t *)&hChannel->hChildWorkTCP, hChannel->fdChildWorkTCP)) < 0) { + WRITE_LOG(LOG_DEBUG, "Hdcserver AttachChannel uv_tcp_open failed %s, channelid:%d fdChildWorkTCP:%d", + uv_err_name(ret), hChannel->channelId, hChannel->fdChildWorkTCP); + Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP); + return; + } + Base::SetTcpOptions((uv_tcp_t *)&hChannel->hChildWorkTCP); + uv_read_start((uv_stream_t *)&hChannel->hChildWorkTCP, hSfc->AllocCallback, hSfc->ReadStream); +}; + +void HdcServer::DeatchChannel(HSession hSession, const uint32_t channelId) +{ + HdcServerForClient *hSfc = static_cast(clsServerForClient); + HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr); + if (!hChannel) { + return; + } + if (hChannel->childCleared) { + WRITE_LOG(LOG_DEBUG, "Childchannel has already freed, cid:%d", channelId); + return; + } + uint8_t count = 1; + Send(hSession->sessionId, hChannel->channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1); + if (uv_is_closing((const uv_handle_t *)&hChannel->hChildWorkTCP)) { + Base::DoNextLoop(&hSession->childLoop, hChannel, [](const uint8_t flag, string &msg, const void *data) { + HChannel hChannel = (HChannel)data; + hChannel->childCleared = true; + WRITE_LOG(LOG_DEBUG, "Childchannel free direct, cid:%d", hChannel->channelId); + }); + } else { + Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP, [](uv_handle_t *handle) -> void { + HChannel hChannel = (HChannel)handle->data; + hChannel->childCleared = true; + WRITE_LOG(LOG_DEBUG, "Childchannel free callback, cid:%d", hChannel->channelId); + }); + } +}; + +bool HdcServer::ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, + uint8_t *bufPtr, const int size) +{ + HdcServerForClient *hSfc = static_cast(clsServerForClient); + HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr); + HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr); + if (!hChannel || !hSession) { + return false; + } + return FetchCommand(hSession, channelId, command, bufPtr, size); +} + +// clang-format off +bool HdcServer::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, + const uint16_t command, uint8_t *payload, const int payloadSize) +// clang-format on +{ + bool ret = true; + hTaskInfo->ownerSessionClass = this; + switch (command) { + case CMD_UNITY_BUGREPORT_INIT: + case CMD_UNITY_BUGREPORT_DATA: + ret = TaskCommandDispatch(hTaskInfo, TYPE_UNITY, command, payload, payloadSize); + break; + case CMD_FILE_INIT: + case CMD_FILE_BEGIN: + case CMD_FILE_CHECK: + case CMD_FILE_DATA: + case CMD_FILE_FINISH: + ret = TaskCommandDispatch(hTaskInfo, TASK_FILE, command, payload, payloadSize); + break; + case CMD_FORWARD_INIT: + case CMD_FORWARD_CHECK: + case CMD_FORWARD_CHECK_RESULT: + case CMD_FORWARD_ACTIVE_MASTER: + case CMD_FORWARD_DATA: + case CMD_FORWARD_FREE_CONTEXT: + ret = TaskCommandDispatch(hTaskInfo, TASK_FORWARD, command, payload, payloadSize); + break; + case CMD_APP_INIT: + case CMD_APP_SIDELOAD: + case CMD_APP_BEGIN: + case CMD_APP_FINISH: + case CMD_APP_UNINSTALL: + ret = TaskCommandDispatch(hTaskInfo, TASK_APP, command, payload, payloadSize); + break; + case CMD_UPDATER_UPDATE_INIT: + case CMD_UPDATER_FLASH_INIT: + case CMD_UPDATER_CHECK: + case CMD_UPDATER_BEGIN: + case CMD_UPDATER_DATA: + case CMD_UPDATER_FINISH: + case CMD_UPDATER_ERASE: + case CMD_UPDATER_FORMAT: + case CMD_UPDATER_PROGRESS: + ret = TaskCommandDispatch(hTaskInfo, TASK_UPDATER, command, payload, payloadSize); + break; + default: + WRITE_LOG(LOG_WARN, "RedirectToTask error command:%d ", command); + ret = false; + break; + } + return ret; +} + +bool HdcServer::RemoveInstanceTask(const uint8_t op, HTaskInfo hTask) +{ + bool ret = true; + switch (hTask->taskType) { + case TYPE_SHELL: + WRITE_LOG(LOG_DEBUG, "Server not enable unity/shell"); + break; + case TYPE_UNITY: + ret = DoTaskRemove(hTask, op); + break; + case TASK_FILE: + ret = DoTaskRemove(hTask, op); + break; + case TASK_FORWARD: + ret = DoTaskRemove(hTask, op); + break; + case TASK_APP: + ret = DoTaskRemove(hTask, op); + break; + case TASK_UPDATER: + ret = DoTaskRemove(hTask, op); + break; + default: + ret = false; + break; + } + return ret; +} +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/host/server.h b/services/flashd/host/server.h new file mode 100755 index 00000000..e1e66810 --- /dev/null +++ b/services/flashd/host/server.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_SERVER_H +#define HDC_SERVER_H +#include "host_common.h" + +namespace Hdc { +class HdcServer : public HdcSessionBase { +public: + HdcServer(bool serverOrDaemonIn); + virtual ~HdcServer(); + bool FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, + const int payloadSize); + string AdminDaemonMap(uint8_t opType, const string &connectKey, HDaemonInfo &hDaemonInfoInOut); + string AdminForwardMap(uint8_t opType, const string &taskString, HForwardInfo &hForwardInfoInOut); + int CreateConnect(const string &connectKey); + bool Initial(const char *listenString); + void AttachChannel(HSession hSession, const uint32_t channelId); + void DeatchChannel(HSession hSession, const uint32_t channelId); + static bool PullupServer(const char *listenString); + static void UsbPreConnect(uv_timer_t *handle); + void NotifyInstanceSessionFree(HSession hSession, bool freeOrClear); + + HdcHostTCP *clsTCPClt; + HdcHostUSB *clsUSBClt; + void *clsServerForClient; + +private: + void ClearInstanceResource(); + void BuildDaemonVisableLine(HDaemonInfo hdi, bool fullDisplay, string &out); + void BuildForwardVisableLine(bool fullOrSimble, HForwardInfo hfi, string &echo); + void ClearMapDaemonInfo(); + bool ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, uint8_t *bufPtr, + const int size); + bool RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, const uint16_t command, + uint8_t *payload, const int payloadSize); + bool RemoveInstanceTask(const uint8_t op, HTaskInfo hTask); + void BuildForwardVisableLine(HDaemonInfo hdi, char *out, int sizeOutBuf); + bool HandServerAuth(HSession hSession, SessionHandShake &handshake); + string GetDaemonMapList(uint8_t opType); + bool ServerSessionHandshake(HSession hSession, uint8_t *payload, int payloadSize); + void GetDaemonMapOnlyOne(HDaemonInfo &hDaemonInfoInOut); + void TryStopInstance(); + static bool PullupServerWin32(const char *path, const char *listenString); + + uv_rwlock_t daemonAdmin; + map mapDaemon; + uv_rwlock_t forwardAdmin; + map mapForward; +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/host/server_for_client.cpp b/services/flashd/host/server_for_client.cpp new file mode 100755 index 00000000..fc6feb17 --- /dev/null +++ b/services/flashd/host/server_for_client.cpp @@ -0,0 +1,674 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "server_for_client.h" +#include "server.h" + +namespace Hdc { +HdcServerForClient::HdcServerForClient(const bool serverOrClient, const string &addrString, void *pClsServer, + uv_loop_t *loopMainIn) + : HdcChannelBase(serverOrClient, addrString, loopMainIn) +{ + clsServer = pClsServer; +} + +HdcServerForClient::~HdcServerForClient() +{ + WRITE_LOG(LOG_DEBUG, "~HdcServerForClient"); +} + +void HdcServerForClient::Stop() +{ + Base::TryCloseHandle((uv_handle_t *)&tcpListen); +} + +uint16_t HdcServerForClient::GetTCPListenPort() +{ + return channelPort; +} + +void HdcServerForClient::AcceptClient(uv_stream_t *server, int status) +{ + uv_tcp_t *pServTCP = (uv_tcp_t *)server; + HdcServerForClient *thisClass = (HdcServerForClient *)pServTCP->data; + HChannel hChannel = nullptr; + uint32_t uid = thisClass->MallocChannel(&hChannel); + if (!hChannel) { + return; + } + if (uv_accept(server, (uv_stream_t *)&hChannel->hWorkTCP) < 0) { + thisClass->FreeChannel(uid); + return; + } + WRITE_LOG(LOG_DEBUG, "HdcServerForClient acceptClient"); + // limit first recv + int bufMaxSize = 0; + uv_recv_buffer_size((uv_handle_t *)&hChannel->hWorkTCP, &bufMaxSize); + auto funcChannelHeaderAlloc = [](uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) -> void { + HChannel context = (HChannel)handle->data; + Base::ReallocBuf(&context->ioBuf, &context->bufSize, context->availTailIndex, sizeWanted); + buf->base = (char *)context->ioBuf + context->availTailIndex; + buf->len = sizeof(struct ChannelHandShake) + DWORD_SERIALIZE_SIZE; // only recv static size + }; + // first packet static size, after this packet will be dup for normal recv + uv_read_start((uv_stream_t *)&hChannel->hWorkTCP, funcChannelHeaderAlloc, ReadStream); + // channel handshake step1 + struct ChannelHandShake handShake; + Base::ZeroStruct(handShake); + if (EOK == strcpy_s(handShake.banner, sizeof(handShake.banner), HANDSHAKE_MESSAGE.c_str())) { + handShake.channelId = htonl(hChannel->channelId); + thisClass->Send(hChannel->channelId, (uint8_t *)&handShake, sizeof(struct ChannelHandShake)); + } +} + +void HdcServerForClient::SetTCPListen() +{ + tcpListen.data = this; + struct sockaddr_in addr; + uv_tcp_init(loopMain, &tcpListen); + uv_ip4_addr(channelHost.c_str(), channelPort, &addr); + uv_tcp_bind(&tcpListen, (const struct sockaddr *)&addr, 0); + uv_listen((uv_stream_t *)&tcpListen, 128, (uv_connection_cb)AcceptClient); +} + +int HdcServerForClient::Initial() +{ + if (!clsServer) { + WRITE_LOG(LOG_FATAL, "Module client initial failed"); + return -1; + } + if (!channelHostPort.size() || !channelHost.size() || !channelPort) { + WRITE_LOG(LOG_FATAL, "Listen string initial failed"); + return -2; + } + SetTCPListen(); + return 0; +} + +void HdcServerForClient::EchoClient(HChannel hChannel, MessageLevel level, const char *msg, ...) +{ + string logInfo = ""; + switch (level) { + case MSG_FAIL: + logInfo = MESSAGE_FAIL; + break; + case MSG_INFO: + logInfo = MESSAGE_INFO; + break; + default: // successful, not append extra info + break; + } + va_list vaArgs; + va_start(vaArgs, msg); + string log = logInfo + Base::StringFormat(msg, vaArgs); + va_end(vaArgs); + if (log.back() != '\n') { + log += "\r\n"; + } + Send(hChannel->channelId, (uint8_t *)log.c_str(), log.size()); +} + +void HdcServerForClient::EchoClientRaw(const uint32_t channelId, uint8_t *payload, const int payloadSize) +{ + Send(channelId, payload, payloadSize); +} + +bool HdcServerForClient::SendToDaemon(HChannel hChannel, const uint16_t commandFlag, uint8_t *bufPtr, const int bufSize) +{ + HDaemonInfo hdi = nullptr; + bool ret = false; + HdcServer *ptrServer = (HdcServer *)clsServer; + while (true) { + ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi); + if (hdi == nullptr) { + break; + } + if (hdi->connStatus != STATUS_CONNECTED) { + break; + } + if (!hdi->hSession) { + break; + } + if (ptrServer->Send(hdi->hSession->sessionId, hChannel->channelId, commandFlag, bufPtr, bufSize) < 0) { + break; + } + ret = true; + break; + } + return ret; +} + +void HdcServerForClient::OrderFindTargets(HChannel hChannel) +{ + int count = 0; + EchoClient(hChannel, MSG_INFO, "Please add HDC server's firewall ruler to allow udp incoming, udpport:%d", + DEFAULT_PORT); + HdcServer *ptrServer = (HdcServer *)clsServer; + ptrServer->clsTCPClt->FindLanDaemon(); + list &lst = ptrServer->clsTCPClt->lstDaemonResult; + // refresh main list + HdcDaemonInformation di; + while (!lst.empty()) { + Base::ZeroStruct(di); + ++count; + di.connectKey = lst.front(); + di.connType = CONN_TCP; + di.connStatus = STATUS_READY; + HDaemonInfo pDi = (HDaemonInfo)&di; + ptrServer->AdminDaemonMap(OP_ADD, STRING_EMPTY, pDi); + lst.pop_front(); + } + EchoClient(hChannel, MSG_INFO, "Broadcast find daemon, total:%d", count); +#ifdef UNIT_TEST + string bufString = std::to_string(count); + Base::WriteBinFile((UT_TMP_PATH + "/base-discover.result").c_str(), (uint8_t *)bufString.c_str(), bufString.size(), + true); +#endif +} + +void HdcServerForClient::OrderConnecTargetResult(uv_timer_t *req) +{ + HChannel hChannel = (HChannel)req->data; + HdcServerForClient *thisClass = (HdcServerForClient *)hChannel->clsChannel; + HdcServer *ptrServer = (HdcServer *)thisClass->clsServer; + bool bConnectOK = false; + bool bExitRepet = false; + HDaemonInfo hdi = nullptr; + string sRet; + string target = std::string(hChannel->bufStd + 2); + if (target == "any") { + ptrServer->AdminDaemonMap(OP_GET_ANY, target, hdi); + } else { + ptrServer->AdminDaemonMap(OP_QUERY, target, hdi); + } + if (hdi && STATUS_CONNECTED == hdi->connStatus) { + bConnectOK = true; + } + while (true) { + if (bConnectOK) { + bExitRepet = true; + sRet = "Connect OK"; + thisClass->EchoClient(hChannel, MSG_OK, (char *)sRet.c_str()); + break; + } else { + uint16_t *bRetryCount = (uint16_t *)hChannel->bufStd; + ++(*bRetryCount); + if (*bRetryCount > 500) { + // 5s + bExitRepet = true; + sRet = "Connect failed"; + thisClass->EchoClient(hChannel, MSG_FAIL, (char *)sRet.c_str()); + break; + } + } + break; + } + if (bExitRepet) { + thisClass->FreeChannel(hChannel->channelId); + Base::TryCloseHandle((const uv_handle_t *)req, Base::CloseTimerCallback); + } +} + +bool HdcServerForClient::NewConnectTry(void *ptrServer, HChannel hChannel, const string &connectKey) +{ + int childRet = ((HdcServer *)ptrServer)->CreateConnect(connectKey); + bool ret = false; + if (-1 == childRet) { + EchoClient(hChannel, MSG_INFO, "Target is connected, repeat operation"); + } else if (-2 == childRet) { + EchoClient(hChannel, MSG_FAIL, "CreateConnect failed"); + WRITE_LOG(LOG_FATAL, "CreateConnect failed"); + } else { + Base::ZeroBuf(hChannel->bufStd, 2); + childRet = snprintf_s(hChannel->bufStd + 2, sizeof(hChannel->bufStd) - 2, sizeof(hChannel->bufStd) - 3, "%s", + (char *)connectKey.c_str()); + if (childRet > 0) { + Base::TimerUvTask(loopMain, hChannel, OrderConnecTargetResult, 10); + ret = true; + } + } + return ret; +} + +bool HdcServerForClient::CommandRemoveSession(HChannel hChannel, const char *connectKey) +{ + HdcServer *ptrServer = (HdcServer *)clsServer; + HDaemonInfo hdiOld = nullptr; + ((HdcServer *)ptrServer)->AdminDaemonMap(OP_QUERY, connectKey, hdiOld); + if (!hdiOld) { + EchoClient(hChannel, MSG_FAIL, "No target available"); + return false; + } + ((HdcServer *)ptrServer)->FreeSession(hdiOld->hSession->sessionId); + return true; +} + +bool HdcServerForClient::CommandRemoveForward(const string &forwardKey) +{ + HdcServer *ptrServer = (HdcServer *)clsServer; + HForwardInfo hfi = nullptr; + ptrServer->AdminForwardMap(OP_QUERY, forwardKey, hfi); + if (!hfi) { + return false; + } + HSession hSession = ptrServer->AdminSession(OP_QUERY, hfi->sessionId, nullptr); + if (!hSession) { + return false; + } + ptrServer->ClearOwnTasks(hSession, hfi->channelId); + FreeChannel(hfi->channelId); + hfi = nullptr; + ptrServer->AdminForwardMap(OP_REMOVE, forwardKey, hfi); + return true; +} + +void HdcServerForClient::GetTargetList(HChannel hChannel, void *formatCommandInput) +{ + TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput; + HdcServer *ptrServer = (HdcServer *)clsServer; + uint16_t cmd = OP_GET_STRLIST; + if (formatCommand->parameters == "v") { + cmd = OP_GET_STRLIST_FULL; + } + HDaemonInfo hdi = nullptr; + string sRet = ptrServer->AdminDaemonMap(cmd, STRING_EMPTY, hdi); + if (!sRet.length()) { + sRet = EMPTY_ECHO; + } + EchoClient(hChannel, MSG_OK, (char *)sRet.c_str()); +#ifdef UNIT_TEST + Base::WriteBinFile((UT_TMP_PATH + "/base-list.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(), + MESSAGE_SUCCESS.size(), true); +#endif +} + +bool HdcServerForClient::GetAnyTarget(HChannel hChannel) +{ + HdcServer *ptrServer = (HdcServer *)clsServer; + HDaemonInfo hdi = nullptr; + ptrServer->AdminDaemonMap(OP_GET_ANY, STRING_EMPTY, hdi); + if (!hdi) { + EchoClient(hChannel, MSG_FAIL, "No target available"); + return false; + } + // can not use hdi->connectKey.This memory may be released to re-Malloc + string connectKey = hdi->connectKey; + bool ret = NewConnectTry(ptrServer, hChannel, connectKey); +#ifdef UNIT_TEST + Base::WriteBinFile((UT_TMP_PATH + "/base-any.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(), + MESSAGE_SUCCESS.size(), true); +#endif + return ret; +} + +bool HdcServerForClient::RemoveForward(HChannel hChannel, const char *parameterString) +{ + HdcServer *ptrServer = (HdcServer *)clsServer; + if (parameterString == nullptr) { // remove all + HForwardInfo hfi = nullptr; // dummy + string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST, "", hfi); + if (!echo.length()) { + return false; + } + vector filterStrings; + Base::SplitString(echo, string("\n"), filterStrings); + for (auto &&s : filterStrings) { + if (!CommandRemoveForward(s.c_str())) { + EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed,ruler:%s", s.c_str()); + } + } + } else { // remove single + if (!CommandRemoveForward(parameterString)) { + EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed,ruler:%s", parameterString); + } + } + return true; +} + +bool HdcServerForClient::DoCommandLocal(HChannel hChannel, void *formatCommandInput) +{ + TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput; + HdcServer *ptrServer = (HdcServer *)clsServer; + const char *parameterString = formatCommand->parameters.c_str(); + bool ret = false; + // Main thread command, direct Listen main thread + switch (formatCommand->cmdFlag) { + case CMD_KERNEL_TARGET_DISCOVER: { + OrderFindTargets(hChannel); + ret = false; + break; + } + case CMD_KERNEL_TARGET_LIST: { + GetTargetList(hChannel, formatCommandInput); + ret = false; + break; + } + case CMD_KERNEL_TARGET_ANY: { + ret = GetAnyTarget(hChannel); + break; + } + case CMD_KERNEL_TARGET_CONNECT: { + ret = NewConnectTry(ptrServer, hChannel, parameterString); + break; + } + case CMD_KERNEL_TARGET_DISCONNECT: { + CommandRemoveSession(hChannel, parameterString); + break; + } + case CMD_KERNEL_SERVER_KILL: { + WRITE_LOG(LOG_DEBUG, "Recv server kill command"); + uv_stop(loopMain); + ret = true; + break; + } + // task will be global task,Therefore, it can only be controlled in the global session. + case CMD_FORWARD_LIST: { + HForwardInfo hfi = nullptr; // dummy + string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST_FULL, "", hfi); + if (!echo.length()) { + echo = EMPTY_ECHO; + } + EchoClient(hChannel, MSG_OK, (char *)echo.c_str()); + break; + } + case CMD_FORWARD_REMOVE: { + RemoveForward(hChannel, parameterString); + break; + } + case CMD_KERNEL_ENABLE_KEEPALIVE: { + // just use for 'list targets' now + hChannel->keepAlive = true; + ret = true; + break; + } + default: { + EchoClient(hChannel, MSG_FAIL, "ExecuteCommand need connect-key?"); + break; + } + } + return ret; +} + +bool HdcServerForClient::TaskCommand(HChannel hChannel, void *formatCommandInput) +{ + TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput; + HdcServer *ptrServer = (HdcServer *)clsServer; + int sizeSend = formatCommand->parameters.size(); + string cmdFlag; + uint8_t sizeCmdFlag = 0; + if (CMD_FILE_INIT == formatCommand->cmdFlag) { + cmdFlag = "send "; + sizeCmdFlag = 5; // 5: cmdFlag send size + } else if (CMD_FORWARD_INIT == formatCommand->cmdFlag) { + cmdFlag = "fport "; + sizeCmdFlag = 6; // 6: cmdFlag fport size + } else if (CMD_APP_INIT == formatCommand->cmdFlag) { + cmdFlag = "install "; + sizeCmdFlag = 8; // 8: cmdFlag install size + } else if (CMD_APP_UNINSTALL == formatCommand->cmdFlag) { + cmdFlag = "uninstall "; + sizeCmdFlag = 10; // 10: cmdFlag uninstall size + } else if (CMD_UNITY_BUGREPORT_INIT == formatCommand->cmdFlag) { + cmdFlag = "bugreport "; + sizeCmdFlag = 10; // 10: cmdFlag bugreport size + } else if (CMD_APP_SIDELOAD == formatCommand->cmdFlag) { + cmdFlag = "sideload "; + sizeCmdFlag = 9; // 9: cmdFlag sideload size + } else if (CMD_UPDATER_UPDATE_INIT == formatCommand->cmdFlag) { + cmdFlag = "update "; + sizeCmdFlag = 7; // 7: cmdFlag update size + } else if (CMD_UPDATER_FLASH_INIT == formatCommand->cmdFlag) { + cmdFlag = "flash "; + sizeCmdFlag = 6; // 6: cmdFlag flash size + } + uint8_t *payload = reinterpret_cast(const_cast(formatCommand->parameters.c_str())) + sizeCmdFlag; + if (!strncmp(formatCommand->parameters.c_str(), cmdFlag.c_str(), sizeCmdFlag)) { // local do + HSession hSession = FindAliveSession(hChannel->targetSessionId); + if (!hSession) { + return false; + } + ptrServer->DispatchTaskData(hSession, hChannel->channelId, formatCommand->cmdFlag, payload, + sizeSend - sizeCmdFlag); + } else { // Send to Daemon-side to do + SendToDaemon(hChannel, formatCommand->cmdFlag, payload, sizeSend - sizeCmdFlag); + } + return true; +} + +bool HdcServerForClient::DoCommandRemote(HChannel hChannel, void *formatCommandInput) +{ + TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput; + bool ret = false; + int sizeSend = formatCommand->parameters.size(); + string cmdFlag; + switch (formatCommand->cmdFlag) { + // Some simple commands only need to forward the instruction, no need to start Task + case CMD_SHELL_INIT: + case CMD_SHELL_DATA: + case CMD_UNITY_EXECUTE: + case CMD_UNITY_TERMINATE: + case CMD_UNITY_REMOUNT: + case CMD_UNITY_REBOOT: + case CMD_UNITY_RUNMODE: + case CMD_UNITY_HILOG: + case CMD_UNITY_ROOTRUN: + case CMD_UNITY_JPID: { + if (!SendToDaemon(hChannel, formatCommand->cmdFlag, + reinterpret_cast(const_cast(formatCommand->parameters.c_str())), + sizeSend)) { + break; + } + ret = true; + if (CMD_SHELL_INIT == formatCommand->cmdFlag) { + hChannel->interactiveShellMode = true; + } + break; + } + case CMD_FILE_INIT: + case CMD_FORWARD_INIT: + case CMD_APP_INIT: + case CMD_APP_UNINSTALL: + case CMD_UNITY_BUGREPORT_INIT: + case CMD_APP_SIDELOAD: + case CMD_UPDATER_UPDATE_INIT: + case CMD_UPDATER_FLASH_INIT: + case CMD_UPDATER_ERASE: + case CMD_UPDATER_FORMAT: { + TaskCommand(hChannel, formatCommandInput); + ret = true; + break; + } + default: + break; + } + if (!ret) { + EchoClient(hChannel, MSG_FAIL, "Failed to communicate with daemon"); + } + return ret; +} +// Do not specify Target's operations no longer need to put it in the thread. +bool HdcServerForClient::DoCommand(HChannel hChannel, void *formatCommandInput) +{ + bool ret = false; + if (!hChannel->hChildWorkTCP.loop) { + // Main thread command, direct Listen main thread + ret = DoCommandLocal(hChannel, formatCommandInput); + } else { // CONNECT DAEMON's work thread command, non-primary thread + ret = DoCommandRemote(hChannel, formatCommandInput); + } + return ret; +} + +// just call from BindChannelToSession +HSession HdcServerForClient::FindAliveSessionFromDaemonMap(const HChannel hChannel) +{ + HSession hSession = nullptr; + HDaemonInfo hdi = nullptr; + HdcServer *ptrServer = (HdcServer *)clsServer; + ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi); + if (!hdi) { + EchoClient(hChannel, MSG_FAIL, "Not match target founded, check connect-key please"); + return nullptr; + } + if (hdi->connStatus != STATUS_CONNECTED) { + EchoClient(hChannel, MSG_FAIL, "Device not founded or connected"); + return nullptr; + } + if (hdi->hSession->isDead) { + EchoClient(hChannel, MSG_FAIL, "Bind tartget session is dead"); + return nullptr; + } + hSession = (HSession)hdi->hSession; + return hSession; +} + +int HdcServerForClient::BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) +{ + HSession hSession = nullptr; + if ((hSession = FindAliveSessionFromDaemonMap(hChannel)) == nullptr) { + return ERR_SESSION_NOFOUND; + } + bool isClosing = uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP); + if (!isClosing && (hChannel->fdChildWorkTCP = Base::DuplicateUvSocket(&hChannel->hWorkTCP)) < 0) { + WRITE_LOG(LOG_FATAL, "Duplicate socket failed, cid:%d", hChannel->channelId); + return ERR_SOCKET_DUPLICATE; + } + uv_close_cb funcWorkTcpClose = [](uv_handle_t *handle) -> void { + HChannel hChannel = (HChannel)handle->data; + --hChannel->sendRef; + }; + ++hChannel->sendRef; + if (!isClosing) { + uv_close((uv_handle_t *)&hChannel->hWorkTCP, funcWorkTcpClose); + } + Base::DoNextLoop(loopMain, hChannel, [](const uint8_t flag, string &msg, const void *data) { + // Thread message can avoid using thread lock and improve program efficiency + // If not next loop call, ReadStream will thread conflict + HChannel hChannel = (HChannel)data; + auto thisClass = (HdcServerForClient *)hChannel->clsChannel; + HSession hSession = nullptr; + if ((hSession = thisClass->FindAliveSessionFromDaemonMap(hChannel)) == nullptr) { + return; + } + auto ctrl = HdcSessionBase::BuildCtrlString(SP_ATTACH_CHANNEL, hChannel->channelId, nullptr, 0); + Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); + }); + return RET_SUCCESS; +} + +bool HdcServerForClient::CheckAutoFillTarget(HChannel hChannel) +{ + HdcServer *ptrServer = (HdcServer *)clsServer; + if (!hChannel->connectKey.size()) { + return false; // Operation of non-bound destination of scanning + } + if (hChannel->connectKey == CMDSTR_CONNECT_ANY) { + HDaemonInfo hdiOld = nullptr; + ptrServer->AdminDaemonMap(OP_GET_ONLY, "", hdiOld); + if (!hdiOld) { + return false; + } + hChannel->connectKey = hdiOld->connectKey; + return true; + } + return true; +} + +int HdcServerForClient::ChannelHandShake(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) +{ + vector rebuildHandshake; + rebuildHandshake.insert(rebuildHandshake.end(), bufPtr, bufPtr + bytesIO); + rebuildHandshake.push_back(0x00); + struct ChannelHandShake *handShake = reinterpret_cast(rebuildHandshake.data()); + if (strncmp(handShake->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) { + hChannel->availTailIndex = 0; + WRITE_LOG(LOG_DEBUG, "Channel Hello failed"); + return ERR_HANDSHAKE_NOTMATCH; + } + if (strlen(handShake->connectKey) > sizeof(handShake->connectKey)) { + hChannel->availTailIndex = 0; + WRITE_LOG(LOG_DEBUG, "Connectkey's size incorrect"); + return ERR_HANDSHAKE_CONNECTKEY_FAILED; + } + // channel handshake step3 + WRITE_LOG(LOG_DEBUG, "ServerForClient channel handshake finished"); + hChannel->connectKey = handShake->connectKey; + hChannel->handshakeOK = true; + if (!CheckAutoFillTarget(hChannel)) { + return 0; + } + // channel handshake stBindChannelToSession + if (BindChannelToSession(hChannel, nullptr, 0)) { + hChannel->availTailIndex = 0; + WRITE_LOG(LOG_FATAL, "BindChannelToSession failed"); + return ERR_GENERIC; + } + return 0; +} + +// Here is Server to get data, the source is the SERVER's ChildWork to send data +int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) +{ + int ret = 0; + if (!hChannel->handshakeOK) { + return ChannelHandShake(hChannel, bufPtr, bytesIO); + } + struct TranslateCommand::FormatCommand formatCommand = { 0 }; + if (!hChannel->interactiveShellMode) { + string retEcho = String2FormatCommand((char *)bufPtr, bytesIO, &formatCommand); + if (retEcho.length()) { + if (!strcmp((char *)bufPtr, CMDSTR_SOFTWARE_HELP.c_str()) || + !strcmp((char *)bufPtr, CMDSTR_SOFTWARE_VERSION.c_str()) || + !strcmp((char *)bufPtr, "flash")) { + EchoClient(hChannel, MSG_OK, retEcho.c_str()); + } else { + EchoClient(hChannel, MSG_FAIL, retEcho.c_str()); + } + } + if (formatCommand.bJumpDo) { + ret = -10; + return ret; + } + } else { + formatCommand.parameters = string(reinterpret_cast(bufPtr), bytesIO); + formatCommand.cmdFlag = CMD_SHELL_DATA; + } + if (!DoCommand(hChannel, &formatCommand)) { + return -3; // -3: error or want close + } + ret = bytesIO; + return ret; +}; + +// avoid session dead +HSession HdcServerForClient::FindAliveSession(uint32_t sessionId) +{ + HdcServer *ptrServer = (HdcServer *)clsServer; + HSession hSession = ptrServer->AdminSession(OP_QUERY, sessionId, nullptr); + if (!hSession || hSession->isDead) { + return nullptr; + } else { + return hSession; + } +} + +bool HdcServerForClient::ChannelSendSessionCtrlMsg(vector &ctrlMsg, uint32_t sessionId) +{ + HSession hSession = FindAliveSession(sessionId); + if (!hSession) { + return false; + } + return Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrlMsg.data(), ctrlMsg.size()) > 0; +} +} // namespace Hdc diff --git a/services/flashd/host/server_for_client.h b/services/flashd/host/server_for_client.h new file mode 100755 index 00000000..22ca06e2 --- /dev/null +++ b/services/flashd/host/server_for_client.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_SERVERFORCLIENT_H +#define HDC_SERVERFORCLIENT_H +#include "host_common.h" +#include "translate.h" + +namespace Hdc { +class HdcServerForClient : public HdcChannelBase { +public: + HdcServerForClient(const bool serverOrClient, const string &addrString, void *pClsServer, uv_loop_t *loopMainIn); + virtual ~HdcServerForClient(); + int Initial(); + void EchoClient(HChannel hChannel, MessageLevel level, const char *msg, ...); + void EchoClientRaw(const uint32_t channelId, uint8_t *payload, const int payloadSize); + uint16_t GetTCPListenPort(); + void Stop(); + +protected: +private: + static void AcceptClient(uv_stream_t *server, int status); + void SetTCPListen(); + int ReadChannel(HChannel hChannel, uint8_t *bufPtr, const int bytesIO); + bool DoCommand(HChannel hChannel, void *formatCommandInput); + void OrderFindTargets(HChannel hChannel); + bool NewConnectTry(void *ptrServer, HChannel hChannel, const string &connectKey); + static void OrderConnecTargetResult(uv_timer_t *req); + bool SendToDaemon(HChannel hChannel, const uint16_t commandFlag, uint8_t *bufPtr, const int bufSize); + int BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO); + bool CheckAutoFillTarget(HChannel hChannel); + bool CommandRemoveSession(HChannel hChannel, const char *connectKey); + bool CommandRemoveForward(const string &forwardKey); + bool DoCommandLocal(HChannel hChannel, void *formatCommandInput); + bool DoCommandRemote(HChannel hChannel, void *formatCommandInput); + void GetTargetList(HChannel hChannel, void *formatCommandInput); + bool GetAnyTarget(HChannel hChannel); + bool RemoveForward(HChannel hChannel, const char *parameterString); + bool TaskCommand(HChannel hChannel, void *formatCommandInput); + int ChannelHandShake(HChannel hChannel, uint8_t *bufPtr, const int bytesIO); + bool ChannelSendSessionCtrlMsg(vector &ctrlMsg, uint32_t sessionId); + HSession FindAliveSession(uint32_t sessionId); + HSession FindAliveSessionFromDaemonMap(const HChannel hChannel); + + uv_tcp_t tcpListen; + void *clsServer; +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/host/translate.cpp b/services/flashd/host/translate.cpp new file mode 100755 index 00000000..350765eb --- /dev/null +++ b/services/flashd/host/translate.cpp @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "translate.h" + +namespace Hdc { +namespace TranslateCommand { + string Usage() + { + string ret; + + ret = "\n OpenHarmony flash ...\n\n" + "---------------------------------global commands:----------------------------------\n" + " -h/help - Print flashd help\n" + " -v/version - Print flashd version\n" + " -l 0-5 - Set runtime loglevel\n" + " -t connectkey - Use device with given connect key\n" + "\n" + "---------------------------------component commands:-------------------------------\n" + "session commands(on server):\n" + " discover - Discover devices listening on TCP via LAN broadcast\n" + " list targets [-v] - List all devices status, -v for detail\n" + " tconn key - Connect device via key, TCP use ip:port\n" + " example:192.168.0.100:10178/192.168.0.100\n" + " USB connect automatic, TCP need to connect manually\n" + " start [-r] - Start server. If with '-r', will be restart server\n" + " kill [-r] - Kill server. If with '-r', will be restart server\n" + " -s [ip:]port - Set flash server listen config\n" + "\n" + "service commands(on daemon):\n" + " target boot [-bootloader|-recovery] - Reboot the device or boot into bootloader\\recovery.\n" + " tmode usb - Reboot the device, listening on USB\n" + " tmode port [port] - Reboot the device, listening on TCP port\n" + "\n" + "---------------------------------flash commands:-------------------------------------\n" + "flash commands:\n" + " update packagename - Update system by package\n" + " flash [-f] partition imagename - Flash partition by image\n" + " erase [-f] partition - Erase partition\n" + " format [-f] partition -t fs_type - Format partition -t [ext4 | f2fs]\n"; + return ret; + } + + string TargetConnect(FormatCommand *outCmd) + { + string stringError; + if (Base::StringEndsWith(outCmd->parameters, " -remove")) { + outCmd->parameters = outCmd->parameters.substr(0, outCmd->parameters.size() - 8); + outCmd->cmdFlag = CMD_KERNEL_TARGET_DISCONNECT; + } else { + outCmd->cmdFlag = CMD_KERNEL_TARGET_CONNECT; + if (outCmd->parameters.size() > 22) { // 22: tcp max=21,USB max=8bytes + stringError = "Error connect key's size"; + outCmd->bJumpDo = true; + } + } + if (outCmd->parameters.find(":") != std::string::npos) { + // tcp mode + string ip = outCmd->parameters.substr(0, outCmd->parameters.find(":")); + string sport = outCmd->parameters.substr(outCmd->parameters.find(":") + 1); + int port = std::stoi(sport); + sockaddr_in addr; + if ((port <= 0 || port > MAX_IP_PORT) || uv_ip4_addr(ip.c_str(), port, &addr) < 0) { + stringError = "IP:Port incorrect"; + outCmd->bJumpDo = true; + } + } + return stringError; + } + + string ForwardPort(const char *input, FormatCommand *outCmd) + { + string stringError; + const char *pExtra = input + 6; // CMDSTR_FORWARD_FPORT CMDSTR_FORWARD_RPORT + " " size + if (!strcmp(pExtra, "ls")) { + outCmd->cmdFlag = CMD_FORWARD_LIST; + } else if (!strncmp(pExtra, "rm", 2)) { // 2 rm size + outCmd->cmdFlag = CMD_FORWARD_REMOVE; + if (strcmp(pExtra, "rm")) { + outCmd->parameters = input + 9; // 9 rm extra size + } + } else { + const char *p = input + 6; + // clang-format off + if (strncmp(p, "tcp:", 4) && strncmp(p, "localabstract:", 14) && strncmp(p, "localreserved:", 14) && + strncmp(p, "localfilesystem:", 16) && strncmp(p, "dev:", 4) && strncmp(p, "jdwp:", 5)) { + stringError = "Incorrect forward command"; + outCmd->bJumpDo = true; + } + // clang-format on + outCmd->cmdFlag = CMD_FORWARD_INIT; + outCmd->parameters = input; + } + return stringError; + } + + string RunMode(const char *input, FormatCommand *outCmd) + { + string stringError; + outCmd->cmdFlag = CMD_UNITY_RUNMODE; + outCmd->parameters = input + CMDSTR_TARGET_MODE.size() + 1; // with ' ' + if (!strncmp(outCmd->parameters.c_str(), "port", 4) + && !strcmp(outCmd->parameters.c_str(), CMDSTR_TMODE_USB.c_str())) { + stringError = "Error tmode command"; + outCmd->bJumpDo = true; + } else if (!strncmp(outCmd->parameters.c_str(), "port ", 5)) { + int port = atoi(input + 4); + if (port > MAX_IP_PORT || port <= 0) { + stringError = "Incorrect port range"; + outCmd->bJumpDo = true; + } + } + return stringError; + } + + string TargetReboot(const char *input, FormatCommand *outCmd) + { + string stringError; + outCmd->cmdFlag = CMD_UNITY_REBOOT; + if (strcmp(input, CMDSTR_TARGET_REBOOT.c_str())) { + outCmd->parameters = input + 12; + if (outCmd->parameters != "-bootloader" + && outCmd->parameters != "-recovery" && outCmd->parameters != "-flashd") { + stringError = "Error reboot paramenter"; + outCmd->bJumpDo = true; + } else { + outCmd->parameters.erase(outCmd->parameters.begin()); + } + } + return stringError; + } + + // command input + // client side:Enter string data formatting conversion to module see internal processing command + string String2FormatCommand(const char *inputRaw, int sizeInputRaw, FormatCommand *outCmd) + { + string stringError; + string input = string(inputRaw, sizeInputRaw); + if (!strcmp(input.c_str(), CMDSTR_SOFTWARE_HELP.c_str())) { + outCmd->cmdFlag = CMD_KERNEL_HELP; + stringError = Usage(); + outCmd->bJumpDo = true; + } else if (!strcmp(input.c_str(), CMDSTR_SOFTWARE_VERSION.c_str())) { + outCmd->cmdFlag = CMD_KERNEL_HELP; + stringError = Base::GetVersion(); + outCmd->bJumpDo = true; + } else if (!strcmp(input.c_str(), CMDSTR_TARGET_DISCOVER.c_str())) { + outCmd->cmdFlag = CMD_KERNEL_TARGET_DISCOVER; + } else if (!strncmp(input.c_str(), CMDSTR_LIST_TARGETS.c_str(), CMDSTR_LIST_TARGETS.size())) { + outCmd->cmdFlag = CMD_KERNEL_TARGET_LIST; + if (strstr(input.c_str(), " -v")) { + outCmd->parameters = "v"; + } + } else if (!strcmp(input.c_str(), CMDSTR_CONNECT_ANY.c_str())) { + outCmd->cmdFlag = CMD_KERNEL_TARGET_ANY; + } else if (!strncmp(input.c_str(), CMDSTR_CONNECT_TARGET.c_str(), CMDSTR_CONNECT_TARGET.size())) { + outCmd->parameters = input.c_str() + CMDSTR_CONNECT_TARGET.size() + 1; // with ' ' + stringError = TargetConnect(outCmd); + } else if (!strncmp(input.c_str(), (CMDSTR_SHELL + " ").c_str(), CMDSTR_SHELL.size() + 1)) { + outCmd->cmdFlag = CMD_UNITY_EXECUTE; + outCmd->parameters = input.c_str() + CMDSTR_SHELL.size() + 1; + } else if (!strcmp(input.c_str(), CMDSTR_SHELL.c_str())) { + outCmd->cmdFlag = CMD_SHELL_INIT; + } else if (!strncmp(input.c_str(), CMDSTR_FILE_SEND.c_str(), CMDSTR_FILE_SEND.size()) + || !strncmp(input.c_str(), CMDSTR_FILE_RECV.c_str(), CMDSTR_FILE_RECV.size())) { + outCmd->cmdFlag = CMD_FILE_INIT; + outCmd->parameters = input.c_str() + 5; // 5: CMDSTR_FORWARD_FPORT CMDSTR_FORWARD_RPORT size + } else if (!strncmp(input.c_str(), string(CMDSTR_FORWARD_FPORT + " ").c_str(), CMDSTR_FORWARD_FPORT.size() + 1) + || !strncmp(input.c_str(), string(CMDSTR_FORWARD_RPORT + " ").c_str(), + CMDSTR_FORWARD_RPORT.size() + 1)) { + stringError = ForwardPort(input.c_str(), outCmd); + } else if (!strcmp(input.c_str(), CMDSTR_KILL_SERVER.c_str())) { + outCmd->cmdFlag = CMD_KERNEL_SERVER_KILL; + } else if (!strcmp(input.c_str(), CMDSTR_KILL_DAEMON.c_str())) { + outCmd->cmdFlag = CMD_UNITY_TERMINATE; + outCmd->parameters = "0"; + } else if (!strncmp(input.c_str(), CMDSTR_APP_INSTALL.c_str(), CMDSTR_APP_INSTALL.size())) { + outCmd->cmdFlag = CMD_APP_INIT; + outCmd->parameters = input; + } else if (!strncmp(input.c_str(), CMDSTR_APP_UNINSTALL.c_str(), CMDSTR_APP_UNINSTALL.size())) { + outCmd->cmdFlag = CMD_APP_UNINSTALL; + outCmd->parameters = input; + if (outCmd->parameters.size() > 512 || outCmd->parameters.size() < 4) { + stringError = "Package's path incorrect"; + outCmd->bJumpDo = true; + } + } else if (!strcmp(input.c_str(), CMDSTR_TARGET_MOUNT.c_str())) { + outCmd->cmdFlag = CMD_UNITY_REMOUNT; + } else if (!strcmp(input.c_str(), CMDSTR_LIST_JDWP.c_str())) { + outCmd->cmdFlag = CMD_UNITY_JPID; + } else if (!strncmp(input.c_str(), CMDSTR_TARGET_REBOOT.c_str(), CMDSTR_TARGET_REBOOT.size())) { + TargetReboot(input.c_str(), outCmd); + } else if (!strncmp(input.c_str(), CMDSTR_TARGET_MODE.c_str(), CMDSTR_TARGET_MODE.size())) { + RunMode(input.c_str(), outCmd); + } else if (!strcmp(input.c_str(), CMDSTR_CONNECT_ANY.c_str())) { + outCmd->cmdFlag = CMD_KERNEL_TARGET_ANY; + } else if (!strncmp(input.c_str(), CMDSTR_HILOG.c_str(), CMDSTR_HILOG.size())) { + outCmd->cmdFlag = CMD_UNITY_HILOG; + if (strstr(input.c_str(), " -v")) { + outCmd->parameters = "v"; + } + } else if (!strncmp(input.c_str(), CMDSTR_STARTUP_MODE.c_str(), CMDSTR_STARTUP_MODE.size())) { + outCmd->cmdFlag = CMD_UNITY_ROOTRUN; + if (strstr(input.c_str(), " -r")) { + outCmd->parameters = "r"; + } + } else if (!strncmp(input.c_str(), CMDSTR_APP_SIDELOAD.c_str(), CMDSTR_APP_SIDELOAD.size())) { + if (strlen(input.c_str()) == CMDSTR_APP_SIDELOAD.size()) { + stringError = "Incorrect command, please with local path"; + outCmd->bJumpDo = true; + } + outCmd->cmdFlag = CMD_APP_SIDELOAD; + outCmd->parameters = input; + } else if (!strncmp(input.c_str(), CMDSTR_BUGREPORT.c_str(), CMDSTR_BUGREPORT.size())) { + outCmd->cmdFlag = CMD_UNITY_BUGREPORT_INIT; + outCmd->parameters = input; + if (outCmd->parameters.size() == CMDSTR_BUGREPORT.size()) { + outCmd->parameters += " "; + } + } + // Inner command, protocol uses only + else if (input == CMDSTR_INNER_ENABLE_KEEPALIVE) { + outCmd->cmdFlag = CMD_KERNEL_ENABLE_KEEPALIVE; + } else if (HostUpdater::CheckMatchUpdate(input, stringError, outCmd->cmdFlag, outCmd->bJumpDo)) { + outCmd->parameters = input; + } else { + stringError = "Unknown command..."; + outCmd->bJumpDo = true; + } + // nl + if (stringError.size()) { + stringError += "\n"; + } + return stringError; + }; +} +} // namespace Hdc diff --git a/services/flashd/host/translate.h b/services/flashd/host/translate.h new file mode 100755 index 00000000..96128e50 --- /dev/null +++ b/services/flashd/host/translate.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HDC_TRANSLATE_H +#define HDC_TRANSLATE_H +#include "host_common.h" + +namespace Hdc { +namespace TranslateCommand { + struct FormatCommand { + uint16_t cmdFlag; + string parameters; + bool bJumpDo; + }; + + string String2FormatCommand(const char *inputRaw, int sizeInputRaw, FormatCommand *outCmd); + string Usage(); +} +} +#endif \ No newline at end of file diff --git a/services/updater_binary/main.cpp b/services/updater_binary/main.cpp index 62542a9b..10ccdd89 100644 --- a/services/updater_binary/main.cpp +++ b/services/updater_binary/main.cpp @@ -44,4 +44,4 @@ int main(int argc, char **argv) std::string packagePath = argv[0]; return ProcessUpdater(retry, pipeFd, packagePath, utils::GetCertName()); } -#endif \ No newline at end of file +#endif diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 5a7a54c8..80172c3f 100755 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -44,8 +44,8 @@ ohos_unittest("updater_unittest") { "applypatch_test/transfer_manager_unittest.cpp", "diffpatch/bzip2_unittest.cpp", "diffpatch/diffpatch_unittest.cpp", - "flashd_test/flash_host_unittest.cpp", "flashd_test/flash_service_unittest.cpp", + "flashd_test/flash_host_unittest.cpp", "fs_manager/do_partition_unittest.cpp", "log_test/log_unittest.cpp", "misc_info_test/misc_info_unittest.cpp", @@ -96,8 +96,8 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/flashd/blockdevice.cpp", "//base/update/updater/services/flashd/daemon/daemon_updater.cpp", "//base/update/updater/services/flashd/daemon/flashd_main.cpp", - "//base/update/updater/services/flashd/flash_service.cpp", "//base/update/updater/services/flashd/host/host_updater.cpp", + "//base/update/updater/services/flashd/flash_service.cpp", "//base/update/updater/services/flashd/partition.cpp", "//base/update/updater/services/fs_manager/cmp_partition.cpp", "//base/update/updater/services/fs_manager/do_partition.cpp", @@ -167,6 +167,7 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/flashd", "//base/update/updater/services/flashd/daemon", "//base/update/updater/services/flashd/host", + "//base/update/updater/services/flashd/common", "//base/update/updater/services/fs_manager", "//base/update/updater/services/applypatch", "//base/update/updater/services/diffpatch", @@ -196,10 +197,6 @@ ohos_unittest("updater_unittest") { "//drivers/peripheral/input/hal/include", "//drivers/peripheral/input/interfaces/include", "//third_party/bounds_checking_function/include", - "//developtools/hdc_standard/src", - "//developtools/hdc_standard/src/daemon", - "//developtools/hdc_standard/src/common", - "//developtools/hdc_standard/src/host", "//base/startup/init_lite/interfaces/innerkits/include", ] deps = [ @@ -214,7 +211,7 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/package:libupdaterpackage", "//base/update/updater/services/ui:libui", "//base/update/updater/utils:libutils", - "//developtools/hdc_standard:hdc_deamon_flashd", + "//base/update/updater/services/flashd:flashd_deamon", "//third_party/bounds_checking_function:libsec_static", "//third_party/bzip2:libbz2", "//third_party/cJSON:cjson_static", diff --git a/test/unittest/flashd_test/flash_host_unittest.cpp b/test/unittest/flashd_test/flash_host_unittest.cpp index 0b9c580f..36561822 100755 --- a/test/unittest/flashd_test/flash_host_unittest.cpp +++ b/test/unittest/flashd_test/flash_host_unittest.cpp @@ -172,12 +172,6 @@ HWTEST_F(FLashHostUnitTest, TestFlashHostFlash, TestSize.Level1) EXPECT_EQ(0, test.TestFlashProgress(CMD_UPDATER_FLASH_INIT, cmdParam, 100)); } -HWTEST_F(FLashHostUnitTest, TestFlashHostHelp, TestSize.Level1) -{ - std::string help = HostUpdater::GetFlashdHelp(); - printf("%s", help.c_str()); -} - HWTEST_F(FLashHostUnitTest, TestFlashHostMatch, TestSize.Level1) { std::string stringError; diff --git a/utils/utils.cpp b/utils/utils.cpp index fe205e4b..3da6a9a1 100644 --- a/utils/utils.cpp +++ b/utils/utils.cpp @@ -190,6 +190,8 @@ void DoReboot(const std::string& rebootTarget, const std::string &extData) result = strcpy_s(msg.update, MAX_UPDATE_SIZE - 1, extData.c_str()); UPDATER_ERROR_CHECK(result == 0, "Failed to copy update", return); msg.update[MAX_UPDATE_SIZE - 1] = 0; + } else { + UPDATER_ERROR_CHECK(!memset_s(msg.update, MAX_UPDATE_SIZE, 0, MAX_UPDATE_SIZE), "Memset_s failed", return); } if (WriteUpdaterMessage(miscBlockDevice, msg) != true) { LOG(INFO) << "DoReboot: WriteUpdaterMessage boot_updater error"; -- Gitee From 15c80870e00debc0483adfc088ba9db770a7c35d Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Tue, 16 Nov 2021 14:03:01 +0800 Subject: [PATCH 11/15] updater: fix gn format Signed-off-by: xionglei6 --- services/flashd/BUILD.gn | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/services/flashd/BUILD.gn b/services/flashd/BUILD.gn index d0019f88..3933ab11 100755 --- a/services/flashd/BUILD.gn +++ b/services/flashd/BUILD.gn @@ -172,12 +172,12 @@ ohos_executable("ohflash") { "${FLASHD_HDC_PATH}/host/host_forward.cpp", "${FLASHD_HDC_PATH}/host/host_tcp.cpp", "${FLASHD_HDC_PATH}/host/host_unity.cpp", + "${FLASHD_HDC_PATH}/host/host_updater.cpp", "${FLASHD_HDC_PATH}/host/host_usb.cpp", "${FLASHD_HDC_PATH}/host/main.cpp", "${FLASHD_HDC_PATH}/host/server.cpp", "${FLASHD_HDC_PATH}/host/server_for_client.cpp", "${FLASHD_HDC_PATH}/host/translate.cpp", - "${FLASHD_HDC_PATH}/host/host_updater.cpp", ] sources += common_sources @@ -189,9 +189,7 @@ ohos_executable("ohflash") { "//utils/native/base:utilsecurec", ] - deps += [ - "//third_party/libusb:libusb", - ] + deps += [ "//third_party/libusb:libusb" ] include_dirs = [ "${FLASHD_HDC_PATH}/host", @@ -201,14 +199,14 @@ ohos_executable("ohflash") { "//third_party/libuv", ] - if(is_mingw) { + if (is_mingw) { static_link = true defines += [ "_WIN32" ] defines += [ "WIN32_LEAN_AND_MEAN" ] libs += [ "setupapi" ] } - if(is_linux) { + if (is_linux) { static_link = true deps += [ "//third_party/openssl:libcrypto_static" ] } @@ -217,23 +215,16 @@ ohos_executable("ohflash") { part_name = "updater" } - group("flashhost_target_standard") { - deps = [ - ":ohflash", - ] + deps = [ ":ohflash" ] } group("flashhost_target_standard_linux") { - deps = [ - ":ohflash(//build/toolchain/linux:clang_x64)", - ] + deps = [ ":ohflash(//build/toolchain/linux:clang_x64)" ] } group("flashhost_target_standard_mingw") { - deps = [ - ":ohflash(//build/toolchain/mingw:mingw_x86_64)", - ] + deps = [ ":ohflash(//build/toolchain/mingw:mingw_x86_64)" ] } group("flashhost_target_standard_all") { -- Gitee From 4f8fff9a6b8d042d0b8abb549a8571990ec8de46 Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Tue, 16 Nov 2021 14:54:13 +0800 Subject: [PATCH 12/15] updater: fix gn format Signed-off-by: xionglei6 --- test/unittest/BUILD.gn | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 80172c3f..8fd94283 100755 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -44,8 +44,8 @@ ohos_unittest("updater_unittest") { "applypatch_test/transfer_manager_unittest.cpp", "diffpatch/bzip2_unittest.cpp", "diffpatch/diffpatch_unittest.cpp", - "flashd_test/flash_service_unittest.cpp", "flashd_test/flash_host_unittest.cpp", + "flashd_test/flash_service_unittest.cpp", "fs_manager/do_partition_unittest.cpp", "log_test/log_unittest.cpp", "misc_info_test/misc_info_unittest.cpp", @@ -96,8 +96,8 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/flashd/blockdevice.cpp", "//base/update/updater/services/flashd/daemon/daemon_updater.cpp", "//base/update/updater/services/flashd/daemon/flashd_main.cpp", - "//base/update/updater/services/flashd/host/host_updater.cpp", "//base/update/updater/services/flashd/flash_service.cpp", + "//base/update/updater/services/flashd/host/host_updater.cpp", "//base/update/updater/services/flashd/partition.cpp", "//base/update/updater/services/fs_manager/cmp_partition.cpp", "//base/update/updater/services/fs_manager/do_partition.cpp", @@ -206,12 +206,12 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/applypatch:libapplypatch", "//base/update/updater/services/diffpatch/diff:libdiff", "//base/update/updater/services/diffpatch/patch:libpatch", + "//base/update/updater/services/flashd:flashd_deamon", "//base/update/updater/services/fs_manager:libfsmanager", "//base/update/updater/services/log:libupdaterlog", "//base/update/updater/services/package:libupdaterpackage", "//base/update/updater/services/ui:libui", "//base/update/updater/utils:libutils", - "//base/update/updater/services/flashd:flashd_deamon", "//third_party/bounds_checking_function:libsec_static", "//third_party/bzip2:libbz2", "//third_party/cJSON:cjson_static", -- Gitee From fb0e7fbabac16404edeb22e1232062e62f30952c Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Wed, 17 Nov 2021 10:26:23 +0800 Subject: [PATCH 13/15] flashed Signed-off-by: xionglei6 --- services/flashd/BUILD.gn | 90 +- services/flashd/common/async_cmd.cpp | 189 --- services/flashd/common/async_cmd.h | 64 - services/flashd/common/auth.cpp | 488 ------ services/flashd/common/auth.h | 37 - services/flashd/common/base.h | 146 -- services/flashd/common/channel.cpp | 434 ------ services/flashd/common/channel.h | 76 - services/flashd/common/common.h | 79 - services/flashd/common/debug.cpp | 104 -- services/flashd/common/debug.h | 28 - services/flashd/common/define.h | 98 -- services/flashd/common/define_plus.h | 340 ----- services/flashd/common/file.cpp | 195 --- services/flashd/common/file_descriptor.cpp | 166 --- services/flashd/common/file_descriptor.h | 58 - .../flashd/common/{file.h => flash_define.h} | 39 +- services/flashd/common/forward.cpp | 789 ---------- services/flashd/common/forward.h | 107 -- services/flashd/common/serial_struct.h | 88 -- services/flashd/common/serial_struct_define.h | 1314 ----------------- services/flashd/common/session.cpp | 1062 ------------- services/flashd/common/session.h | 183 --- services/flashd/common/task.cpp | 99 -- services/flashd/common/task.h | 57 - services/flashd/common/tcp.cpp | 98 -- services/flashd/common/tcp.h | 43 - services/flashd/common/transfer.cpp | 417 ------ services/flashd/common/transfer.h | 114 -- services/flashd/common/usb.cpp | 144 -- services/flashd/common/usb.h | 41 - services/flashd/daemon/daemon.cpp | 72 +- services/flashd/daemon/daemon.h | 47 - services/flashd/daemon/daemon_app.cpp | 151 -- services/flashd/daemon/daemon_app.h | 38 - services/flashd/daemon/daemon_common.h | 41 - services/flashd/daemon/daemon_forward.cpp | 82 - services/flashd/daemon/daemon_forward.h | 31 - services/flashd/daemon/daemon_tcp.cpp | 151 -- services/flashd/daemon/daemon_tcp.h | 40 - services/flashd/daemon/daemon_unity.h | 48 - services/flashd/daemon/daemon_updater.cpp | 2 + services/flashd/daemon/daemon_usb.cpp | 498 ------- services/flashd/daemon/daemon_usb.h | 62 - services/flashd/daemon/flashd_main.cpp | 1 + services/flashd/daemon/jdwp.cpp | 279 ---- services/flashd/daemon/jdwp.h | 59 - services/flashd/daemon/main.cpp | 197 --- services/flashd/daemon/shell.cpp | 217 --- services/flashd/daemon/shell.h | 47 - services/flashd/daemon/usb_ffs.h | 218 --- services/flashd/host/client.cpp | 53 +- services/flashd/host/client.h | 59 - services/flashd/host/host_app.cpp | 177 --- services/flashd/host/host_app.h | 34 - services/flashd/host/host_common.h | 37 - services/flashd/host/host_forward.cpp | 26 - services/flashd/host/host_forward.h | 29 - services/flashd/host/host_tcp.cpp | 166 --- services/flashd/host/host_tcp.h | 38 - services/flashd/host/host_unity.cpp | 155 -- services/flashd/host/host_unity.h | 51 - services/flashd/host/host_updater.cpp | 18 +- services/flashd/host/host_updater.h | 6 +- services/flashd/host/host_usb.cpp | 550 ------- services/flashd/host/host_usb.h | 66 - services/flashd/host/main.cpp | 1 + services/flashd/host/server.cpp | 5 +- services/flashd/host/server.h | 64 - services/flashd/host/server_for_client.cpp | 2 + services/flashd/host/server_for_client.h | 60 - services/flashd/host/translate.cpp | 1 + services/flashd/host/translate.h | 31 - test/unittest/BUILD.gn | 3 + .../flashd_test/flash_host_unittest.cpp | 10 +- .../flashd_test/flash_service_unittest.cpp | 5 +- 76 files changed, 143 insertions(+), 10972 deletions(-) delete mode 100755 services/flashd/common/async_cmd.cpp delete mode 100755 services/flashd/common/async_cmd.h delete mode 100755 services/flashd/common/auth.cpp delete mode 100755 services/flashd/common/auth.h delete mode 100755 services/flashd/common/base.h delete mode 100755 services/flashd/common/channel.cpp delete mode 100755 services/flashd/common/channel.h delete mode 100755 services/flashd/common/common.h delete mode 100755 services/flashd/common/debug.cpp delete mode 100755 services/flashd/common/debug.h delete mode 100755 services/flashd/common/define.h delete mode 100755 services/flashd/common/define_plus.h delete mode 100755 services/flashd/common/file.cpp delete mode 100755 services/flashd/common/file_descriptor.cpp delete mode 100755 services/flashd/common/file_descriptor.h rename services/flashd/common/{file.h => flash_define.h} (43%) delete mode 100755 services/flashd/common/forward.cpp delete mode 100755 services/flashd/common/forward.h delete mode 100755 services/flashd/common/serial_struct.h delete mode 100755 services/flashd/common/serial_struct_define.h delete mode 100755 services/flashd/common/session.cpp delete mode 100755 services/flashd/common/session.h delete mode 100755 services/flashd/common/task.cpp delete mode 100755 services/flashd/common/task.h delete mode 100755 services/flashd/common/tcp.cpp delete mode 100755 services/flashd/common/tcp.h delete mode 100755 services/flashd/common/transfer.cpp delete mode 100755 services/flashd/common/transfer.h delete mode 100755 services/flashd/common/usb.cpp delete mode 100755 services/flashd/common/usb.h delete mode 100755 services/flashd/daemon/daemon.h delete mode 100755 services/flashd/daemon/daemon_app.cpp delete mode 100755 services/flashd/daemon/daemon_app.h delete mode 100755 services/flashd/daemon/daemon_common.h delete mode 100755 services/flashd/daemon/daemon_forward.cpp delete mode 100755 services/flashd/daemon/daemon_forward.h delete mode 100755 services/flashd/daemon/daemon_tcp.cpp delete mode 100755 services/flashd/daemon/daemon_tcp.h delete mode 100755 services/flashd/daemon/daemon_unity.h delete mode 100755 services/flashd/daemon/daemon_usb.cpp delete mode 100755 services/flashd/daemon/daemon_usb.h delete mode 100755 services/flashd/daemon/jdwp.cpp delete mode 100755 services/flashd/daemon/jdwp.h delete mode 100755 services/flashd/daemon/main.cpp delete mode 100755 services/flashd/daemon/shell.cpp delete mode 100755 services/flashd/daemon/shell.h delete mode 100755 services/flashd/daemon/usb_ffs.h delete mode 100755 services/flashd/host/client.h delete mode 100755 services/flashd/host/host_app.cpp delete mode 100755 services/flashd/host/host_app.h delete mode 100755 services/flashd/host/host_common.h delete mode 100755 services/flashd/host/host_forward.cpp delete mode 100755 services/flashd/host/host_forward.h delete mode 100755 services/flashd/host/host_tcp.cpp delete mode 100755 services/flashd/host/host_tcp.h delete mode 100755 services/flashd/host/host_unity.cpp delete mode 100755 services/flashd/host/host_unity.h delete mode 100755 services/flashd/host/host_usb.cpp delete mode 100755 services/flashd/host/host_usb.h delete mode 100755 services/flashd/host/server.h delete mode 100755 services/flashd/host/server_for_client.h delete mode 100755 services/flashd/host/translate.h diff --git a/services/flashd/BUILD.gn b/services/flashd/BUILD.gn index 3933ab11..7a30a9fb 100755 --- a/services/flashd/BUILD.gn +++ b/services/flashd/BUILD.gn @@ -13,39 +13,40 @@ import("//build/ohos.gni") -FLASHD_HDC_PATH = "//base/update/updater/services/flashd" +FLASHD_PATH = "//base/update/updater/services/flashd" +HDC_PATH = "//developtools/hdc_standard/src" common_sources = [ - "${FLASHD_HDC_PATH}/common/async_cmd.cpp", - "${FLASHD_HDC_PATH}/common/auth.cpp", - "${FLASHD_HDC_PATH}/common/base.cpp", - "${FLASHD_HDC_PATH}/common/channel.cpp", - "${FLASHD_HDC_PATH}/common/debug.cpp", - "${FLASHD_HDC_PATH}/common/file.cpp", - "${FLASHD_HDC_PATH}/common/file_descriptor.cpp", - "${FLASHD_HDC_PATH}/common/forward.cpp", - "${FLASHD_HDC_PATH}/common/session.cpp", - "${FLASHD_HDC_PATH}/common/task.cpp", - "${FLASHD_HDC_PATH}/common/tcp.cpp", - "${FLASHD_HDC_PATH}/common/transfer.cpp", - "${FLASHD_HDC_PATH}/common/usb.cpp", + "${FLASHD_PATH}/common/base.cpp", + "${HDC_PATH}/common/async_cmd.cpp", + "${HDC_PATH}/common/auth.cpp", + "${HDC_PATH}/common/channel.cpp", + "${HDC_PATH}/common/debug.cpp", + "${HDC_PATH}/common/file.cpp", + "${HDC_PATH}/common/file_descriptor.cpp", + "${HDC_PATH}/common/forward.cpp", + "${HDC_PATH}/common/session.cpp", + "${HDC_PATH}/common/task.cpp", + "${HDC_PATH}/common/tcp.cpp", + "${HDC_PATH}/common/transfer.cpp", + "${HDC_PATH}/common/usb.cpp", ] config("flashd_hdc_config") { - include_dirs = [ "${FLASHD_HDC_PATH}/common" ] + include_dirs = [ "${FLASHD_PATH}/common" ] cflags_cc = [ "-std=c++17" ] } ohos_source_set("flashd_deamon") { sources = [ - "${FLASHD_HDC_PATH}/daemon/daemon.cpp", - "${FLASHD_HDC_PATH}/daemon/daemon_app.cpp", - "${FLASHD_HDC_PATH}/daemon/daemon_forward.cpp", - "${FLASHD_HDC_PATH}/daemon/daemon_tcp.cpp", - "${FLASHD_HDC_PATH}/daemon/daemon_unity.cpp", - "${FLASHD_HDC_PATH}/daemon/daemon_usb.cpp", - "${FLASHD_HDC_PATH}/daemon/jdwp.cpp", - "${FLASHD_HDC_PATH}/daemon/shell.cpp", + "${FLASHD_PATH}/daemon/daemon.cpp", + "${FLASHD_PATH}/daemon/daemon_unity.cpp", + "${HDC_PATH}/daemon/daemon_app.cpp", + "${HDC_PATH}/daemon/daemon_forward.cpp", + "${HDC_PATH}/daemon/daemon_tcp.cpp", + "${HDC_PATH}/daemon/daemon_usb.cpp", + "${HDC_PATH}/daemon/jdwp.cpp", + "${HDC_PATH}/daemon/shell.cpp", ] sources += common_sources @@ -72,7 +73,8 @@ ohos_source_set("flashd_deamon") { } include_dirs = [ - "${FLASHD_HDC_PATH}/daemon", + "${HDC_PATH}/daemon", + "${HDC_PATH}/common", "//base/update/updater/services/flashd", "//base/update/updater/services/flashd/daemon", "//base/update/updater/services/flashd/common", @@ -128,11 +130,12 @@ ohos_static_library("libflashd") { ] include_dirs = [ - "${FLASHD_HDC_PATH}/daemon", - "${FLASHD_HDC_PATH}/common", + "${HDC_PATH}/daemon", + "${HDC_PATH}/common", "//base/update/updater/services", "//base/update/updater/services/flashd", "//base/update/updater/services/flashd/daemon", + "//base/update/updater/services/flashd/common", "//base/update/updater/interfaces/kits/include", "//base/update/updater/services/include/package", "//base/update/updater/services/include/script", @@ -167,17 +170,17 @@ ohos_executable("ohflash") { "-Wno-unused-variable", ] sources = [ - "${FLASHD_HDC_PATH}/host/client.cpp", - "${FLASHD_HDC_PATH}/host/host_app.cpp", - "${FLASHD_HDC_PATH}/host/host_forward.cpp", - "${FLASHD_HDC_PATH}/host/host_tcp.cpp", - "${FLASHD_HDC_PATH}/host/host_unity.cpp", - "${FLASHD_HDC_PATH}/host/host_updater.cpp", - "${FLASHD_HDC_PATH}/host/host_usb.cpp", - "${FLASHD_HDC_PATH}/host/main.cpp", - "${FLASHD_HDC_PATH}/host/server.cpp", - "${FLASHD_HDC_PATH}/host/server_for_client.cpp", - "${FLASHD_HDC_PATH}/host/translate.cpp", + "${FLASHD_PATH}/host/client.cpp", + "${FLASHD_PATH}/host/host_updater.cpp", + "${FLASHD_PATH}/host/main.cpp", + "${FLASHD_PATH}/host/server.cpp", + "${FLASHD_PATH}/host/server_for_client.cpp", + "${FLASHD_PATH}/host/translate.cpp", + "${HDC_PATH}/host/host_app.cpp", + "${HDC_PATH}/host/host_forward.cpp", + "${HDC_PATH}/host/host_tcp.cpp", + "${HDC_PATH}/host/host_unity.cpp", + "${HDC_PATH}/host/host_usb.cpp", ] sources += common_sources @@ -192,7 +195,10 @@ ohos_executable("ohflash") { deps += [ "//third_party/libusb:libusb" ] include_dirs = [ - "${FLASHD_HDC_PATH}/host", + "${FLASHD_PATH}/host", + "${HDC_PATH}/host", + "${FLASHD_PATH}/common", + "${HDC_PATH}/common", "//utils/native/base/include", "//third_party/lz4/lib", "//third_party/openssl/include", @@ -229,19 +235,11 @@ group("flashhost_target_standard_mingw") { group("flashhost_target_standard_all") { deps = [ - ":flashhost_target_standard", ":flashhost_target_standard_linux", ":flashhost_target_standard_mingw", ] } -group("flashhost_target_standard_windows") { - deps = [ - ":flashhost_target_standard", - ":flashhost_target_standard_mingw", - ] -} - group("updater_flashd") { deps = [ ":libflashd" ] } diff --git a/services/flashd/common/async_cmd.cpp b/services/flashd/common/async_cmd.cpp deleted file mode 100755 index 43d5f1a9..00000000 --- a/services/flashd/common/async_cmd.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "async_cmd.h" -#define PIPE_READ 0 -#define PIPE_WRITE 1 - -namespace Hdc { -// Do not add thread-specific init op in the following methods as it's running in child thread. -AsyncCmd::AsyncCmd() -{ - Base::ZeroStruct(stdinPipe); - Base::ZeroStruct(stdoutPipe); - Base::ZeroStruct(stderrPipe); - Base::ZeroStruct(proc); - Base::ZeroStruct(procOptions); - running = false; - loop = nullptr; -} - -AsyncCmd::~AsyncCmd() -{ - WRITE_LOG(LOG_DEBUG, "~AsyncCmd"); -}; - -bool AsyncCmd::ReadyForRelease() const -{ - return !running; -} - -// manual stop will not trigger ExitCallback, we call it -void AsyncCmd::DoRelease() -{ - if (hasStop || !running) { - return; - } - hasStop = true; // must set here to deny repeate release - uv_process_kill(&proc, SIGKILL); - WRITE_LOG(LOG_DEBUG, "AsyncCmd::DoRelease finish"); -} - -void AsyncCmd::ChildReadCallback(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) -{ - AsyncCmd *thisClass = (AsyncCmd *)stream->data; - if (nread <= 0) { // stdout and stderr - WRITE_LOG(LOG_DEBUG, "Read ShellChildProcess failed %s", uv_err_name(nread)); - } else { - if (thisClass->options & OPTION_READBACK_OUT) { - thisClass->cmdResult = buf->base; - if (!thisClass->resultCallback(false, 0, thisClass->cmdResult)) { - uv_process_kill(&thisClass->proc, SIGKILL); - uv_read_stop(stream); - } - thisClass->cmdResult = STRING_EMPTY; - } else { // output all when finish - thisClass->cmdResult += buf->base; - } - } - delete[] buf->base; -} - -void AsyncCmd::ExitCallback(uv_process_t *req, int64_t exitStatus, int tersignal) -{ - auto funcReqClose = [](uv_handle_t *handle) -> void { - AsyncCmd *thisClass = (AsyncCmd *)handle->data; - if (--thisClass->uvRef == 0) { - thisClass->running = false; - } - }; - AsyncCmd *thisClass = (AsyncCmd *)req->data; - thisClass->hasStop = true; // callback maybe call dorelease, so deny repeate ExitCallback - - thisClass->resultCallback(true, exitStatus, thisClass->cmdResult); - WRITE_LOG(LOG_DEBUG, "AsyncCmd::ExitCallback"); - thisClass->uvRef = 4; - Base::TryCloseHandle((uv_handle_t *)&thisClass->stdinPipe, true, funcReqClose); - Base::TryCloseHandle((uv_handle_t *)&thisClass->stdoutPipe, true, funcReqClose); - Base::TryCloseHandle((uv_handle_t *)&thisClass->stderrPipe, true, funcReqClose); - Base::TryCloseHandle((uv_handle_t *)req, true, funcReqClose); - thisClass->cmdResult = STRING_EMPTY; -} - -bool AsyncCmd::Initial(uv_loop_t *loopIn, const CmdResultCallback callback, uint32_t optionsIn) -{ - if (running) { - return false; - } - loop = loopIn; - resultCallback = callback; - options = optionsIn; - return true; -} - -bool AsyncCmd::ExecuteCommand(const string &command) -{ - string cmd = command; - Base::Trim(cmd, "\""); - if (!(options & OPTION_COMMAND_ONETIME)) { - if (StartProcess() < 0) { - return false; - } - if (options & OPTION_APPEND_NEWLINE) { - cmd += "\n"; - } - Base::SendToStream((uv_stream_t *)&stdinPipe, (uint8_t *)cmd.c_str(), cmd.size() + 1); - } else { - if (StartProcess(cmd) < 0) { - return false; - } - } - return true; -} - -int AsyncCmd::StartProcess(string command) -{ - constexpr auto countStdIOCount = 3; - char **ppShellArgs = nullptr; - string shellPath = Base::GetShellPath(); - uv_stdio_container_t stdioShellProc[countStdIOCount]; - while (true) { - uv_pipe_init(loop, &stdinPipe, 1); - uv_pipe_init(loop, &stdoutPipe, 1); - uv_pipe_init(loop, &stderrPipe, 1); - stdinPipe.data = this; - stdoutPipe.data = this; - stderrPipe.data = this; - procOptions.stdio = stdioShellProc; - procOptions.stdio[STDIN_FILENO].flags = (uv_stdio_flags)(UV_CREATE_PIPE | UV_READABLE_PIPE); - procOptions.stdio[STDIN_FILENO].data.stream = (uv_stream_t *)&stdinPipe; - procOptions.stdio[STDOUT_FILENO].flags = (uv_stdio_flags)(UV_CREATE_PIPE | UV_WRITABLE_PIPE); - procOptions.stdio[STDOUT_FILENO].data.stream = (uv_stream_t *)&stdoutPipe; - procOptions.stdio[STDERR_FILENO].flags = (uv_stdio_flags)(UV_CREATE_PIPE | UV_WRITABLE_PIPE); - procOptions.stdio[STDERR_FILENO].data.stream = (uv_stream_t *)&stderrPipe; - procOptions.stdio_count = countStdIOCount; - procOptions.file = shellPath.c_str(); - procOptions.exit_cb = ExitCallback; - - if (command.size() > 0) { - constexpr auto args = 4; - ppShellArgs = new char *[args]; - const string shellCommandFlag = "-c"; - ppShellArgs[0] = (char *)shellPath.c_str(); - ppShellArgs[1] = (char *)shellCommandFlag.c_str(); - ppShellArgs[args - CMD_ARG1_COUNT] = (char *)command.c_str(); - ppShellArgs[args - 1] = nullptr; - } else { - ppShellArgs = new char *[CMD_ARG1_COUNT]; - ppShellArgs[0] = (char *)shellPath.c_str(); - ppShellArgs[1] = nullptr; - } - procOptions.args = ppShellArgs; - proc.data = this; - - if (uv_spawn(loop, &proc, &procOptions)) { - WRITE_LOG(LOG_FATAL, "Spawn shell process failed"); - break; - } - if (uv_read_start((uv_stream_t *)&stdoutPipe, Base::AllocBufferCallback, ChildReadCallback)) { - break; - } - if (uv_read_start((uv_stream_t *)&stderrPipe, Base::AllocBufferCallback, ChildReadCallback)) { - break; - } - running = true; - break; - } - if (ppShellArgs) { - delete[] ppShellArgs; - } - if (!running) { - // failed - resultCallback(true, -1, "Start process failed"); - return -1; - } else { - return 0; - } -} -} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/common/async_cmd.h b/services/flashd/common/async_cmd.h deleted file mode 100755 index f7772282..00000000 --- a/services/flashd/common/async_cmd.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_ASYNC_CMD_H -#define HDC_ASYNC_CMD_H -#include "common.h" - -namespace Hdc { -class AsyncCmd { -public: - AsyncCmd(); - virtual ~AsyncCmd(); - enum AsyncCmdOption { - OPTION_APPEND_NEWLINE = 1, - OPTION_COMMAND_ONETIME = 2, - OPTION_READBACK_OUT = 4, - USB_OPTION_RESERVE8 = 8, - }; - // 1)is finish 2)exitStatus 3)resultString(maybe empty) - using CmdResultCallback = std::function; - static uint32_t GetDefaultOption() - { - return OPTION_APPEND_NEWLINE | OPTION_COMMAND_ONETIME; - } - // uv_loop_t loop is given to uv_spawn, which can't be const - bool Initial(uv_loop_t *loopIn, const CmdResultCallback callback, uint32_t optionsIn = GetDefaultOption()); - void DoRelease(); // Release process resources - bool ExecuteCommand(const string &command); - bool ReadyForRelease() const; - -private: - int StartProcess(string command = STRING_EMPTY); - // uv_read_cb callback 1st parameter can't be changed, const can't be added - static void ChildReadCallback(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); - // uv_exit_cb callback 1st parameter can't be changed, const can't be added - static void ExitCallback(uv_process_t *req, int64_t exitStatus, int tersignal); - - uv_loop_t *loop; - // loop is given to uv_spawn, which can't be const - uv_pipe_t stdinPipe; - uv_pipe_t stdoutPipe; - uv_pipe_t stderrPipe; - uv_process_t proc; - uv_process_options_t procOptions; - CmdResultCallback resultCallback; - string cmdResult; - bool running; - bool hasStop = false; - uint32_t options = 0; - uint8_t uvRef = 0; -}; -} // namespace Hdc -#endif \ No newline at end of file diff --git a/services/flashd/common/auth.cpp b/services/flashd/common/auth.cpp deleted file mode 100755 index 50f148b4..00000000 --- a/services/flashd/common/auth.cpp +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "auth.h" -#include -#include -#include -#include -#include - -using namespace Hdc; -#define BIGNUMTOBIT 32 - -namespace HdcAuth { -// ---------------------------------------Cheat compiler--------------------------------------------------------- -#ifdef HDC_HOST - -bool AuthVerify(uint8_t *token, uint8_t *sig, int siglen) -{ - return false; -}; -bool PostUIConfirm(string publicKey) -{ - return false; -} - -#else // daemon - -bool GenerateKey(const char *file) -{ - return false; -}; -int AuthSign(void *rsa, const unsigned char *token, size_t tokenSize, void *sig) -{ - return 0; -}; -int GetPublicKeyFileBuf(unsigned char *data, size_t len) -{ - return 0; -} - -#endif -// ------------------------------------------------------------------------------------------------ - -const uint32_t RSANUMBYTES = 256; // 2048 bit key length -const uint32_t RSANUMWORDS = (RSANUMBYTES / sizeof(uint32_t)); -struct RSAPublicKey { - int wordModulusSize; // Length of n[] in number of uint32_t */ - uint32_t rsaN0inv; // -1 / n[0] mod 2^32 - uint32_t modulus[RSANUMWORDS]; // modulus as little endian array - uint32_t rr[RSANUMWORDS]; // R^2 as little endian array - int exponent; // 3 or 65537 -}; - -#ifdef HDC_HOST -// Convert OpenSSL RSA private key to pre-computed RSAPublicKey format -int RSA2RSAPublicKey(RSA *rsa, RSAPublicKey *publicKey) -{ - int result = 1; - unsigned int i; - BN_CTX *ctx = BN_CTX_new(); - BIGNUM *r32 = BN_new(); - BIGNUM *rsaRR = BN_new(); - BIGNUM *rsaR = BN_new(); - BIGNUM *rsaRem = BN_new(); - BIGNUM *rsaN0inv = BN_new(); -#ifdef OPENSSL_IS_BORINGSSL - // boringssl - BIGNUM *n = BN_new(); - BN_copy(n, rsa->n); - publicKey->exponent = BN_get_word(rsa->e); -#else - // openssl -#if OPENSSL_VERSION_NUMBER >= 0x10100005L - BIGNUM *n = (BIGNUM *)RSA_get0_n(rsa); - publicKey->exponent = BN_get_word(RSA_get0_e(rsa)); -#else - BIGNUM *n = BN_new(); - BN_copy(n, rsa->n); - publicKey->exponent = BN_get_word(rsa->e); -#endif - -#endif // OPENSSL_IS_BORINGSSL - while (true) { - if (RSA_size(rsa) != RSANUMBYTES) { - result = 0; - break; - } - - BN_set_bit(r32, BIGNUMTOBIT); - BN_set_bit(rsaR, RSANUMWORDS * BIGNUMTOBIT); - BN_mod_sqr(rsaRR, rsaR, n, ctx); - BN_div(nullptr, rsaRem, n, r32, ctx); - BN_mod_inverse(rsaN0inv, rsaRem, r32, ctx); - publicKey->wordModulusSize = RSANUMWORDS; - publicKey->rsaN0inv = 0 - BN_get_word(rsaN0inv); - for (i = 0; i < RSANUMWORDS; ++i) { - BN_div(rsaRR, rsaRem, rsaRR, r32, ctx); - publicKey->rr[i] = BN_get_word(rsaRem); - BN_div(n, rsaRem, n, r32, ctx); - publicKey->modulus[i] = BN_get_word(rsaRem); - } - break; - } - - BN_free(rsaR); - BN_free(rsaRR); - BN_free(n); - BN_free(r32); - BN_free(rsaN0inv); - BN_free(rsaRem); - BN_CTX_free(ctx); - return result; -} - -int GetUserInfo(char *buf, size_t len) -{ - char hostname[BUF_SIZE_DEFAULT]; - char username[BUF_SIZE_DEFAULT]; - uv_passwd_t pwd; - int ret = -1; - size_t bufSize = sizeof(hostname); - if (uv_os_gethostname(hostname, &bufSize) < 0 && EOK != strcpy_s(hostname, sizeof(hostname), "unknown")) { - return ERR_API_FAIL; - } - if (!uv_os_get_passwd(&pwd) && !strcpy_s(username, sizeof(username), pwd.username)) { - ret = 0; - } - uv_os_free_passwd(&pwd); - if (ret < 0 && EOK != strcpy_s(username, sizeof(username), "unknown")) { - return ERR_API_FAIL; - } - if (snprintf_s(buf, len, len - 1, " %s@%s", username, hostname) < 0) { - return ERR_BUF_OVERFLOW; - } - return RET_SUCCESS; -} - -int WritePublicKeyfile(RSA *private_key, const char *private_key_path) -{ - RSAPublicKey publicKey; - char info[BUF_SIZE_DEFAULT]; - int ret = 0; - string path = private_key_path + string(".pub"); - - ret = RSA2RSAPublicKey(private_key, &publicKey); - if (!ret) { - WRITE_LOG(LOG_DEBUG, "Failed to convert to publickey\n"); - return 0; - } - vector vec = Base::Base64Encode((const uint8_t *)&publicKey, sizeof(RSAPublicKey)); - if (!vec.size()) { - return 0; - } - GetUserInfo(info, sizeof(info)); - vec.insert(vec.end(), (uint8_t *)info, (uint8_t *)info + strlen(info)); - ret = Base::WriteBinFile(path.c_str(), vec.data(), vec.size(), true); - return ret >= 0 ? 1 : 0; -} - -bool GenerateKey(const char *file) -{ - EVP_PKEY *publicKey = EVP_PKEY_new(); - BIGNUM *exponent = BN_new(); - RSA *rsa = RSA_new(); - mode_t old_mask; - FILE *fKey = nullptr; - bool ret = false; - - while (true) { - WRITE_LOG(LOG_DEBUG, "generate_key '%s'\n", file); - if (!publicKey || !exponent || !rsa) { - WRITE_LOG(LOG_DEBUG, "Failed to allocate key"); - break; - } - - BN_set_word(exponent, RSA_F4); - RSA_generate_key_ex(rsa, 2048, exponent, nullptr); - EVP_PKEY_set1_RSA(publicKey, rsa); - old_mask = umask(077); // 077:permission - - fKey = fopen(file, "w"); - if (!fKey) { - WRITE_LOG(LOG_DEBUG, "Failed to open '%s'\n", file); - umask(old_mask); - break; - } - umask(old_mask); - if (!PEM_write_PrivateKey(fKey, publicKey, nullptr, nullptr, 0, nullptr, nullptr)) { - WRITE_LOG(LOG_DEBUG, "Failed to write key"); - break; - } - if (!WritePublicKeyfile(rsa, file)) { - WRITE_LOG(LOG_DEBUG, "Failed to write public key"); - break; - } - ret = true; - break; - } - - RSA_free(rsa); - EVP_PKEY_free(publicKey); - BN_free(exponent); - if (fKey) - fclose(fKey); - return ret; -} - -bool ReadKey(const char *file, list *listPrivateKey) -{ - FILE *f = nullptr; - bool ret = false; - - while (true) { - if (!(f = fopen(file, "r"))) { - break; - } - RSA *rsa = RSA_new(); - if (!PEM_read_RSAPrivateKey(f, &rsa, nullptr, nullptr)) { - RSA_free(rsa); - break; - } - listPrivateKey->push_back((void *)rsa); - ret = true; - break; - } - if (f) { - fclose(f); - } - return ret; -} - -int GetUserKeyPath(string &path) -{ - struct stat status; - const char harmoneyPath[] = ".harmony"; - const char hdcKeyFile[] = "hdckey"; - char buf[BUF_SIZE_DEFAULT]; - size_t len = BUF_SIZE_DEFAULT; - // $home - if (uv_os_homedir(buf, &len) < 0) - return false; - path = string(buf) + Base::GetPathSep() + string(harmoneyPath) + Base::GetPathSep(); - if (stat(path.c_str(), &status)) { - uv_fs_t req; - uv_fs_mkdir(nullptr, &req, path.c_str(), 0750, nullptr); // 0750:permission - uv_fs_req_cleanup(&req); - if (req.result < 0) { - WRITE_LOG(LOG_DEBUG, "Cannot mkdir '%s'", path.c_str()); - return false; - } - } - path += hdcKeyFile; - return true; -} - -bool LoadHostUserKey(list *listPrivateKey) -{ - struct stat status; - string path; - if (!GetUserKeyPath(path)) { - return false; - } - if (stat(path.c_str(), &status) == -1) { - if (!GenerateKey(path.c_str())) { - WRITE_LOG(LOG_DEBUG, "Failed to generate new key"); - return false; - } - } - if (!ReadKey(path.c_str(), listPrivateKey)) { - return false; - } - return true; -} - -int AuthSign(void *rsa, const unsigned char *token, size_t tokenSize, void *sig) -{ - unsigned int len; - if (!RSA_sign(NID_sha1, token, tokenSize, (unsigned char *)sig, &len, (RSA *)rsa)) { - return 0; - } - return (int)len; -} - -int GetPublicKeyFileBuf(unsigned char *data, size_t len) -{ - string path; - int ret; - - if (!GetUserKeyPath(path)) { - return 0; - } - path += ".pub"; - ret = Base::ReadBinFile(path.c_str(), (void **)data, len); - if (ret <= 0) { - return 0; - } - data[ret] = '\0'; - return ret + 1; -} - -#else // daemon - -bool RSAPublicKey2RSA(const uint8_t *keyBuf, RSA **key) -{ - const int pubKeyModulusSize = 256; - const int pubKeyModulusSizeWords = pubKeyModulusSize / 4; - - const RSAPublicKey *keyStruct = reinterpret_cast(keyBuf); - bool ret = false; - uint8_t modulusBuffer[pubKeyModulusSize]; - RSA *newKey = RSA_new(); - if (!newKey) { - goto cleanup; - } - if (keyStruct->wordModulusSize != pubKeyModulusSizeWords) { - goto cleanup; - } - if (memcpy_s(modulusBuffer, sizeof(modulusBuffer), keyStruct->modulus, sizeof(modulusBuffer)) != EOK) { - goto cleanup; - } - Base::ReverseBytes(modulusBuffer, sizeof(modulusBuffer)); - -#ifdef OPENSSL_IS_BORINGSSL - // boringssl - newKey->n = BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr); - newKey->e = BN_new(); - if (!newKey->e || !BN_set_word(newKey->e, keyStruct->exponent) || !newKey->n) { - goto cleanup; - } -#else - // openssl -#if OPENSSL_VERSION_NUMBER >= 0x10100005L - RSA_set0_key(newKey, BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr), BN_new(), BN_new()); -#else - newKey->n = BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr); - newKey->e = BN_new(); - if (!newKey->e || !BN_set_word(newKey->e, keyStruct->exponent) || !newKey->n) { - goto cleanup; - } -#endif -#endif - - *key = newKey; - ret = true; - -cleanup: - if (!ret && newKey) { - RSA_free(newKey); - } - return ret; -} - -void ReadDaemonKeys(const char *file, list *listPublicKey) -{ - char buf[BUF_SIZE_DEFAULT2]; - char *sep = nullptr; - int ret; - FILE *f = fopen(file, "re"); - if (!f) { - WRITE_LOG(LOG_DEBUG, "Can't open '%s'", file); - return; - } - while (fgets(buf, sizeof(buf), f)) { - RSAPublicKey *key = new RSAPublicKey(); - if (!key) { - break; - } - sep = strpbrk(buf, " \t"); - if (sep) { - *sep = '\0'; - } - ret = Base::Base64DecodeBuf(reinterpret_cast(buf), strlen(buf), (uint8_t *)key); - if (ret != sizeof(RSAPublicKey)) { - WRITE_LOG(LOG_DEBUG, "%s: Invalid base64 data ret=%d", file, ret); - delete key; - continue; - } - - if (key->wordModulusSize != RSANUMWORDS) { - WRITE_LOG(LOG_DEBUG, "%s: Invalid key len %d\n", file, key->wordModulusSize); - delete key; - continue; - } - listPublicKey->push_back(key); - } - fclose(f); -} - -bool AuthVerify(uint8_t *token, uint8_t *sig, int siglen) -{ - list listPublicKey; - uint8_t authKeyIndex = 0; - void *ptr = nullptr; - int ret = 0; - int childRet = 0; - while (KeylistIncrement(&listPublicKey, authKeyIndex, &ptr)) { - RSA *rsa = nullptr; - if (!RSAPublicKey2RSA((const uint8_t *)ptr, &rsa)) { - break; - } - childRet = RSA_verify(NID_sha1, (const unsigned char *)token, RSA_TOKEN_SIZE, (const unsigned char *)sig, - siglen, rsa); - RSA_free(rsa); - if (childRet) { - ret = 1; - break; - } - } - FreeKey(true, &listPublicKey); - return ret; -} - -void LoadDaemonKey(list *listPublicKey) -{ -#ifdef HDC_PCDEBUG - char keyPaths[][BUF_SIZE_SMALL] = { "/root/.harmony/hdckey.pub" }; -#else - char keyPaths[][BUF_SIZE_SMALL] = { "/hdc_keys", "/data/misc/hdc/hdc_keys" }; -#endif - int num = sizeof(keyPaths) / sizeof(keyPaths[0]); - struct stat buf; - - for (int i = 0; i < num; ++i) { - char *p = keyPaths[i]; - if (!stat(p, &buf)) { - WRITE_LOG(LOG_DEBUG, "Loading keys from '%s'", p); - ReadDaemonKeys(p, listPublicKey); - } - } -} - -bool PostUIConfirm(string publicKey) -{ - // Because the Hi3516 development board has no UI support for the time being, all public keys are received and - // By default, the system UI will record the public key /data/misc/hdc/hdckey/data/misc/hdc/hdckey - return true; -} -#endif // HDC_HOST - -// --------------------------------------common code------------------------------------------ -bool KeylistIncrement(list *listKey, uint8_t &authKeyIndex, void **out) -{ - if (!listKey->size()) { -#ifdef HDC_HOST - LoadHostUserKey(listKey); -#else - LoadDaemonKey(listKey); -#endif - } - if (authKeyIndex == listKey->size()) { - // all finish - return false; - } - auto listIndex = listKey->begin(); - std::advance(listIndex, ++authKeyIndex); - *out = *listIndex; - if (!*out) { - return false; - } - return true; -} - -void FreeKey(bool publicOrPrivate, list *listKey) -{ - for (auto &&v : *listKey) { - if (publicOrPrivate) { - delete (RSAPublicKey *)v; - v = nullptr; - } else { - RSA_free((RSA *)v); - v = nullptr; - } - } - listKey->clear(); -} -} diff --git a/services/flashd/common/auth.h b/services/flashd/common/auth.h deleted file mode 100755 index 1e2083b6..00000000 --- a/services/flashd/common/auth.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_AUTH_H -#define HDC_AUTH_H -#include "common.h" - -// If these functions occupy too high a load, you can consider placing them in a thread for execution, and perform -// subsequent processing in the callback directly after completion. -namespace HdcAuth { -const uint8_t RSA_TOKEN_SIZE = 20; // SHA_DIGEST_LENGTH -// in host out==RSA*, in daemon out=RSAPublicKey* -bool KeylistIncrement(list *listKey, uint8_t &authKeyIndex, void **out); -void FreeKey(bool publicOrPrivate, list *listKey); - -// host -bool GenerateKey(const char *file); -int AuthSign(void *rsa, const unsigned char *token, size_t tokenSize, void *sig); -int GetPublicKeyFileBuf(unsigned char *data, size_t len); - -// daemon -bool AuthVerify(uint8_t *token, uint8_t *sig, int siglen); -bool PostUIConfirm(string pkey); -} - -#endif \ No newline at end of file diff --git a/services/flashd/common/base.h b/services/flashd/common/base.h deleted file mode 100755 index 9a6b12be..00000000 --- a/services/flashd/common/base.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_BASE_H -#define HDC_BASE_H -#include "common.h" - -namespace Hdc { -namespace Base { - void SetLogLevel(const uint8_t logLevel); - void PrintLogEx(const char *functionName, int line, uint8_t logLevel, const char *msg, ...); - void PrintMessage(const char *fmt, ...); - // tcpHandle can't be const as it's passed into uv_tcp_keepalive - void SetTcpOptions(uv_tcp_t *tcpHandle); - // Realloc need to update origBuf&origSize which can't be const - void ReallocBuf(uint8_t **origBuf, int *nOrigSize, const int indexUsedBuf, int sizeWanted); - // handle&sendHandle must keep sync with uv_write - int SendToStreamEx(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen, uv_stream_t *handleSend, - const void *finishCallback, const void *pWriteReqData); - int SendToStream(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen); - // As an uv_write_cb it must keep the same as prototype - void SendCallback(uv_write_t *req, int status); - // As an uv_alloc_cb it must keep the same as prototype - void AllocBufferCallback(uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf); - uint64_t GetRuntimeMSec(); - string GetRandomString(const uint16_t expectedLen); - int GetRandomNum(const int min, const int max); - uint64_t GetRandom(const uint64_t min = 0, const uint64_t max = UINT64_MAX); - int ConnectKey2IPPort(const char *connectKey, char *outIP, uint16_t *outPort); - // As an uv_work_cb it must keep the same as prototype - // clang-format off - int StartWorkThread(uv_loop_t *loop, uv_work_cb pFuncWorkThread, - uv_after_work_cb pFuncAfterThread, void *pThreadData); - // clang-format on - // As an uv_work_cb it must keep the same as prototype - void FinishWorkThread(uv_work_t *req, int status); - int GetMaxBufSize(); - bool TryCloseLoop(uv_loop_t *ptrLoop, const char *callerName); - void TryCloseHandle(const uv_handle_t *handle); - void TryCloseHandle(const uv_handle_t *handle, uv_close_cb closeCallBack); - void TryCloseHandle(const uv_handle_t *handle, bool alwaysCallback, uv_close_cb closeCallBack); - char **SplitCommandToArgs(const char *cmdStringLine, int *slotIndex); - bool SetHdcProperty(const char *key, const char *value); - // value needs to save results which can't be const - bool GetHdcProperty(const char *key, char *value, uint16_t sizeOutBuf); - bool RunPipeComand(const char *cmdString, char *outBuf, uint16_t sizeOutBuf, bool ignoreTailLF); - // results need to save in buf which can't be const - int ReadBinFile(const char *pathName, void **buf, const int bufLen); - int WriteBinFile(const char *pathName, const uint8_t *buf, const int bufLen, bool newFile = false); - void CloseIdleCallback(uv_handle_t *handle); - void CloseTimerCallback(uv_handle_t *handle); - int ProgramMutex(const char *procname, bool checkOrNew); - // result needs to save results which can't be const - void SplitString(const string &origString, const string &seq, vector &resultStrings); - string GetShellPath(); - uint64_t HostToNet(uint64_t val); - uint64_t NetToHost(uint64_t val); - string GetFullFilePath(const string &s); - int CreateSocketPair(int *fds); - void CloseSocketPair(const int *fds); - int StringEndsWith(string s, string sub); - bool CheckDirectoryOrPath(const char *localPath, bool pathOrDir, bool readWrite); - int Base64EncodeBuf(const uint8_t *input, const int length, uint8_t *bufOut); - vector Base64Encode(const uint8_t *input, const int length); - int Base64DecodeBuf(const uint8_t *input, const int length, uint8_t *bufOut); - string Base64Decode(const uint8_t *input, const int length); - void ReverseBytes(void *start, int size); - string CanonicalizeSpecPath(string &src); - // Just zero a POD type, such as a structure or union - template int ZeroStruct(T &structBuf) - { - return memset_s(&structBuf, sizeof(T), 0, sizeof(T)); - } - // just zero a statically allocated array of POD or built-in types - template int ZeroArray(T (&arrayBuf)[N]) - { - return memset_s(arrayBuf, sizeof(T) * N, 0, sizeof(T) * N); - } - // just zero memory buf, such as pointer - template int ZeroBuf(T &arrayBuf, int size) - { - return memset_s(arrayBuf, size, 0, size); - } - // clang-format off - const string StringFormat(const char * const formater, ...); - const string StringFormat(const char * const formater, va_list &vaArgs); - // clang-format on - string GetVersion(); - bool IdleUvTask(uv_loop_t *loop, void *data, uv_idle_cb cb); - bool TimerUvTask(uv_loop_t *loop, void *data, uv_timer_cb cb, int repeatTimeout = UV_DEFAULT_INTERVAL); - bool DelayDo(uv_loop_t *loop, const int delayMs, const uint8_t flag, string msg, void *data, - std::function cb); - inline bool DelayDoSimple(uv_loop_t *loop, const int delayMs, - std::function cb) - { - return DelayDo(loop, delayMs, 0, "", nullptr, cb); - } - inline bool DoNextLoop(uv_loop_t *loop, void *data, std::function cb) - { - return DelayDo(loop, 0, 0, "", data, cb); - } - - // Trim from right side - inline string &RightTrim(string &s, const string &w = WHITE_SPACES) - { - s.erase(s.find_last_not_of(w) + 1); - return s; - } - - // Trim from left side - inline string &LeftTrim(string &s, const string &w = WHITE_SPACES) - { - s.erase(0, s.find_first_not_of(w)); - return s; - } - - // Trim from both sides - inline string &Trim(string &s, const string &w = WHITE_SPACES) - { - return LeftTrim(RightTrim(s, w), w); - } - string ReplaceAll(string str, const string from, const string to); - uint8_t CalcCheckSum(const uint8_t *data, int len); - string GetFileNameAny(string &path); - string GetCwd(); - string GetTmpDir(); - uv_os_sock_t DuplicateUvSocket(uv_tcp_t *tcp); - vector Md5Sum(uint8_t *buf, int size); - bool IsRoot(); - char GetPathSep(); - bool IsAbsolutePath(string &path); -} // namespace base -} // namespace Hdc - -#endif // HDC_BASE_H \ No newline at end of file diff --git a/services/flashd/common/channel.cpp b/services/flashd/common/channel.cpp deleted file mode 100755 index 8d944ac5..00000000 --- a/services/flashd/common/channel.cpp +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "channel.h" -namespace Hdc { -HdcChannelBase::HdcChannelBase(const bool serverOrClient, const string &addrString, uv_loop_t *loopMainIn) -{ - SetChannelTCPString(addrString); - isServerOrClient = serverOrClient; - loopMain = loopMainIn; - uv_rwlock_init(&mainAsync); - uv_async_init(loopMain, &asyncMainLoop, MainAsyncCallback); - uv_rwlock_init(&lockMapChannel); -} - -HdcChannelBase::~HdcChannelBase() -{ - ClearChannels(); - // clear - if (!uv_is_closing((uv_handle_t *)&asyncMainLoop)) { - uv_close((uv_handle_t *)&asyncMainLoop, nullptr); - } - - uv_rwlock_destroy(&mainAsync); - uv_rwlock_destroy(&lockMapChannel); -} - -vector HdcChannelBase::GetChannelHandshake(string &connectKey) const -{ - vector ret; - // clang-format off - struct ChannelHandShake handshake = {{0}}; - // clang-format on - Base::ZeroStruct(handshake); - if (strcpy_s(handshake.banner, sizeof(handshake.banner), HANDSHAKE_MESSAGE.c_str()) != EOK) { - return ret; - } - if (strcpy_s(handshake.connectKey, sizeof(handshake.connectKey), connectKey.c_str()) != EOK) { - return ret; - } - ret.insert(ret.begin(), (uint8_t *)&handshake, (uint8_t *)&handshake + sizeof(ChannelHandShake)); - return ret; -} - -bool HdcChannelBase::SetChannelTCPString(const string &addrString) -{ - bool ret = false; - while (true) { - if (addrString.find(":") == string::npos) { - break; - } - string host = addrString.substr(0, addrString.find(":")); - string port = addrString.substr(addrString.find(":") + 1); - channelPort = std::atoi(port.c_str()); - sockaddr_in addr; - if (!channelPort || uv_ip4_addr(host.c_str(), channelPort, &addr) != 0) { - break; - } - channelHost = host; - channelHostPort = addrString; - ret = true; - break; - } - if (!ret) { - channelPort = 0; - channelHost = STRING_EMPTY; - channelHostPort = STRING_EMPTY; - } - return ret; -} - -void HdcChannelBase::ClearChannels() -{ - for (auto v : mapChannel) { - HChannel hChannel = (HChannel)v.second; - if (!hChannel->isDead) { - FreeChannel(hChannel->channelId); - } - } -} - -void HdcChannelBase::WorkerPendding() -{ - WRITE_LOG(LOG_DEBUG, "Begin host channel pendding"); - uv_run(loopMain, UV_RUN_DEFAULT); - uv_loop_close(loopMain); -} - -void HdcChannelBase::ReadStream(uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) -{ - int size = 0; - int indexBuf = 0; - int childRet = 0; - bool needExit = false; - HChannel hChannel = (HChannel)tcp->data; - HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; - - if (nread == UV_ENOBUFS) { - WRITE_LOG(LOG_DEBUG, "HdcChannelBase::ReadStream Pipe IOBuf max"); - return; - } else if (nread == 0) { - // maybe just afer accept, second client req - WRITE_LOG(LOG_DEBUG, "HdcChannelBase::ReadStream idle read"); - return; - } else if (nread < 0) { - Base::TryCloseHandle((uv_handle_t *)tcp); - WRITE_LOG(LOG_DEBUG, "HdcChannelBase::ReadStream failed2:%s", uv_err_name(nread)); - needExit = true; - goto Finish; - } else { - hChannel->availTailIndex += nread; - } - while (hChannel->availTailIndex > DWORD_SERIALIZE_SIZE) { - size = ntohl(*(uint32_t *)(hChannel->ioBuf + indexBuf)); // big endian - if (size <= 0 || (uint32_t)size > HDC_BUF_MAX_BYTES) { - needExit = true; - break; - } - if (hChannel->availTailIndex - DWORD_SERIALIZE_SIZE < size) { - break; - } - childRet = thisClass->ReadChannel(hChannel, (uint8_t *)hChannel->ioBuf + DWORD_SERIALIZE_SIZE + indexBuf, size); - if (childRet < 0) { - if (!hChannel->keepAlive) { - needExit = true; - break; - } - } - // update io - hChannel->availTailIndex -= (DWORD_SERIALIZE_SIZE + size); - indexBuf += DWORD_SERIALIZE_SIZE + size; - } - if (indexBuf > 0 && hChannel->availTailIndex > 0) { - if (memmove_s(hChannel->ioBuf, hChannel->bufSize, hChannel->ioBuf + indexBuf, hChannel->availTailIndex)) { - needExit = true; - goto Finish; - } - } - -Finish: - if (needExit) { - thisClass->FreeChannel(hChannel->channelId); - WRITE_LOG(LOG_DEBUG, "Read Stream needExit, FreeChannel finish"); - } -} - -void HdcChannelBase::WriteCallback(uv_write_t *req, int status) -{ - HChannel hChannel = (HChannel)req->handle->data; - --hChannel->sendRef; - HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; - if (status < 0) { - Base::TryCloseHandle((uv_handle_t *)req->handle); - if (!hChannel->isDead && !hChannel->sendRef) { - thisClass->FreeChannel(hChannel->channelId); - WRITE_LOG(LOG_DEBUG, "WriteCallback TryCloseHandle"); - } - } - delete[]((uint8_t *)req->data); - delete req; -} - -void HdcChannelBase::AsyncMainLoopTask(uv_idle_t *handle) -{ - AsyncParam *param = (AsyncParam *)handle->data; - HdcChannelBase *thisClass = (HdcChannelBase *)param->thisClass; - - switch (param->method) { - case ASYNC_FREE_SESSION: { - // alloc/release should pair in main thread. - thisClass->FreeChannel(param->sid); - break; - } - default: - break; - } - if (param->data) { - delete[]((uint8_t *)param->data); - } - delete param; - uv_close((uv_handle_t *)handle, Base::CloseIdleCallback); -} - -// multiple uv_async_send() calls may be merged by libuv,so not each call will yield callback as expected. -// eg: if uv_async_send() 5 times before callback calling,it will be called only once. -// if uv_async_send() is called again after callback calling, it will be called again. -void HdcChannelBase::MainAsyncCallback(uv_async_t *handle) -{ - HdcChannelBase *thisClass = (HdcChannelBase *)handle->data; - if (uv_is_closing((uv_handle_t *)thisClass->loopMain)) { - return; - } - list::iterator i; - list &lst = thisClass->lstMainThreadOP; - uv_rwlock_wrlock(&thisClass->mainAsync); - for (i = lst.begin(); i != lst.end();) { - AsyncParam *param = (AsyncParam *)*i; - Base::IdleUvTask(thisClass->loopMain, param, AsyncMainLoopTask); - i = lst.erase(i); - } - uv_rwlock_wrunlock(&thisClass->mainAsync); -} - -void HdcChannelBase::PushAsyncMessage(const uint32_t channelId, const uint8_t method, const void *data, - const int dataSize) -{ - if (uv_is_closing((uv_handle_t *)&asyncMainLoop)) { - return; - } - auto param = new AsyncParam(); - if (!param) { - return; - } - param->sid = channelId; // Borrow SID storage - param->thisClass = this; - param->method = method; - if (dataSize > 0) { - param->dataSize = dataSize; - param->data = new uint8_t[param->dataSize](); - if (!param->data) { - delete param; - return; - } - if (memcpy_s((uint8_t *)param->data, param->dataSize, data, dataSize)) { - delete[]((uint8_t *)param->data); - delete param; - return; - } - } - asyncMainLoop.data = this; - uv_rwlock_wrlock(&mainAsync); - lstMainThreadOP.push_back(param); - uv_rwlock_wrunlock(&mainAsync); - uv_async_send(&asyncMainLoop); -} - -// client to server, or vice versa -// works only in current working thread -void HdcChannelBase::Send(const uint32_t channelId, uint8_t *bufPtr, const int size) -{ - uv_stream_t *sendStream = nullptr; - int sizeNewBuf = size + DWORD_SERIALIZE_SIZE; - HChannel hChannel = (HChannel)AdminChannel(OP_QUERY, channelId, nullptr); - if (!hChannel || hChannel->isDead) { - return; - } - auto data = new uint8_t[sizeNewBuf](); - if (!data) { - return; - } - *(uint32_t *)data = htonl(size); // big endian - if (memcpy_s(data + DWORD_SERIALIZE_SIZE, sizeNewBuf - DWORD_SERIALIZE_SIZE, bufPtr, size)) { - delete[] data; - return; - } - if (hChannel->hWorkThread == uv_thread_self()) { - sendStream = (uv_stream_t *)&hChannel->hWorkTCP; - } else { - sendStream = (uv_stream_t *)&hChannel->hChildWorkTCP; - } - if (!uv_is_closing((const uv_handle_t *)sendStream) && uv_is_writable(sendStream)) { - ++hChannel->sendRef; - Base::SendToStreamEx(sendStream, data, sizeNewBuf, nullptr, (void *)WriteCallback, data); - } -} - -void HdcChannelBase::AllocCallback(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) -{ - if (sizeWanted <= 0) { - return; - } - HChannel context = (HChannel)handle->data; - Base::ReallocBuf(&context->ioBuf, &context->bufSize, context->availTailIndex, sizeWanted); - buf->base = (char *)context->ioBuf + context->availTailIndex; - buf->len = context->bufSize - context->availTailIndex - 1; - if (buf->len < 0) { - buf->len = 0; - } -} - -uint32_t HdcChannelBase::MallocChannel(HChannel *hOutChannel) -{ - auto hChannel = new HdcChannel(); - if (!hChannel) { - return 0; - } - uint32_t channelId = Base::GetRuntimeMSec(); - if (isServerOrClient) { - hChannel->serverOrClient = isServerOrClient; - ++channelId; // Use different value for serverForClient&client in per process - } - uv_tcp_init(loopMain, &hChannel->hWorkTCP); - ++hChannel->uvRef; - hChannel->hWorkThread = uv_thread_self(); - hChannel->hWorkTCP.data = hChannel; - hChannel->clsChannel = this; - hChannel->channelId = channelId; - AdminChannel(OP_ADD, channelId, hChannel); - *hOutChannel = hChannel; - WRITE_LOG(LOG_DEBUG, "Mallocchannel:%d", channelId); - return channelId; -} - -// work when libuv-handle at struct of HdcSession has all callback finished -void HdcChannelBase::FreeChannelFinally(uv_idle_t *handle) -{ - HChannel hChannel = (HChannel)handle->data; - HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; - if (hChannel->uvRef > 0) { - return; - } - thisClass->NotifyInstanceChannelFree(hChannel); - thisClass->AdminChannel(OP_REMOVE, hChannel->channelId, nullptr); - WRITE_LOG(LOG_DEBUG, "!!!FreeChannelFinally channelId:%d finish", hChannel->channelId); - if (!hChannel->serverOrClient) { - uv_stop(thisClass->loopMain); - } - delete hChannel; - Base::TryCloseHandle((const uv_handle_t *)handle, Base::CloseIdleCallback); -} - -void HdcChannelBase::FreeChannelContinue(HChannel hChannel) -{ - auto closeChannelHandle = [](uv_handle_t *handle) -> void { - HChannel hChannel = (HChannel)handle->data; - --hChannel->uvRef; - Base::TryCloseHandle((uv_handle_t *)handle); - }; - hChannel->availTailIndex = 0; - if (hChannel->ioBuf) { - delete[] hChannel->ioBuf; - hChannel->ioBuf = nullptr; - } - if (!hChannel->serverOrClient) { - Base::TryCloseHandle((uv_handle_t *)&hChannel->stdinTty, closeChannelHandle); - Base::TryCloseHandle((uv_handle_t *)&hChannel->stdoutTty, closeChannelHandle); - } - if (uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP)) { - --hChannel->uvRef; - } else { - Base::TryCloseHandle((uv_handle_t *)&hChannel->hWorkTCP, closeChannelHandle); - } - Base::IdleUvTask(loopMain, hChannel, FreeChannelFinally); -} - -void HdcChannelBase::FreeChannelOpeate(uv_timer_t *handle) -{ - HChannel hChannel = (HChannel)handle->data; - HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; - if (hChannel->sendRef > 0) { - return; - } - if (hChannel->hChildWorkTCP.loop) { - auto ctrl = HdcSessionBase::BuildCtrlString(SP_DEATCH_CHANNEL, hChannel->channelId, nullptr, 0); - thisClass->ChannelSendSessionCtrlMsg(ctrl, hChannel->targetSessionId); - auto callbackCheckFreeChannelContinue = [](uv_timer_t *handle) -> void { - HChannel hChannel = (HChannel)handle->data; - HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; - if (!hChannel->childCleared) { - return; - } - Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback); - thisClass->FreeChannelContinue(hChannel); - }; - Base::TimerUvTask(thisClass->loopMain, hChannel, callbackCheckFreeChannelContinue); - } else { - thisClass->FreeChannelContinue(hChannel); - } - Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback); -} - -void HdcChannelBase::FreeChannel(const uint32_t channelId) -{ - HChannel hChannel = AdminChannel(OP_QUERY, channelId, nullptr); - if (!hChannel) { - return; - } - // Two cases: alloc in main thread, or work thread - if (hChannel->hWorkThread != uv_thread_self()) { - PushAsyncMessage(hChannel->channelId, ASYNC_FREE_SESSION, nullptr, 0); - return; - } - if (hChannel->isDead) { - return; - } - Base::TimerUvTask(loopMain, hChannel, FreeChannelOpeate, MINOR_TIMEOUT); // do immediately - hChannel->isDead = true; -} - -HChannel HdcChannelBase::AdminChannel(const uint8_t op, const uint32_t channelId, HChannel hInput) -{ - HChannel hRet = nullptr; - switch (op) { - case OP_ADD: - uv_rwlock_wrlock(&lockMapChannel); - mapChannel[channelId] = hInput; - uv_rwlock_wrunlock(&lockMapChannel); - break; - case OP_REMOVE: - uv_rwlock_wrlock(&lockMapChannel); - mapChannel.erase(channelId); - uv_rwlock_wrunlock(&lockMapChannel); - break; - case OP_QUERY: - uv_rwlock_rdlock(&lockMapChannel); - if (mapChannel.count(channelId)) { - hRet = mapChannel[channelId]; - } - uv_rwlock_rdunlock(&lockMapChannel); - break; - case OP_UPDATE: - uv_rwlock_wrlock(&lockMapChannel); - // remove old - mapChannel.erase(channelId); - mapChannel[hInput->channelId] = hInput; - uv_rwlock_wrunlock(&lockMapChannel); - break; - default: - break; - } - return hRet; -} -} \ No newline at end of file diff --git a/services/flashd/common/channel.h b/services/flashd/common/channel.h deleted file mode 100755 index 72b81813..00000000 --- a/services/flashd/common/channel.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_CHANNEL_H -#define HDC_CHANNEL_H -#include "common.h" - -namespace Hdc { -class HdcChannelBase { -public: - HdcChannelBase(const bool serverOrClient, const string &addrString, uv_loop_t *loopMainIn); - virtual ~HdcChannelBase(); - HChannel AdminChannel(const uint8_t op, const uint32_t channelId, HChannel hInput); - static void AllocCallback(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf); - static void ReadStream(uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf); - void PushAsyncMessage(const uint32_t channelId, const uint8_t method, const void *data, const int dataSize); - void WorkerPendding(); - void FreeChannel(const uint32_t channelId); - vector GetChannelHandshake(string &connectKey) const; - -protected: - struct ChannelHandShake { - char banner[12]; // must first index - union { - uint32_t channelId; - char connectKey[MAX_CONNECTKEY_SIZE]; - }; - } __attribute__((packed)); - uint32_t MallocChannel(HChannel *hOutChannel); - virtual int ReadChannel(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) - { - return 0; - } - virtual void NotifyInstanceChannelFree(HChannel hChannel) {}; - void Send(const uint32_t channelId, uint8_t *bufPtr, const int size); - virtual bool ChannelSendSessionCtrlMsg(vector &ctrlMsg, uint32_t sessionId) - { - return true; // just server use - } - - string channelHostPort; - string channelHost; - uint16_t channelPort; - uv_loop_t *loopMain; - bool isServerOrClient; - uv_rwlock_t mainAsync; - uv_async_t asyncMainLoop; - list lstMainThreadOP; - -private: - static void MainAsyncCallback(uv_async_t *handle); - static void WriteCallback(uv_write_t *req, int status); - static void AsyncMainLoopTask(uv_idle_t *handle); - static void FreeChannelOpeate(uv_timer_t *handle); - static void FreeChannelFinally(uv_idle_t *handle); - void ClearChannels(); - void FreeChannelContinue(HChannel hChannel); - bool SetChannelTCPString(const string &addrString); - - uv_rwlock_t lockMapChannel; // protect mapChannel - map mapChannel; -}; -} // namespace Hdc - -#endif // HDC_CHANNEL_H \ No newline at end of file diff --git a/services/flashd/common/common.h b/services/flashd/common/common.h deleted file mode 100755 index e90125ba..00000000 --- a/services/flashd/common/common.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_COMMON_H -#define HDC_COMMON_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using std::condition_variable; -using std::list; -using std::map; -using std::mutex; -using std::string; -using std::vector; - -// clang-format off -#include // libuv 1.35 -#ifdef HDC_HOST - -#ifdef HARMONY_PROJECT -#include -#else // NOT HARMONY_PROJECT -#include -#endif // END HARMONY_PROJECT - -#else // NOT HDC_HOST -#endif // HDC_HOST - -#ifndef _WIN32 -#include -#include -#endif - -#include - -#include "define.h" -#include "debug.h" -#include "base.h" -#include "task.h" -#include "channel.h" -#include "session.h" -#include "auth.h" - -#include "tcp.h" -#include "usb.h" -#include "file_descriptor.h" - -// clang-format on - -#endif // !defined(COMMON_H_INCLUDED) diff --git a/services/flashd/common/debug.cpp b/services/flashd/common/debug.cpp deleted file mode 100755 index 30b81c7e..00000000 --- a/services/flashd/common/debug.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "debug.h" -#include "base.h" - -namespace Hdc { -namespace Debug { - int WriteHexToDebugFile(const char *fileName, const uint8_t *buf, const int bufLen) - { - char pathName[BUF_SIZE_DEFAULT]; - if (snprintf_s(pathName, sizeof(pathName), sizeof(pathName) - 1, "/mnt/hgfs/vtmp/%s", fileName) < 0) { - return ERR_BUF_OVERFLOW; - } - string srcPath = pathName; - string resolvedPath = Base::CanonicalizeSpecPath(srcPath); - FILE *fp = fopen(resolvedPath.c_str(), "a+"); - if (fp == nullptr) { - if (snprintf_s(pathName, sizeof(pathName), sizeof(pathName) - 1, "/tmp/%s", fileName) < 0) { - WRITE_LOG(LOG_DEBUG, "Write hex to %s failed!", pathName); - return ERR_FILE_OPEN; - } - - srcPath = pathName; - resolvedPath = Base::CanonicalizeSpecPath(srcPath); - if ((fp = fopen(resolvedPath.c_str(), "a+")) == nullptr) { - WRITE_LOG(LOG_DEBUG, "Write hex to %s failed!", pathName); - return ERR_FILE_OPEN; - } - } - fwrite(buf, 1, bufLen, fp); - fflush(fp); - fclose(fp); - return RET_SUCCESS; - } - - int ReadHexFromDebugFile(const char *fileName, uint8_t *buf, const int bufLen) - { - char pathName[BUF_SIZE_DEFAULT]; - if (snprintf_s(pathName, sizeof(pathName), sizeof(pathName) - 1, "/mnt/hgfs/vtmp/%s", fileName) < 0) { - return ERR_BUF_OVERFLOW; - } - FILE *fp = fopen(pathName, "r"); - if (fp == nullptr) { - if (snprintf_s(pathName, sizeof(pathName), sizeof(pathName) - 1, "/tmp/%s", fileName) < 0 - || (fp = fopen(pathName, "r")) == nullptr) { - if (fp != nullptr) { - fclose(fp); - } - WRITE_LOG(LOG_DEBUG, "Write hex to %s failed!", pathName); - return ERR_FILE_WRITE; - } - } - struct stat statbuf; - stat(pathName, &statbuf); - int size = statbuf.st_size; - if (size > bufLen) { - fclose(fp); - return ERR_BUF_SIZE; - } - int ret = fread(buf, 1, size, fp); - fflush(fp); - fclose(fp); - if (ret != size) { - return ERR_FILE_READ; - } - return size; - } - - void DetermineThread(HSession hSession) - { - if (uv_thread_self() == hSession->hWorkThread) { - WRITE_LOG(LOG_WARN, "At main workthread"); - } else if (uv_thread_self() == hSession->hWorkChildThread) { - WRITE_LOG(LOG_WARN, "At child workthread"); - } else { - WRITE_LOG(LOG_WARN, "At unknow workthread"); - } - } - - int PrintfHexBuf(const uint8_t *buf, int bufLen) - { - int i = 0; - for (i = 0; i < bufLen; ++i) { - printf("0x%02x, ", buf[i]); - fflush(stdout); - } - printf("\r\n"); - fflush(stdout); - return 0; - } -} -} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/common/debug.h b/services/flashd/common/debug.h deleted file mode 100755 index b14d1e10..00000000 --- a/services/flashd/common/debug.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_DEBUG_H -#define HDC_DEBUG_H -#include "common.h" - -namespace Hdc { -namespace Debug { - int WriteHexToDebugFile(const char *fileName, const uint8_t *buf, const int bufLen); - int ReadHexFromDebugFile(const char *fileName, uint8_t *buf, const int bufLen); - void DetermineThread(HSession hSession); - int PrintfHexBuf(const uint8_t *buf, int bufLen); -} -} // namespace Hdc - -#endif \ No newline at end of file diff --git a/services/flashd/common/define.h b/services/flashd/common/define.h deleted file mode 100755 index 0c1ddf0d..00000000 --- a/services/flashd/common/define.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_DEFINE_H -#define HDC_DEFINE_H -#include "define_plus.h" - -namespace Hdc { -// ############################## config ####################################### -constexpr uint8_t MINOR_TIMEOUT = 5; -constexpr uint8_t SIZE_THREAD_POOL = 16; -constexpr uint8_t GLOBAL_TIMEOUT = 30; -constexpr uint16_t DEFAULT_PORT = 8710; -constexpr uint16_t MAX_SIZE_IOBUF = 5120; // USB EP block max size about 10k, USBFFS_BULKSIZE 16384 -constexpr bool ENABLE_IO_CHECKSUM = false; -const string DEFAULT_SERVER_ADDR = "127.0.0.1:8710"; - -// ################################ macro define ################################### -constexpr uint8_t DWORD_SERIALIZE_SIZE = 4; -constexpr uint8_t CMD_ARG1_COUNT = 2; -constexpr uint8_t STREAM_MAIN = 0; // work at main thread -constexpr uint8_t STREAM_WORK = 1; // work at work thread -constexpr uint16_t BUF_SIZE_MICRO = 16; -constexpr uint16_t BUF_SIZE_TINY = 64; -constexpr uint16_t BUF_SIZE_SMALL = 256; -constexpr uint16_t BUF_SIZE_MEDIUM = 512; -constexpr uint16_t BUF_SIZE_DEFAULT = 1024; -constexpr uint16_t BUF_SIZE_DEFAULT2 = BUF_SIZE_DEFAULT * 2; -constexpr uint16_t BUF_SIZE_DEFAULT4 = BUF_SIZE_DEFAULT * 4; -constexpr uint16_t MAX_IP_PORT = 65535; -constexpr uint16_t MAX_CONNECTKEY_SIZE = 32; // usb sn/tcp ipport -constexpr uint16_t TIME_BASE = 1000; // time unit conversion base value -constexpr uint16_t AID_SHELL = 2000; -constexpr uint16_t UV_DEFAULT_INTERVAL = 250; // ms -constexpr uint16_t VER_PROTOCOL = 0x01; -constexpr uint16_t EXTRA_ALLOC_SIZE = 2048; -// double-word(hex)=[0]major[1][2]minor[3][4]version[5]fix(a-p)[6][7]reserve -constexpr uint32_t HDC_VERSION_NUMBER = 0x10101800; // 1.1.1b=0x10101100 -constexpr uint32_t HDC_BUF_MAX_BYTES = 1024000000; - -const string WHITE_SPACES = " \t\n\r"; -const string UT_TMP_PATH = "/tmp/hdc-ut"; -const string LOG_FILE_NAME = "hdc.log"; -const string SERVER_NAME = "HDCServer"; -const string STRING_EMPTY = ""; -const string HANDSHAKE_MESSAGE = "OHOS HDC"; // sep not char '-', not more than 11 bytes -const string PACKET_FLAG = "HW"; // must 2bytes -const string EMPTY_ECHO = "[Empty]"; -const string MESSAGE_INFO = "[Info]"; -const string MESSAGE_FAIL = "[Fail]"; -const string MESSAGE_SUCCESS = "[Success]"; -// input command -const string CMDSTR_SOFTWARE_VERSION = "version"; -const string CMDSTR_SOFTWARE_HELP = "help"; -const string CMDSTR_TARGET_DISCOVER = "discover"; -const string CMDSTR_SERVICE_START = "start"; -const string CMDSTR_SERVICE_KILL = "kill"; -const string CMDSTR_GENERATE_KEY = "keygen"; -const string CMDSTR_KILL_SERVER = "kserver"; -const string CMDSTR_KILL_DAEMON = "kdaemon"; -const string CMDSTR_LIST_TARGETS = "list targets"; -const string CMDSTR_CONNECT_TARGET = "tconn"; -const string CMDSTR_CONNECT_ANY = "any"; -const string CMDSTR_SHELL = "shell"; -const string CMDSTR_TARGET_REBOOT = "target boot"; -const string CMDSTR_TARGET_MOUNT = "target mount"; -const string CMDSTR_STARTUP_MODE = "smode"; -const string CMDSTR_TARGET_MODE = "tmode"; -const string CMDSTR_BUGREPORT = "bugreport"; -const string CMDSTR_HILOG = "hilog"; -const string CMDSTR_TMODE_USB = "usb"; -const string CMDSTR_TMODE_TCP = "tcp"; -const string CMDSTR_FILE_SEND = "file send"; -const string CMDSTR_FILE_RECV = "file recv"; -const string CMDSTR_FORWARD_FPORT = "fport"; -const string CMDSTR_FORWARD_RPORT = "rport"; -const string CMDSTR_APP_INSTALL = "install"; -const string CMDSTR_APP_UNINSTALL = "uninstall"; -const string CMDSTR_APP_SIDELOAD = "sideload"; -const string CMDSTR_LIST_JDWP = "jpid"; -const string CMDSTR_UPDATE_SYSTEM = "update"; -const string CMDSTR_FLASH_PARTITION = "flash"; -const string CMDSTR_ERASE_PARTITION = "erase"; -const string CMDSTR_FORMAT_PARTITION = "format"; -const string CMDSTR_INNER_ENABLE_KEEPALIVE = "alive"; -} // namespace Hdc -#endif // HDC_DEFINE_H diff --git a/services/flashd/common/define_plus.h b/services/flashd/common/define_plus.h deleted file mode 100755 index 0e4c22b7..00000000 --- a/services/flashd/common/define_plus.h +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef DEFINE_PLUS_H -#define DEFINE_PLUS_H - -namespace Hdc { -constexpr uint8_t LOG_LEVEL_FULL = 5; -// ############################# enum define ################################### -enum LogLevel { - LOG_OFF, - LOG_FATAL, - LOG_INFO, // default - LOG_WARN, - LOG_DEBUG, - LOG_FULL, - LOG_LAST = LOG_FULL, // tail, not use -}; -#define WRITE_LOG(x, y...) Base::PrintLogEx(__FILE__, __LINE__, x, y) - -enum MessageLevel { - MSG_FAIL, - MSG_INFO, - MSG_OK, -}; - -enum ConnType { CONN_USB = 0, CONN_TCP, CONN_SERIAL, CONN_BT }; -enum ConnStatus { STATUS_UNKNOW = 0, STATUS_READY, STATUS_CONNECTED, STATUS_OFFLINE }; - -enum OperateID { - OP_ADD, - OP_REMOVE, - OP_QUERY, - OP_GET_STRLIST, - OP_GET_STRLIST_FULL, - OP_GET_ANY, - OP_UPDATE, - OP_CLEAR, - OP_INIT, - OP_GET_ONLY -}; - -enum RetErrCode { - RET_SUCCESS = 0, - ERR_GENERIC = -1, - ERR_BUF_SIZE = -10000, - ERR_BUF_ALLOC, - ERR_BUF_OVERFLOW, - ERR_BUF_CHECK, - ERR_BUF_RESET, - ERR_BUF_COPY, - ERR_FILE_OPEN = -11000, - ERR_FILE_READ, - ERR_FILE_WRITE, - ERR_FILE_STAT, - ERR_FILE_PATH_CHECK, - ERR_PARM_FORMAT = -12000, - ERR_PARM_SIZE, - ERR_PARM_FAIL, - ERR_API_FAIL = -13000, - ERR_IO_FAIL = -14000, - ERR_IO_TIMEOUT, - ERR_IO_SOFT_RESET, - ERR_SESSION_NOFOUND = -15000, - ERR_SESSION_OFFLINE, - ERR_SESSION_DEAD, - ERR_HANDSHAKE_NOTMATCH = -16000, - ERR_HANDSHAKE_CONNECTKEY_FAILED, - ERR_HANDSHAKE_HANGUP_CHILD, - ERR_SOCKET_FAIL = -17000, - ERR_SOCKET_DUPLICATE, - ERR_MODULE_JDWP_FAILED = -18000, - ERR_UT_MODULE_NOTREADY = -19000, - ERR_UT_MODULE_WAITMAX, - ERR_THREAD_MUTEX_FAIL = -20000, - ERR_PROCESS_SUB_FAIL = -21000, - ERR_PRIVELEGE_NEED = -22000, -}; - -// Flags shared by multiple modules -enum AsyncEvent { - ASYNC_STOP_MAINLOOP = 0, - ASYNC_FREE_SESSION, -}; -enum InnerCtrlCommand { - SP_START_SESSION = 0, - SP_STOP_SESSION, - SP_ATTACH_CHANNEL, - SP_DEATCH_CHANNEL, - SP_JDWP_NEWFD, -}; - -enum HdcCommand { - // core commands types - CMD_KERNEL_HELP = 0, - CMD_KERNEL_HANDSHAKE, - CMD_KERNEL_CHANNEL_CLOSE, - CMD_KERNEL_SERVER_KILL, - CMD_KERNEL_TARGET_DISCOVER, - CMD_KERNEL_TARGET_LIST, - CMD_KERNEL_TARGET_ANY, - CMD_KERNEL_TARGET_CONNECT, - CMD_KERNEL_TARGET_DISCONNECT, - CMD_KERNEL_ECHO, - CMD_KERNEL_ECHO_RAW, - CMD_KERNEL_ENABLE_KEEPALIVE, - // One-pass simple commands - CMD_UNITY_EXECUTE = 1000, - CMD_UNITY_REMOUNT, - CMD_UNITY_REBOOT, - CMD_UNITY_RUNMODE, - CMD_UNITY_HILOG, - CMD_UNITY_TERMINATE, - CMD_UNITY_ROOTRUN, - CMD_UNITY_BUGREPORT_INIT, - CMD_UNITY_BUGREPORT_DATA, - CMD_UNITY_JPID, - // Shell commands types - CMD_SHELL_INIT = 2000, - CMD_SHELL_DATA, - // Forward commands types - CMD_FORWARD_INIT = 2500, - CMD_FORWARD_CHECK, - CMD_FORWARD_CHECK_RESULT, - CMD_FORWARD_ACTIVE_SLAVE, - CMD_FORWARD_ACTIVE_MASTER, - CMD_FORWARD_DATA, - CMD_FORWARD_FREE_CONTEXT, - CMD_FORWARD_LIST, - CMD_FORWARD_REMOVE, - CMD_FORWARD_SUCCESS, - // File commands - CMD_FILE_INIT = 3000, - CMD_FILE_CHECK, - CMD_FILE_BEGIN, - CMD_FILE_DATA, - CMD_FILE_FINISH, - CMD_APP_SIDELOAD, - // App commands - CMD_APP_INIT = 3500, - CMD_APP_CHECK, - CMD_APP_BEGIN, - CMD_APP_DATA, - CMD_APP_FINISH, - CMD_APP_UNINSTALL, - // update - CMD_UPDATER_UPDATE_INIT = 4000, - CMD_UPDATER_FLASH_INIT, - CMD_UPDATER_CHECK, - CMD_UPDATER_BEGIN, - CMD_UPDATER_DATA, - CMD_UPDATER_FINISH = 4005, - CMD_UPDATER_ERASE, - CMD_UPDATER_FORMAT, - CMD_UPDATER_PROGRESS -}; - -enum UsbProtocolOption { - USB_OPTION_TAIL = 1, - USB_OPTION_RESET = 2, - USB_OPTION_RESERVE4 = 4, - USB_OPTION_RESERVE8 = 8, - USB_OPTION_RESERVE16 = 16, -}; -// ################################### struct define ################################### -#pragma pack(push) -#pragma pack(1) - -struct USBHead { - uint8_t flag[2]; - uint8_t option; - uint32_t sessionId; - uint16_t dataSize; -}; - -struct AsyncParam { - void *context; // context=hsession or hchannel - uint32_t sid; // sessionId/channelId - void *thisClass; // caller's class ptr - uint16_t method; - int dataSize; - void *data; // put it in the last -}; - -struct TaskInformation { - uint8_t taskType; - uint32_t sessionId; - uint32_t channelId; - bool hasInitial; - bool taskStop; - bool taskFree; - bool serverOrDaemon; - uv_loop_t *runLoop; - void *taskClass; - void *ownerSessionClass; -}; -using HTaskInfo = TaskInformation *; - -#pragma pack(pop) - -struct HdcUSB { -#ifdef HDC_HOST - libusb_context *ctxUSB = nullptr; // child-use, main null - libusb_device *device; - libusb_device_handle *devHandle; - uint8_t interfaceNumber; - uint16_t retryCount; - // D2H device to host endpoint's address - uint8_t epDevice; - // H2D host to device endpoint's address - uint8_t epHost; - uint8_t devId; - uint8_t busId; - int32_t sizeEpBuf; - uint16_t wMaxPacketSize; - string serialNumber; - string usbMountPoint; - uint8_t *bufDevice; - uint8_t *bufHost; - - mutex lockDeviceHandle; - libusb_transfer *transferRecv; - bool recvIOComplete; - - mutex lockSend; - condition_variable cvTransferSend; - libusb_transfer *transferSend; - bool sendIOComplete; -#else - // usb accessory FunctionFS - // USB main thread use, sub-thread disable, sub-thread uses the main thread USB handle - int bulkOut; // EP1 device recv - int bulkIn; // EP2 device send -#endif - vector bufRecv; - bool resetIO; // if true, must break write and read,default false -}; -using HUSB = struct HdcUSB *; - -struct HdcSession { - bool serverOrDaemon; // instance of daemon or server - bool handshakeOK; // Is an expected peer side - bool isDead; - string connectKey; - uint8_t connType; // ConnType - uint32_t sessionId; - std::atomic sendRef; - uint8_t uvRef; // libuv handle ref -- just main thread now - uint8_t uvChildRef; // libuv handle ref -- just main thread now - bool childCleared; - map *mapTask; - // class ptr - void *classInstance; // HdcSessionBase instance, HdcServer or HdcDaemon - void *classModule; // Communicate module, TCP or USB instance,HdcDaemonUSB HdcDaemonTCP etc... - // io cache - int bufSize; // total buffer size - int availTailIndex; // buffer available data size - uint8_t *ioBuf; - // auth - list *listKey; // rsa private or publickey list - uint8_t authKeyIndex; - string tokenRSA; // SHA_DIGEST_LENGTH+1==21 - // child work - uv_loop_t childLoop; // run in work thread - // pipe0 in main thread(hdc server mainloop), pipe1 in work thread - uv_tcp_t ctrlPipe[2]; // control channel - int ctrlFd[2]; // control channel socketpair - // data channel(TCP with socket, USB with thread forward) - uv_tcp_t dataPipe[2]; - int dataFd[2]; // data channel socketpair - uv_tcp_t hChildWorkTCP; // work channel,separate thread for server/daemon - uv_os_sock_t fdChildWorkTCP; - // usb handle - HUSB hUSB; - // tcp handle - uv_tcp_t hWorkTCP; - uv_thread_t hWorkThread; - uv_thread_t hWorkChildThread; -}; -using HSession = struct HdcSession *; - -struct HdcChannel { - void *clsChannel; // ptr Class of serverForClient or client - uint32_t channelId; - string connectKey; - uv_tcp_t hWorkTCP; // work channel for client, forward channel for server - uv_thread_t hWorkThread; - uint8_t uvRef = 0; // libuv handle ref -- just main thread now - bool handshakeOK; - bool isDead; - bool serverOrClient; // client's channel/ server's channel - bool childCleared; - bool interactiveShellMode; // Is shell interactive mode - bool keepAlive; // channel will not auto-close by server - std::atomic sendRef; - uint32_t targetSessionId; - // child work - uv_tcp_t hChildWorkTCP; // work channel for server, no use in client - uv_os_sock_t fdChildWorkTCP; - // read io cache - int bufSize; // total buffer size - int availTailIndex; // buffer available data size - uint8_t *ioBuf; - // std - uv_tty_t stdinTty; - uv_tty_t stdoutTty; - char bufStd[128]; -}; -using HChannel = struct HdcChannel *; - -struct HdcDaemonInformation { - uint8_t connType; - uint8_t connStatus; - string connectKey; - string usbMountPoint; - string devName; - HSession hSession; -}; -using HDaemonInfo = struct HdcDaemonInformation *; - -struct HdcForwardInformation { - string taskString; - bool forwardDirection; // true for forward, false is reverse; - uint32_t sessionId; - uint32_t channelId; -}; -using HForwardInfo = struct HdcForwardInformation *; -} -#endif \ No newline at end of file diff --git a/services/flashd/common/file.cpp b/services/flashd/common/file.cpp deleted file mode 100755 index 4e3cd905..00000000 --- a/services/flashd/common/file.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "file.h" -#include "serial_struct.h" - -namespace Hdc { -HdcFile::HdcFile(HTaskInfo hTaskInfo) - : HdcTransferBase(hTaskInfo) -{ - commandBegin = CMD_FILE_BEGIN; - commandData = CMD_FILE_DATA; -} - -HdcFile::~HdcFile() -{ - WRITE_LOG(LOG_DEBUG, "~HdcFile"); -}; - -void HdcFile::StopTask() -{ - WRITE_LOG(LOG_DEBUG, "HdcFile StopTask"); - singalStop = true; -}; - -bool HdcFile::BeginTransfer(CtxFile *context, const string &command) -{ - int argc = 0; - bool ret = false; - char **argv = Base::SplitCommandToArgs(command.c_str(), &argc); - if (argc < CMD_ARG1_COUNT || argv == nullptr) { - LogMsg(MSG_FAIL, "Transfer path split failed"); - if (argv) { - delete[]((char *)argv); - } - return false; - } - if (!SetMasterParameters(context, command.c_str(), argc, argv)) { - delete[]((char *)argv); - return false; - } - do { - ++refCount; - uv_fs_open(loopTask, &context->fsOpenReq, context->localPath.c_str(), O_RDONLY, S_IWUSR | S_IRUSR, OnFileOpen); - context->master = true; - ret = true; - } while (false); - if (!ret) { - LogMsg(MSG_FAIL, "Transfer path failed, Master:%s Slave:%s", context->localPath.c_str(), - context->remotePath.c_str()); - } - delete[]((char *)argv); - return ret; -} - -bool HdcFile::SetMasterParameters(CtxFile *context, const char *command, int argc, char **argv) -{ - int srcArgvIndex = 0; - const string CMD_OPTION_TSTMP = "-a"; - const string CMD_OPTION_SYNC = "-sync"; - const string CMD_OPTION_ZIP = "-z"; - - for (int i = 0; i < argc - CMD_ARG1_COUNT; i++) { - if (argv[i] == CMD_OPTION_ZIP) { - context->transferConfig.compressType = COMPRESS_LZ4; - ++srcArgvIndex; - } else if (argv[i] == CMD_OPTION_SYNC) { - context->transferConfig.updateIfNew = true; - ++srcArgvIndex; - } else if (argv[i] == CMD_OPTION_TSTMP) { - // The time zone difference may cause the display time on the PC and the - // device to differ by several hours - // - // ls -al --full-time - context->transferConfig.holdTimestamp = true; - ++srcArgvIndex; - } else if (argv[i] == CMD_OPTION_CLIENTCWD) { - context->transferConfig.clientCwd = argv[i + 1]; - srcArgvIndex += CMD_ARG1_COUNT; // skip 2args - } else if (argv[i][0] == '-') { - LogMsg(MSG_FAIL, "Unknow file option: %s", argv[i]); - return false; - } - } - context->remotePath = argv[argc - 1]; - context->localPath = argv[argc - 2]; - if (taskInfo->serverOrDaemon) { - // master and server - ExtractRelativePath(context->transferConfig.clientCwd, context->localPath); - } - if (!Base::CheckDirectoryOrPath(context->localPath.c_str(), true, true)) { - LogMsg(MSG_FAIL, "Src not exist, path: %s", context->localPath.c_str()); - return false; - } - context->localName = Base::GetFullFilePath(context->localPath); - return true; -} - -void HdcFile::CheckMaster(CtxFile *context) -{ - string s = SerialStruct::SerializeToString(context->transferConfig); - SendToAnother(CMD_FILE_CHECK, (uint8_t *)s.c_str(), s.size()); -} - -void HdcFile::WhenTransferFinish(CtxFile *context) -{ - WRITE_LOG(LOG_DEBUG, "HdcTransferBase OnFileClose"); - uint8_t flag = 1; - SendToAnother(CMD_FILE_FINISH, &flag, 1); -} - -void HdcFile::TransferSummary(CtxFile *context) -{ - uint64_t nMSec = Base::GetRuntimeMSec() - context->transferBegin; - double fRate = static_cast(context->indexIO) / nMSec; // / /1000 * 1000 = 0 - LogMsg(MSG_OK, "FileTransfer finish, Size:%lld time:%lldms rate:%.2lfkB/s", context->indexIO, nMSec, fRate); -} - -bool HdcFile::SlaveCheck(uint8_t *payload, const int payloadSize) -{ - bool ret = true; - bool childRet = false; - // parse option - string serialStrring((char *)payload, payloadSize); - TransferConfig &stat = ctxNow.transferConfig; - SerialStruct::ParseFromString(stat, serialStrring); - ctxNow.fileSize = stat.fileSize; - ctxNow.localPath = stat.path; - ctxNow.master = false; - ctxNow.fsOpenReq.data = &ctxNow; - // check path - childRet = SmartSlavePath(stat.clientCwd, ctxNow.localPath, stat.optionalName.c_str()); - if (childRet && ctxNow.transferConfig.updateIfNew) { // file exist and option need update - // if is newer - uv_fs_t fs; - Base::ZeroStruct(fs.statbuf); - uv_fs_stat(nullptr, &fs, ctxNow.localPath.c_str(), nullptr); - uv_fs_req_cleanup(&fs); - if ((uint64_t)fs.statbuf.st_mtim.tv_sec >= ctxNow.transferConfig.mtime) { - LogMsg(MSG_FAIL, "Target file is the same date or newer,path: %s", ctxNow.localPath.c_str()); - return false; - } - } - // begin work - ++refCount; - uv_fs_open(loopTask, &ctxNow.fsOpenReq, ctxNow.localPath.c_str(), UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, - S_IWUSR | S_IRUSR, OnFileOpen); - ctxNow.transferBegin = Base::GetRuntimeMSec(); - return ret; -} - -bool HdcFile::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) -{ - HdcTransferBase::CommandDispatch(command, payload, payloadSize); - bool ret = true; - switch (command) { - case CMD_FILE_INIT: { // initial - string s = string((char *)payload, payloadSize); - ret = BeginTransfer(&ctxNow, s); - ctxNow.transferBegin = Base::GetRuntimeMSec(); - break; - } - case CMD_FILE_CHECK: { - ret = SlaveCheck(payload, payloadSize); - break; - } - case CMD_FILE_FINISH: { - if (*payload) { // close-step3 - --(*payload); - SendToAnother(CMD_FILE_FINISH, payload, 1); - ++refCount; - uv_fs_close(loopTask, &ctxNow.fsCloseReq, ctxNow.fsOpenReq.result, OnFileClose); - } else { // close-step3 - TransferSummary(&ctxNow); - TaskFinish(); - } - break; - } - default: - break; - } - return ret; -} -} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/common/file_descriptor.cpp b/services/flashd/common/file_descriptor.cpp deleted file mode 100755 index 61886062..00000000 --- a/services/flashd/common/file_descriptor.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "file_descriptor.h" - -namespace Hdc { -HdcFileDescriptor::HdcFileDescriptor(uv_loop_t *loopIn, int fdToRead, void *callerContextIn, - CallBackWhenRead callbackReadIn, CmdResultCallback callbackFinishIn) -{ - loop = loopIn; - workContinue = true; - callbackFinish = callbackFinishIn; - callbackRead = callbackReadIn; - fdIO = fdToRead; - refIO = 0; - callerContext = callerContextIn; -} - -HdcFileDescriptor::~HdcFileDescriptor() -{ - if (refIO > 0) { - WRITE_LOG(LOG_FATAL, "~HdcFileDescriptor refIO > 0"); - } -} - -bool HdcFileDescriptor::ReadyForRelease() -{ - return refIO == 0; -} - -// just tryCloseFdIo = true, callback will be effect -void HdcFileDescriptor::StopWork(bool tryCloseFdIo, std::function closeFdCallback) -{ - workContinue = false; - callbackCloseFd = closeFdCallback; - if (tryCloseFdIo && refIO > 0) { - ++refIO; - reqClose.data = this; - uv_fs_close(loop, &reqClose, fdIO, [](uv_fs_t *req) { - auto thisClass = (HdcFileDescriptor *)req->data; - uv_fs_req_cleanup(req); - if (thisClass->callbackCloseFd != nullptr) { - thisClass->callbackCloseFd(); - } - --thisClass->refIO; - }); - } -}; - -void HdcFileDescriptor::OnFileIO(uv_fs_t *req) -{ - CtxFileIO *ctxIO = static_cast(req->data); - HdcFileDescriptor *thisClass = ctxIO->thisClass; - uint8_t *buf = ctxIO->bufIO; - bool bFinish = false; - bool fetalFinish = false; - - do { - if (req->result > 0) { - if (req->fs_type == UV_FS_READ) { - if (!thisClass->callbackRead(thisClass->callerContext, buf, req->result)) { - bFinish = true; - break; - } - thisClass->LoopRead(); - } else { - // fs_write - } - } else { - WRITE_LOG(LOG_DEBUG, "OnFileIO fd:%d failed:%s", thisClass->fdIO, uv_strerror(req->result)); - bFinish = true; - fetalFinish = true; - break; - } - } while (false); - uv_fs_req_cleanup(req); - delete[] buf; - delete ctxIO; - - --thisClass->refIO; - if (bFinish) { - thisClass->callbackFinish(thisClass->callerContext, fetalFinish, "OnRead finish"); - thisClass->workContinue = false; - } -} - -int HdcFileDescriptor::LoopRead() -{ - uv_buf_t iov; - int readMax = Base::GetMaxBufSize() * 1.2; - auto contextIO = new CtxFileIO(); - auto buf = new uint8_t[readMax](); - if (!contextIO || !buf) { - if (contextIO) { - delete contextIO; - } - if (buf) { - delete[] buf; - } - WRITE_LOG(LOG_FATAL, "Memory alloc failed"); - callbackFinish(callerContext, true, "Memory alloc failed"); - return -1; - } - uv_fs_t *req = &contextIO->fs; - contextIO->bufIO = buf; - contextIO->thisClass = this; - req->data = contextIO; - ++refIO; - iov = uv_buf_init((char *)buf, readMax); - uv_fs_read(loop, req, fdIO, &iov, 1, -1, OnFileIO); - return 0; -} - -bool HdcFileDescriptor::StartWork() -{ - if (LoopRead() < 0) { - return false; - } - return true; -} - -int HdcFileDescriptor::Write(uint8_t *data, int size) -{ - if (size > static_cast(HDC_BUF_MAX_BYTES)) { - size = static_cast(HDC_BUF_MAX_BYTES); - } - auto buf = new uint8_t[size]; - if (!buf) { - return -1; - } - memcpy_s(buf, size, data, size); - return WriteWithMem(buf, size); -} - -// Data's memory must be Malloc, and the callback FREE after this function is completed -int HdcFileDescriptor::WriteWithMem(uint8_t *data, int size) -{ - auto contextIO = new CtxFileIO(); - if (!contextIO) { - delete[] data; - WRITE_LOG(LOG_FATAL, "Memory alloc failed"); - callbackFinish(callerContext, true, "Memory alloc failed"); - return -1; - } - uv_fs_t *req = &contextIO->fs; - contextIO->bufIO = data; - contextIO->thisClass = this; - req->data = contextIO; - ++refIO; - - uv_buf_t iov = uv_buf_init((char *)data, size); - uv_fs_write(loop, req, fdIO, &iov, 1, -1, OnFileIO); - return size; -} -} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/common/file_descriptor.h b/services/flashd/common/file_descriptor.h deleted file mode 100755 index 40311e71..00000000 --- a/services/flashd/common/file_descriptor.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_FILE_DESCRIPTOR_H -#define HDC_FILE_DESCRIPTOR_H -#include "common.h" - -namespace Hdc { -class HdcFileDescriptor { -public: - // callerContext, normalFinish, errorString - using CmdResultCallback = std::function; - // callerContext, readBuf, readIOByes - using CallBackWhenRead = std::function; - HdcFileDescriptor(uv_loop_t *loopIn, int fdToRead, void *callerContextIn, CallBackWhenRead callbackReadIn, - CmdResultCallback callbackFinishIn); - virtual ~HdcFileDescriptor(); - int Write(uint8_t *data, int size); - int WriteWithMem(uint8_t *data, int size); - - bool ReadyForRelease(); - bool StartWork(); - void StopWork(bool tryCloseFdIo, std::function closeFdCallback); - -protected: -private: - struct CtxFileIO { - uv_fs_t fs; - uint8_t *bufIO; - HdcFileDescriptor *thisClass; - }; - static void OnFileIO(uv_fs_t *req); - int LoopRead(); - - std::function callbackCloseFd; - CmdResultCallback callbackFinish; - CallBackWhenRead callbackRead; - uv_loop_t *loop; - uv_fs_t reqClose; - void *callerContext; - bool workContinue; - int fdIO; - int refIO; -}; -} // namespace Hdc - -#endif // HDC_FILE_DESCRIPTOR_H \ No newline at end of file diff --git a/services/flashd/common/file.h b/services/flashd/common/flash_define.h similarity index 43% rename from services/flashd/common/file.h rename to services/flashd/common/flash_define.h index 230d3f50..20361a07 100755 --- a/services/flashd/common/file.h +++ b/services/flashd/common/flash_define.h @@ -12,28 +12,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef HDC_FILE_TRANSFER_H -#define HDC_FILE_TRANSFER_H +#ifndef UPDATER_HDC_DEFINE_H +#define UPDATER_HDC_DEFINE_H #include "common.h" -#include "transfer.h" namespace Hdc { -class HdcFile : public HdcTransferBase { -public: - HdcFile(HTaskInfo hTaskInfo); - virtual ~HdcFile(); - void StopTask(); - bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); +const string CMDSTR_UPDATE_SYSTEM = "update"; +const string CMDSTR_FLASH_PARTITION = "flash"; +const string CMDSTR_ERASE_PARTITION = "erase"; +const string CMDSTR_FORMAT_PARTITION = "format"; -protected: -private: - bool SlaveCheck(uint8_t *payload, const int payloadSize); - void CheckMaster(CtxFile *context); - void WhenTransferFinish(CtxFile *context); - bool BeginTransfer(CtxFile *context, const string &command); - void TransferSummary(CtxFile *context); - bool SetMasterParameters(CtxFile *context, const char *command, int argc, char **argv); -}; -} // namespace Hdc +// update +const int CMD_UPDATER_UPDATE_INIT = CMD_APP_INIT + 200; +const int CMD_UPDATER_FLASH_INIT = CMD_UPDATER_UPDATE_INIT + 1; +const int CMD_UPDATER_CHECK = CMD_UPDATER_UPDATE_INIT + 2; +const int CMD_UPDATER_BEGIN = CMD_UPDATER_UPDATE_INIT + 3; +const int CMD_UPDATER_DATA = CMD_UPDATER_UPDATE_INIT + 4; +const int CMD_UPDATER_FINISH = CMD_UPDATER_UPDATE_INIT + 5; +const int CMD_UPDATER_ERASE = CMD_UPDATER_UPDATE_INIT + 6; +const int CMD_UPDATER_FORMAT = CMD_UPDATER_UPDATE_INIT + 7; +const int CMD_UPDATER_PROGRESS = CMD_UPDATER_UPDATE_INIT + 8; -#endif \ No newline at end of file +const int TASK_UPDATER = TASK_APP + 1; +} // namespace Hdc +#endif // UPDATER_HDC_DEFINE_H diff --git a/services/flashd/common/forward.cpp b/services/flashd/common/forward.cpp deleted file mode 100755 index b096cbb9..00000000 --- a/services/flashd/common/forward.cpp +++ /dev/null @@ -1,789 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "forward.h" -#include "base.h" - -namespace Hdc { -HdcForwardBase::HdcForwardBase(HTaskInfo hTaskInfo) - : HdcTaskBase(hTaskInfo) -{ -} - -HdcForwardBase::~HdcForwardBase() -{ - WRITE_LOG(LOG_DEBUG, "~HdcForwardBase"); -}; - -bool HdcForwardBase::ReadyForRelease() -{ - if (!HdcTaskBase::ReadyForRelease()) { - return false; - } - return true; -} - -void HdcForwardBase::StopTask() -{ - map::iterator iter; - for (iter = mapCtxPoint.begin(); iter != mapCtxPoint.end(); ++iter) { - HCtxForward ctx = iter->second; - FreeContext(ctx, 0, false); - } - // FREECONTEXT in the STOP is triggered by the other party sector, no longer notifying each other. - mapCtxPoint.clear(); -}; - -void HdcForwardBase::OnAccept(uv_stream_t *server, HCtxForward ctxClient, uv_stream_t *client) -{ - HCtxForward ctxListen = (HCtxForward)server->data; - char buf[BUF_SIZE_DEFAULT] = { 0 }; - bool ret = false; - while (true) { - if (uv_accept(server, client)) { - break; - } - ctxClient->type = ctxListen->type; - ctxClient->remoteParamenters = ctxListen->remoteParamenters; - int maxSize = sizeof(buf) - FORWARD_PARAMENTER_BUFSIZE; - // clang-format off - if (snprintf_s(buf + FORWARD_PARAMENTER_BUFSIZE, maxSize, maxSize - 1, "%s", - ctxClient->remoteParamenters.c_str()) < 0) { - break; - } - // clang-format on - // pre 8bytes preserve for param bits - SendToTask(ctxClient->id, CMD_FORWARD_ACTIVE_SLAVE, (uint8_t *)buf, - strlen(buf + FORWARD_PARAMENTER_BUFSIZE) + 9); - ret = true; - break; - } - if (!ret) { - FreeContext(ctxClient, 0, false); - } -} - -void HdcForwardBase::ListenCallback(uv_stream_t *server, const int status) -{ - HCtxForward ctxListen = (HCtxForward)server->data; - HdcForwardBase *thisClass = ctxListen->thisClass; - uv_stream_t *client = nullptr; - - if (status == -1 || !ctxListen->ready) { - thisClass->FreeContext(ctxListen, 0, false); - thisClass->TaskFinish(); - return; - } - HCtxForward ctxClient = (HCtxForward)thisClass->MallocContext(true); - if (!ctxClient) { - return; - } - if (FORWARD_TCP == ctxListen->type) { - uv_tcp_init(ctxClient->thisClass->loopTask, &ctxClient->tcp); - client = (uv_stream_t *)&ctxClient->tcp; - } else { - // FORWARD_ABSTRACT, FORWARD_RESERVED, FORWARD_FILESYSTEM, - uv_pipe_init(ctxClient->thisClass->loopTask, &ctxClient->pipe, 0); - client = (uv_stream_t *)&ctxClient->pipe; - } - thisClass->OnAccept(server, ctxClient, client); -} - -void *HdcForwardBase::MallocContext(bool masterSlave) -{ - HCtxForward ctx = nullptr; - if ((ctx = new ContextForward()) == nullptr) { - return nullptr; - } - ctx->id = Base::GetRuntimeMSec(); - ctx->masterSlave = masterSlave; - ctx->thisClass = this; - ctx->fdClass = nullptr; - ctx->tcp.data = ctx; - ctx->pipe.data = ctx; - AdminContext(OP_ADD, ctx->id, ctx); - refCount++; - return ctx; -} - -void HdcForwardBase::FreeContextCallBack(HCtxForward ctx) -{ - AdminContext(OP_REMOVE, ctx->id, nullptr); - Base::DoNextLoop(loopTask, ctx, [](const uint8_t flag, string &msg, const void *data) { - HCtxForward ctx = (HCtxForward)data; - delete ctx; - }); - --refCount; -} - -void HdcForwardBase::FreeJDWP(HCtxForward ctx) -{ - if (ctx->fd > 0) { - close(ctx->fd); - } - if (ctx->fdClass) { - ctx->fdClass->StopWork(false, nullptr); - - auto funcReqClose = [](uv_idle_t *handle) -> void { - uv_close_cb funcIdleHandleClose = [](uv_handle_t *handle) -> void { - HCtxForward ctx = (HCtxForward)handle->data; - ctx->thisClass->FreeContextCallBack(ctx); - delete (uv_idle_t *)handle; - }; - HCtxForward ctx = (HCtxForward)handle->data; - if (ctx->fdClass->ReadyForRelease()) { - delete ctx->fdClass; - ctx->fdClass = nullptr; - Base::TryCloseHandle((uv_handle_t *)handle, funcIdleHandleClose); - } - }; - Base::IdleUvTask(loopTask, ctx, funcReqClose); - } -} - -void HdcForwardBase::FreeContext(HCtxForward ctxIn, const uint32_t id, bool bNotifyRemote) -{ - WRITE_LOG(LOG_DEBUG, "FreeContext bNotifyRemote:%d %p", bNotifyRemote, ctxIn); - HCtxForward ctx = nullptr; - if (!ctxIn) { - if (!(ctx = (HCtxForward)AdminContext(OP_QUERY, id, nullptr))) { - WRITE_LOG(LOG_DEBUG, "Query id failed"); - return; - } - } else { - ctx = ctxIn; - } - if (ctx->finish) { - return; - } - if (bNotifyRemote) { - SendToTask(ctx->id, CMD_FORWARD_FREE_CONTEXT, nullptr, 0); - } - uv_close_cb funcHandleClose = [](uv_handle_t *handle) -> void { - HCtxForward ctx = (HCtxForward)handle->data; - ctx->thisClass->FreeContextCallBack(ctx); - }; - switch (ctx->type) { - case FORWARD_TCP: - case FORWARD_JDWP: - Base::TryCloseHandle((uv_handle_t *)&ctx->tcp, true, funcHandleClose); - break; - case FORWARD_ABSTRACT: - case FORWARD_RESERVED: - case FORWARD_FILESYSTEM: - Base::TryCloseHandle((uv_handle_t *)&ctx->pipe, true, funcHandleClose); - break; - case FORWARD_DEVICE: { - FreeJDWP(ctx); - break; - } - default: - break; - } - ctx->finish = true; -} - -bool HdcForwardBase::SendToTask(const uint32_t cid, const uint16_t command, uint8_t *bufPtr, const int bufSize) -{ - bool ret = false; - // usually MAX_SIZE_IOBUF*2 from HdcFileDescriptor maxIO - if (bufSize > Base::GetMaxBufSize() * 2) { - return false; - } - auto newBuf = new uint8_t[bufSize + 4]; - if (!newBuf) { - return false; - } - *(uint32_t *)(newBuf) = htonl(cid); - if (bufSize > 0 && bufPtr != nullptr && memcpy_s(newBuf + 4, bufSize, bufPtr, bufSize) != EOK) { - delete[] newBuf; - return false; - } - ret = SendToAnother(command, newBuf, bufSize + 4); - delete[] newBuf; - return ret; -} - -// Forward flow is small and frequency is fast -void HdcForwardBase::AllocForwardBuf(uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf) -{ - const uint16_t size = 1492 - 256; // For layer 3, the default MTU is 1492 bytes. reserve hdc header 256 bytes - buf->base = (char *)new char[size]; - if (buf->base) { - buf->len = size - 1; - } else { - WRITE_LOG(LOG_WARN, "AllocForwardBuf == null"); - } -} - -void HdcForwardBase::ReadForwardBuf(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) -{ - HCtxForward ctx = (HCtxForward)stream->data; - if (nread < 0) { - ctx->thisClass->FreeContext(ctx, 0, true); - return; - } - ctx->thisClass->SendToTask(ctx->id, CMD_FORWARD_DATA, (uint8_t *)buf->base, nread); - // clear - delete[] buf->base; -} - -void HdcForwardBase::ConnectTarget(uv_connect_t *connection, int status) -{ - HCtxForward ctx = (HCtxForward)connection->data; - HdcForwardBase *thisClass = ctx->thisClass; - delete connection; - if (status < 0) { - WRITE_LOG(LOG_WARN, "Forward connect result:%d error:%s", status, uv_err_name(status)); - } - thisClass->SetupPointContinue(ctx, status); -} - -bool HdcForwardBase::CheckNodeInfo(const char *nodeInfo, string as[2]) -{ - char bufString[BUF_SIZE_MEDIUM]; - if (!strchr(nodeInfo, ':')) { - return false; - } - if (EOK != strcpy_s(bufString, sizeof(bufString), nodeInfo)) { - return false; - } - if (*strchr(bufString, ':')) { - *strchr(bufString, ':') = '\0'; - } else { - return false; - } - as[0] = bufString; - as[1] = bufString + strlen(bufString) + 1; - if (as[0].size() > BUF_SIZE_SMALL || as[1].size() > BUF_SIZE_SMALL) { - return false; - } - if (as[0] == "tcp") { - int port = atoi(as[1].c_str()); - if (port <= 0 || port > MAX_IP_PORT) { - return false; - } - } - return true; -} - -bool HdcForwardBase::SetupPointContinue(HCtxForward ctx, int status) -{ - if (ctx->checkPoint) { - // send to active - uint8_t flag = status > 0; - SendToTask(ctx->id, CMD_FORWARD_CHECK_RESULT, &flag, 1); - FreeContext(ctx, 0, false); - return true; - } - if (status < 0) { - FreeContext(ctx, 0, true); - return false; - } - // send to active - if (!SendToTask(ctx->id, CMD_FORWARD_ACTIVE_MASTER, nullptr, 0)) { - FreeContext(ctx, 0, true); - return false; - } - return DoForwardBegin(ctx); -} - -bool HdcForwardBase::DetechForwardType(HCtxForward ctxPoint) -{ - string &sFType = ctxPoint->localArgs[0]; - string &sNodeCfg = ctxPoint->localArgs[1]; - // string to enum - if (sFType == "tcp") { - ctxPoint->type = FORWARD_TCP; - } else if (sFType == "dev") { - ctxPoint->type = FORWARD_DEVICE; - } else if (sFType == "localabstract") { - // daemon shell: /system/bin/socat abstract-listen:linux-abstract - - // daemon shell: /system/bin/socat - abstract-connect:linux-abstract - // host: hdc_std fport tcp:8080 localabstract:linux-abstract - ctxPoint->type = FORWARD_ABSTRACT; - } else if (sFType == "localreserved") { - sNodeCfg = HARMONY_RESERVED_SOCKET_PREFIX + sNodeCfg; - ctxPoint->type = FORWARD_RESERVED; - } else if (sFType == "localfilesystem") { - sNodeCfg = FILESYSTEM_SOCKET_PREFIX + sNodeCfg; - ctxPoint->type = FORWARD_FILESYSTEM; - } else if (sFType == "jdwp") { - ctxPoint->type = FORWARD_JDWP; - } else { - return false; - } - return true; -} - -bool HdcForwardBase::SetupTCPPoint(HCtxForward ctxPoint) -{ - string &sNodeCfg = ctxPoint->localArgs[1]; - int port = atoi(sNodeCfg.c_str()); - ctxPoint->tcp.data = ctxPoint; - uv_tcp_init(loopTask, &ctxPoint->tcp); - struct sockaddr_in addr; - if (ctxPoint->masterSlave) { - uv_ip4_addr("0.0.0.0", port, &addr); // loop interface - uv_tcp_bind(&ctxPoint->tcp, (const struct sockaddr *)&addr, 0); - if (uv_listen((uv_stream_t *)&ctxPoint->tcp, 4, ListenCallback)) { - ctxPoint->lastError = "TCP Port listen failed at " + sNodeCfg; - return false; - } - } else { - uv_ip4_addr("127.0.0.1", port, &addr); // loop interface - uv_connect_t *conn = new uv_connect_t(); - conn->data = ctxPoint; - uv_tcp_connect(conn, (uv_tcp_t *)&ctxPoint->tcp, (const struct sockaddr *)&addr, ConnectTarget); - } - return true; -} - -bool HdcForwardBase::SetupDevicePoint(HCtxForward ctxPoint) -{ - uint8_t flag = 1; - string &sNodeCfg = ctxPoint->localArgs[1]; - string resolvedPath = Base::CanonicalizeSpecPath(sNodeCfg); - if ((ctxPoint->fd = open(resolvedPath.c_str(), O_RDWR)) < 0) { - ctxPoint->lastError = "Open unix-dev failed"; - flag = -1; - } - auto funcRead = [&](const void *a, uint8_t *b, const int c) -> bool { - HCtxForward ctx = (HCtxForward)a; - return SendToTask(ctx->id, CMD_FORWARD_DATA, b, c); - }; - auto funcFinish = [&](const void *a, const bool b, const string c) -> bool { - HCtxForward ctx = (HCtxForward)a; - WRITE_LOG(LOG_DEBUG, "Error ReadForwardBuf dev,ret:%d reson:%s", b, c.c_str()); - FreeContext(ctx, 0, true); - return false; - }; - ctxPoint->fdClass = new HdcFileDescriptor(loopTask, ctxPoint->fd, ctxPoint, funcRead, funcFinish); - SetupPointContinue(ctxPoint, flag); - return true; -} - -bool HdcForwardBase::LocalAbstractConnect(uv_pipe_t *pipe, string &sNodeCfg) -{ - bool abstractRet = false; -#ifndef _WIN32 - int s = 0; - do { - if ((s = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) { - break; - } - fcntl(s, F_SETFD, FD_CLOEXEC); - struct sockaddr_un addr; - Base::ZeroStruct(addr); - int addrLen = sNodeCfg.size() + offsetof(struct sockaddr_un, sun_path) + 1; - addr.sun_family = AF_LOCAL; - addr.sun_path[0] = 0; - - if (memcpy_s(addr.sun_path + 1, sizeof(addr.sun_path) - 1, sNodeCfg.c_str(), sNodeCfg.size()) != EOK) { - break; - }; - // local connect, ignore timeout - if (connect(s, (struct sockaddr *)&addr, addrLen) < 0) { - break; - } - if (uv_pipe_open(pipe, s)) { - break; - } - abstractRet = true; - } while (false); - if (!abstractRet && s > 0) { - close(s); - } -#endif - return abstractRet; -} - -bool HdcForwardBase::SetupFilePoint(HCtxForward ctxPoint) -{ - string &sNodeCfg = ctxPoint->localArgs[1]; - ctxPoint->pipe.data = ctxPoint; - uv_pipe_init(loopTask, &ctxPoint->pipe, 0); - if (ctxPoint->masterSlave) { - if (ctxPoint->type == FORWARD_RESERVED || ctxPoint->type == FORWARD_FILESYSTEM) { - unlink(sNodeCfg.c_str()); - } - if (uv_pipe_bind(&ctxPoint->pipe, sNodeCfg.c_str())) { - ctxPoint->lastError = "Unix pipe bind failed"; - return false; - } - if (uv_listen((uv_stream_t *)&ctxPoint->pipe, 4, ListenCallback)) { - ctxPoint->lastError = "Unix pipe listen failed"; - return false; - } - } else { - uv_connect_t *connect = new uv_connect_t(); - connect->data = ctxPoint; - if (ctxPoint->type == FORWARD_ABSTRACT) { - bool abstractRet = LocalAbstractConnect(&ctxPoint->pipe, sNodeCfg); - SetupPointContinue(ctxPoint, abstractRet ? 0 : -1); - if (!abstractRet) { - ctxPoint->lastError = "LocalAbstractConnect failed"; - return false; - } - } else { - uv_pipe_connect(connect, &ctxPoint->pipe, sNodeCfg.c_str(), ConnectTarget); - } - } - return true; -} - -bool HdcForwardBase::SetupPoint(HCtxForward ctxPoint) -{ - bool ret = true; - if (!DetechForwardType(ctxPoint)) { - return false; - } - switch (ctxPoint->type) { - case FORWARD_TCP: - if (!SetupTCPPoint(ctxPoint)) { - ret = false; - }; - break; -#ifndef _WIN32 - case FORWARD_DEVICE: - if (!SetupDevicePoint(ctxPoint)) { - ret = false; - }; - break; - case FORWARD_JDWP: - if (!SetupJdwpPoint(ctxPoint)) { - ret = false; - }; - break; - case FORWARD_ABSTRACT: - case FORWARD_RESERVED: - case FORWARD_FILESYSTEM: - if (!SetupFilePoint(ctxPoint)) { - ret = false; - }; - break; -#else - case FORWARD_DEVICE: - case FORWARD_JDWP: - case FORWARD_ABSTRACT: - case FORWARD_RESERVED: - case FORWARD_FILESYSTEM: - ctxPoint->lastError = "Not supoort forward-type"; - ret = false; - break; -#endif - default: - ctxPoint->lastError = "Not supoort forward-type"; - ret = false; - break; - } - return ret; -} - -bool HdcForwardBase::BeginForward(const char *command, string &sError) -{ - bool ret = false; - int argc = 0; - char bufString[BUF_SIZE_SMALL] = ""; - HCtxForward ctxPoint = (HCtxForward)MallocContext(true); - if (!ctxPoint) { - WRITE_LOG(LOG_FATAL, "MallocContext failed"); - return false; - } - char **argv = Base::SplitCommandToArgs(command, &argc); - while (true) { - if (argc < CMD_ARG1_COUNT) { - break; - } - if (strlen(argv[0]) > BUF_SIZE_SMALL || strlen(argv[1]) > BUF_SIZE_SMALL) { - break; - } - if (!CheckNodeInfo(argv[0], ctxPoint->localArgs)) { - break; - } - if (!CheckNodeInfo(argv[1], ctxPoint->remoteArgs)) { - break; - } - ctxPoint->remoteParamenters = argv[1]; - if (!SetupPoint(ctxPoint)) { - break; - } - - ret = true; - break; - } - sError = ctxPoint->lastError; - if (ret) { - // First 8-byte parameter bit - int maxBufSize = sizeof(bufString) - FORWARD_PARAMENTER_BUFSIZE; - if (snprintf_s(bufString + FORWARD_PARAMENTER_BUFSIZE, maxBufSize, maxBufSize - 1, "%s", argv[1]) > 0) { - SendToTask(ctxPoint->id, CMD_FORWARD_CHECK, (uint8_t *)bufString, - FORWARD_PARAMENTER_BUFSIZE + strlen(bufString + FORWARD_PARAMENTER_BUFSIZE) + 1); - taskCommand = command; - } - } - if (argv) { - delete[]((char *)argv); - } - return ret; -} - -inline bool HdcForwardBase::FilterCommand(uint8_t *bufCmdIn, uint32_t *idOut, uint8_t **pContentBuf) -{ - *pContentBuf = bufCmdIn + DWORD_SERIALIZE_SIZE; - *idOut = ntohl(*(uint32_t *)bufCmdIn); - return true; -} - -bool HdcForwardBase::SlaveConnect(uint8_t *bufCmd, bool bCheckPoint, string &sError) -{ - bool ret = false; - char *content = nullptr; - uint32_t idSlaveOld = 0; - HCtxForward ctxPoint = (HCtxForward)MallocContext(false); - if (!ctxPoint) { - WRITE_LOG(LOG_FATAL, "MallocContext failed"); - return false; - } - idSlaveOld = ctxPoint->id; - ctxPoint->checkPoint = bCheckPoint; - // refresh another id,8byte param - FilterCommand(bufCmd, &ctxPoint->id, (uint8_t **)&content); - AdminContext(OP_UPDATE, idSlaveOld, ctxPoint); - content += FORWARD_PARAMENTER_BUFSIZE; - if (!CheckNodeInfo(content, ctxPoint->localArgs)) { - return false; - } - if ((ctxPoint->checkPoint && slaveCheckWhenBegin) || !ctxPoint->checkPoint) { - if (!SetupPoint(ctxPoint)) { - WRITE_LOG(LOG_FATAL, "SetupPoint failed"); - goto Finish; - } - sError = ctxPoint->lastError; - } else { - SetupPointContinue(ctxPoint, 0); - } - ret = true; -Finish: - if (!ret) { - FreeContext(ctxPoint, 0, true); - } - return ret; -} - -bool HdcForwardBase::DoForwardBegin(HCtxForward ctx) -{ - switch (ctx->type) { - case FORWARD_TCP: - case FORWARD_JDWP: // jdwp use tcp ->socketpair->jvm - uv_tcp_nodelay((uv_tcp_t *)&ctx->tcp, 1); - uv_read_start((uv_stream_t *)&ctx->tcp, AllocForwardBuf, ReadForwardBuf); - break; - case FORWARD_ABSTRACT: - case FORWARD_RESERVED: - case FORWARD_FILESYSTEM: - uv_read_start((uv_stream_t *)&ctx->pipe, AllocForwardBuf, ReadForwardBuf); - break; - case FORWARD_DEVICE: { - ctx->fdClass->StartWork(); - break; - } - default: - break; - } - ctx->ready = true; - return true; -} - -void *HdcForwardBase::AdminContext(const uint8_t op, const uint32_t id, HCtxForward hInput) -{ - void *hRet = nullptr; - map &mapCtx = mapCtxPoint; - switch (op) { - case OP_ADD: - mapCtx[id] = hInput; - break; - case OP_REMOVE: - mapCtx.erase(id); - break; - case OP_QUERY: - if (mapCtx.count(id)) { - hRet = mapCtx[id]; - } - break; - case OP_UPDATE: - mapCtx.erase(id); - mapCtx[hInput->id] = hInput; - break; - default: - break; - } - return hRet; -} - -void HdcForwardBase::SendCallbackForwardBuf(uv_write_t *req, int status) -{ - ContextForwardIO *ctxIO = (ContextForwardIO *)req->data; - HCtxForward ctx = (HCtxForward)ctxIO->ctxForward; - if (status < 0 && !ctx->finish) { - WRITE_LOG(LOG_DEBUG, "SendCallbackForwardBuf ctx->type:%d, status:%d finish", ctx->type, status); - ctx->thisClass->FreeContext(ctx, 0, true); - } - delete[] ctxIO->bufIO; - delete ctxIO; - delete req; -} - -int HdcForwardBase::SendForwardBuf(HCtxForward ctx, uint8_t *bufPtr, const int size) -{ - int nRet = 0; - if (size > static_cast(HDC_BUF_MAX_BYTES)) { - return -1; - } - auto pDynBuf = new uint8_t[size]; - if (!pDynBuf) { - return -1; - } - memcpy_s(pDynBuf, size, bufPtr, size); - if (FORWARD_DEVICE == ctx->type) { - nRet = ctx->fdClass->WriteWithMem(pDynBuf, size); - } else { - auto ctxIO = new ContextForwardIO(); - if (!ctxIO) { - delete[] pDynBuf; - return -1; - } - ctxIO->ctxForward = ctx; - ctxIO->bufIO = pDynBuf; - if (FORWARD_TCP == ctx->type || FORWARD_JDWP == ctx->type) { - nRet = Base::SendToStreamEx((uv_stream_t *)&ctx->tcp, pDynBuf, size, nullptr, - (void *)SendCallbackForwardBuf, (void *)ctxIO); - } else { - // FORWARD_ABSTRACT, FORWARD_RESERVED, FORWARD_FILESYSTEM, - nRet = Base::SendToStreamEx((uv_stream_t *)&ctx->pipe, pDynBuf, size, nullptr, - (void *)SendCallbackForwardBuf, (void *)ctxIO); - } - } - return nRet; -} - -bool HdcForwardBase::CommandForwardCheckResult(HCtxForward ctx, uint8_t *payload) -{ - bool ret = true; - bool bCheck = (bool)payload; - LogMsg(bCheck ? MSG_OK : MSG_FAIL, "Forwardport result:%s", bCheck ? "OK" : "Failed"); - if (bCheck) { - string mapInfo = taskInfo->serverOrDaemon ? "1|" : "0|"; - mapInfo += taskCommand; - ctx->ready = true; - ServerCommand(CMD_FORWARD_SUCCESS, (uint8_t *)mapInfo.c_str(), mapInfo.size() + 1); - } else { - ret = false; - FreeContext(ctx, 0, false); - } - return ret; -} - -bool HdcForwardBase::ForwardCommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) -{ - bool ret = true; - uint8_t *pContent = nullptr; - int sizeContent = 0; - uint32_t id = 0; - HCtxForward ctx = nullptr; - FilterCommand(payload, &id, &pContent); - sizeContent = payloadSize - DWORD_SERIALIZE_SIZE; - if (!(ctx = (HCtxForward)AdminContext(OP_QUERY, id, nullptr))) { - WRITE_LOG(LOG_WARN, "Query id failed"); - return false; - } - switch (command) { - case CMD_FORWARD_CHECK_RESULT: { - ret = CommandForwardCheckResult(ctx, payload); - break; - } - case CMD_FORWARD_ACTIVE_MASTER: { - ret = DoForwardBegin(ctx); - break; - } - case CMD_FORWARD_DATA: { - if (ctx->finish) { - break; - } - if (SendForwardBuf(ctx, pContent, sizeContent) < 0) { - FreeContext(ctx, 0, true); - } - break; - } - case CMD_FORWARD_FREE_CONTEXT: { - FreeContext(ctx, 0, false); - break; - } - default: - ret = false; - break; - } - if (!ret) { - if (ctx) { - FreeContext(ctx, 0, true); - } else { - WRITE_LOG(LOG_DEBUG, "ctx==nullptr raw free"); - TaskFinish(); - } - } - return ret; -} - -bool HdcForwardBase::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) -{ - bool ret = true; - string sError; - // prepare - if (CMD_FORWARD_INIT == command) { - if (!BeginForward((char *)(payload), sError)) { - ret = false; - goto Finish; - } - return true; - } else if (CMD_FORWARD_CHECK == command) { - // Detect remote if it's reachable - if (!SlaveConnect(payload, true, sError)) { - ret = false; - goto Finish; - } - return true; - } else if (CMD_FORWARD_ACTIVE_SLAVE == command) { - // slave connect target port when activating - if (!SlaveConnect(payload, false, sError)) { - ret = false; - goto Finish; - } - return true; - } - if (!ForwardCommandDispatch(command, payload, payloadSize)) { - ret = false; - goto Finish; - } -Finish: - if (!ret) { - if (!sError.size()) { - LogMsg(MSG_FAIL, "Forward parament failed"); - } else { - LogMsg(MSG_FAIL, (char *)sError.c_str()); - WRITE_LOG(LOG_WARN, (char *)sError.c_str()); - } - } - return ret; -} -} // namespace Hdc diff --git a/services/flashd/common/forward.h b/services/flashd/common/forward.h deleted file mode 100755 index 9baf4702..00000000 --- a/services/flashd/common/forward.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_FORWARD_H -#define HDC_FORWARD_H -#include "common.h" - -namespace Hdc { -class HdcForwardBase : public HdcTaskBase { -public: - HdcForwardBase(HTaskInfo hTaskInfo); - virtual ~HdcForwardBase(); - bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); - bool BeginForward(const char *command, string &sError); - void StopTask(); - bool ReadyForRelease(); - -protected: - enum FORWARD_TYPE { - FORWARD_TCP, - FORWARD_DEVICE, - FORWARD_JDWP, - FORWARD_ABSTRACT, - FORWARD_RESERVED, - FORWARD_FILESYSTEM, - }; - struct ContextForward { - FORWARD_TYPE type; - bool masterSlave; - bool checkPoint; - bool ready; - bool finish; - int fd; - uint32_t id; - uv_tcp_t tcp; - uv_pipe_t pipe; - HdcFileDescriptor *fdClass; - HdcForwardBase *thisClass; - string path; - string lastError; - string localArgs[2]; - string remoteArgs[2]; - string remoteParamenters; - }; - using HCtxForward = struct ContextForward *; - struct ContextForwardIO { - HCtxForward ctxForward; - uint8_t *bufIO; - }; - - virtual bool SetupJdwpPoint(HCtxForward ctxPoint) - { - return false; - } - bool SetupPointContinue(HCtxForward ctx, int status); - -private: - static void ListenCallback(uv_stream_t *server, const int status); - static void ConnectTarget(uv_connect_t *connection, int status); - static void ReadForwardBuf(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); - static void AllocForwardBuf(uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf); - static void SendCallbackForwardBuf(uv_write_t *req, int status); - static void OnFdRead(uv_fs_t *req); - - bool SetupPoint(HCtxForward ctxPoint); - void *MallocContext(bool masterSlave); - bool SlaveConnect(uint8_t *bufCmd, bool bCheckPoint, string &sError); - bool SendToTask(const uint32_t cid, const uint16_t command, uint8_t *bufPtr, const int bufSize); - bool FilterCommand(uint8_t *bufCmdIn, uint32_t *idOut, uint8_t **pContentBuf); - void *AdminContext(const uint8_t op, const uint32_t id, HCtxForward hInput); - bool DoForwardBegin(HCtxForward ctx); - int SendForwardBuf(HCtxForward ctx, uint8_t *bufPtr, const int size); - bool CheckNodeInfo(const char *nodeInfo, string as[2]); - void FreeContext(HCtxForward ctxIn, const uint32_t id, bool bNotifyRemote); - int LoopFdRead(HCtxForward ctx); - void FreeContextCallBack(HCtxForward ctx); - void FreeJDWP(HCtxForward ctx); - void OnAccept(uv_stream_t *server, HCtxForward ctxClient, uv_stream_t *client); - bool DetechForwardType(HCtxForward ctxPoint); - bool SetupTCPPoint(HCtxForward ctxPoint); - bool SetupDevicePoint(HCtxForward ctxPoint); - bool SetupFilePoint(HCtxForward ctxPoint); - bool ForwardCommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); - bool CommandForwardCheckResult(HCtxForward ctx, uint8_t *payload); - bool LocalAbstractConnect(uv_pipe_t *pipe, string &sNodeCfg); - - map mapCtxPoint; - string taskCommand; - const uint8_t FORWARD_PARAMENTER_BUFSIZE = 8; - const string FILESYSTEM_SOCKET_PREFIX = "/tmp/"; - const string HARMONY_RESERVED_SOCKET_PREFIX = "/dev/socket/"; - // set true to enable slave check when forward create - const bool slaveCheckWhenBegin = false; -}; -} // namespace Hdc -#endif \ No newline at end of file diff --git a/services/flashd/common/serial_struct.h b/services/flashd/common/serial_struct.h deleted file mode 100755 index b151f9dc..00000000 --- a/services/flashd/common/serial_struct.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_SERIAL_STRUCT_H -#define HDC_SERIAL_STRUCT_H -#include "common.h" -#include "serial_struct_define.h" -#include "transfer.h" - -namespace Hdc { -namespace SerialStruct { - constexpr int fieldOne = 1; - constexpr int fieldTwo = 2; - constexpr int fieldThree = 3; - constexpr int fieldFour = 4; - constexpr int fieldFive = 5; - constexpr int fieldSix = 6; - constexpr int fieldSeven = 7; - constexpr int fieldEight = 8; - constexpr int fieldNine = 9; - constexpr int fieldTen = 10; - constexpr int field11 = 11; - constexpr int field12 = 12; - constexpr int field13 = 13; - - template<> struct Descriptor { - static auto type() - { - return Message(Field("fileSize"), - Field("atime"), - Field("mtime"), - Field("options"), - Field("path"), - Field("optionalName"), - Field("updateIfNew"), - Field("compressType"), - Field("holdTimestamp"), - Field("functionName"), - Field("clientCwd"), - Field("reserve1"), - Field("reserve2")); - } - }; - - template<> struct Descriptor { - static auto type() - { - return Message(Field("index"), - Field("compressType"), - Field("compressSize"), - Field("uncompressSize")); - } - }; - - template<> struct Descriptor { - static auto type() - { - return Message(Field("banner"), - Field("authType"), - Field("sessionId"), - Field("connectKey"), - Field("buf")); - } - }; - - template<> struct Descriptor { - static auto type() - { - return Message(Field("channelId"), - Field("commandFlag"), - Field("checkSum"), - Field("vCode")); - } - }; -} // SerialStruct -} // Hdc -#endif // HDC_SERIAL_STRUCT_H diff --git a/services/flashd/common/serial_struct_define.h b/services/flashd/common/serial_struct_define.h deleted file mode 100755 index f2beb1cd..00000000 --- a/services/flashd/common/serial_struct_define.h +++ /dev/null @@ -1,1314 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_SERIAL_STRUCT_DEFINE_H -#define HDC_SERIAL_STRUCT_DEFINE_H -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// static file define. No need not modify. by zako -namespace Hdc { -// clang-format off -namespace SerialStruct { - namespace SerialDetail { - template struct MemPtr { - }; - template struct MemPtr { - using type = T; - using MemberType = U; - }; - template struct MessageImpl { - public: - MessageImpl(Fields &&... fields) - : _fields(std::move(fields)...) - { - } - - template void Visit(Handler &&handler) const - { - VisitImpl(std::forward(handler), std::make_index_sequence()); - } - - private: - std::tuple _fields; - - template void VisitImpl(Handler &&handler, std::index_sequence) const - { - (handler(std::get(_fields)), ...); - } - }; - - template struct FieldImpl { - using type = typename SerialDetail::MemPtr::type; - using MemberType = typename SerialDetail::MemPtr::MemberType; - constexpr static const uint32_t tag = Tag; - constexpr static const uint32_t flags = Flags; - const std::string field_name; - - static decltype(auto) get(const type &value) - { - return value.*MemPtr; - } - - static decltype(auto) get(type &value) - { - return value.*MemPtr; - } - }; - - template struct OneofFieldImpl { - using type = typename SerialDetail::MemPtr::type; - using MemberType = typename SerialDetail::MemPtr::MemberType; - constexpr static const uint32_t tag = Tag; - constexpr static const size_t index = Index; - constexpr static const uint32_t flags = Flags; - const std::string field_name; - - static decltype(auto) get(const type &value) - { - return value.*MemPtr; - } - - static decltype(auto) get(type &value) - { - return value.*MemPtr; - } - }; - - template - struct MapFieldImpl { - using type = typename SerialDetail::MemPtr::type; - using MemberType = typename SerialDetail::MemPtr::MemberType; - constexpr static const uint32_t tag = Tag; - constexpr static const uint32_t KEY_FLAGS = KeyFlags; - constexpr static const uint32_t VALUE_FLAGS = ValueFlags; - - const std::string field_name; - - static decltype(auto) get(const type &value) - { - return value.*MemPtr; - } - - static decltype(auto) get(type &value) - { - return value.*MemPtr; - } - }; - } - - enum class WireType : uint32_t { - VARINT = 0, - FIXED64 = 1, - LENGTH_DELIMETED = 2, - START_GROUP = 3, - END_GROUP = 4, - FIXED32 = 5, - }; - enum flags { no = 0, s = 1, f = 2 }; - template struct FlagsType { - }; - - template struct Descriptor { - static_assert(sizeof(T) == 0, "You need to implement descriptor for your own types"); - static void type() - { - } - }; - - template constexpr auto Message(Fields &&... fields) - { - return SerialDetail::MessageImpl(std::forward(fields)...); - } - - template constexpr auto Field(const std::string &fieldName) - { - return SerialDetail::FieldImpl { fieldName }; - } - - template - constexpr auto OneofField(const std::string &fieldName) - { - return SerialDetail::OneofFieldImpl { fieldName }; - } - - template - constexpr auto MapField(const std::string &fieldName) - { - return SerialDetail::MapFieldImpl { fieldName }; - } - - template const auto &MessageType() - { - static const auto message = Descriptor::type(); - return message; - } - - template struct Serializer; - - struct Writer { - virtual void Write(const void *bytes, size_t size) = 0; - }; - - struct reader { - virtual size_t Read(void *bytes, size_t size) = 0; - }; - - namespace SerialDetail { - template - struct HasSerializePacked : public std::false_type { - }; - - template - struct HasSerializePacked().SerializePacked( - std::declval(), std::declval(), std::declval()))>> : public std::true_type { - }; - - template - constexpr bool HAS_SERIALIZE_PACKED_V = HasSerializePacked::value; - - template - struct HasParsePacked : public std::false_type { - }; - - template - struct HasParsePacked().ParsePacked( - std::declval(), std::declval(), std::declval()))>> : public std::true_type { - }; - - template - constexpr bool HAS_PARSE_PACKED_V = HasParsePacked::value; - - static uint32_t MakeTagWireType(uint32_t tag, WireType wireType) - { - return (tag << 3) | static_cast(wireType); - } - - static inline void ReadTagWireType(uint32_t tagKey, uint32_t &tag, WireType &wireType) - { - wireType = static_cast(tagKey & 0b0111); - tag = tagKey >> 3; - } - - static uint32_t MakeZigzagValue(int32_t value) - { - return (static_cast(value) << 1) ^ static_cast(value >> 31); - } - - static uint64_t MakeZigzagValue(int64_t value) - { - return (static_cast(value) << 1) ^ static_cast(value >> 63); - } - - static int32_t ReadZigzagValue(uint32_t value) - { - return static_cast((value >> 1) ^ (~(value & 1) + 1)); - } - - static int64_t ReadZigzagValue(uint64_t value) - { - return static_cast((value >> 1) ^ (~(value & 1) + 1)); - } - - template To BitCast(From from) - { - static_assert(sizeof(To) == sizeof(From), ""); - static_assert(std::is_trivially_copyable_v, ""); - static_assert(std::is_trivially_copyable_v, ""); - To to; - memcpy_s(&to, sizeof(To), &from, sizeof(from)); - return to; - } - - struct WriterSizeCollector : public Writer { - void Write(const void *, size_t size) override - { - byte_size += size; - } - size_t byte_size = 0; - }; - - struct LimitedReader : public reader { - LimitedReader(reader &parent, size_t sizeLimit) - : _parent(parent), _size_limit(sizeLimit) - { - } - - size_t Read(void *bytes, size_t size) - { - auto sizeToRead = std::min(size, _size_limit); - auto readSize = _parent.Read(bytes, sizeToRead); - _size_limit -= readSize; - return readSize; - } - - size_t AvailableBytes() const - { - return _size_limit; - } - - private: - reader &_parent; - size_t _size_limit; - }; - - static bool ReadByte(uint8_t &value, reader &in) - { - return in.Read(&value, 1) == 1; - } - - static void WriteVarint(uint32_t value, Writer &out) - { - uint8_t b[5] {}; - for (size_t i = 0; i < 5; ++i) { - b[i] = value & 0b0111'1111; - value >>= 7; - if (value) { - b[i] |= 0b1000'0000; - } else { - out.Write(b, i + 1); - break; - } - } - } - - static void WriteVarint(uint64_t value, Writer &out) - { - uint8_t b[10] {}; - for (size_t i = 0; i < 10; ++i) { - b[i] = value & 0b0111'1111; - value >>= 7; - if (value) { - b[i] |= 0b1000'0000; - } else { - out.Write(b, i + 1); - break; - } - } - } - -#if defined(HOST_MAC) - static void WriteVarint(unsigned long value, Writer &out) - { - WriteVarint(static_cast(value), out); - } -#endif - - static bool ReadVarint(uint32_t &value, reader &in) - { - value = 0; - for (size_t c = 0; c < 5; ++c) { - uint8_t x; - if (!ReadByte(x, in)) { - return false; - } - value |= static_cast(x & 0b0111'1111) << 7 * c; - if (!(x & 0b1000'0000)) { - return true; - } - } - - return false; - } - - static bool ReadVarint(uint64_t &value, reader &in) - { - value &= 0; - for (size_t c = 0; c < 10; ++c) { - uint8_t x; - if (!ReadByte(x, in)) { - return false; - } - value |= static_cast(x & 0b0111'1111) << 7 * c; - if (!(x & 0b1000'0000)) { - return true; - } - } - return false; - } - -#if defined(HOST_MAC) - static bool ReadVarint(unsigned long &value, reader &in) - { - uint64_t intermediateValue; - if (ReadVarint(intermediateValue, in)) { - value = static_cast(intermediateValue); - return true; - } - return false; - } -#endif - - static void WriteFixed(uint32_t value, Writer &out) - { -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - out.Write(&value, sizeof(value)); -#else - static_assert(false, "Not a little-endian"); -#endif - } - - static void WriteFixed(uint64_t value, Writer &out) - { -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - out.Write(&value, sizeof(value)); -#else - static_assert(false, "Not a little-endian"); -#endif - } - - static void WriteFixed(double value, Writer &out) - { - WriteFixed(BitCast(value), out); - } - - static void WriteFixed(float value, Writer &out) - { - WriteFixed(BitCast(value), out); - } - - static void WriteVarint(int32_t value, Writer &out) - { - WriteVarint(BitCast(value), out); - } - - static void WriteVarint(int64_t value, Writer &out) - { - WriteVarint(BitCast(value), out); - } - - static void WriteSignedVarint(int32_t value, Writer &out) - { - WriteVarint(MakeZigzagValue(value), out); - } - - static void WriteSignedVarint(int64_t value, Writer &out) - { - WriteVarint(MakeZigzagValue(value), out); - } - - static void WriteSignedFixed(int32_t value, Writer &out) - { - WriteFixed(static_cast(value), out); - } - - static void WriteSignedFixed(int64_t value, Writer &out) - { - WriteFixed(static_cast(value), out); - } - - static void WriteTagWriteType(uint32_t tag, WireType wireType, Writer &out) - { - WriteVarint(MakeTagWireType(tag, wireType), out); - } - - static bool ReadFixed(uint32_t &value, reader &in) - { -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - return in.Read(&value, sizeof(value)) == sizeof(value); -#else - static_assert(false, "Not a little-endian"); -#endif - } - - static bool ReadFixed(uint64_t &value, reader &in) - { -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - return in.Read(&value, sizeof(value)) == sizeof(value); -#else - static_assert(false, "Not a little-endian"); -#endif - } - - static bool ReadFixed(double &value, reader &in) - { - uint64_t intermediateValue; - if (ReadFixed(intermediateValue, in)) { - value = BitCast(intermediateValue); - return true; - } - return false; - } - - static bool ReadFixed(float &value, reader &in) - { - uint32_t intermediateValue; - if (ReadFixed(intermediateValue, in)) { - value = BitCast(intermediateValue); - return true; - } - return false; - } - - static bool ReadVarint(int32_t &value, reader &in) - { - uint32_t intermediateValue; - if (ReadVarint(intermediateValue, in)) { - value = BitCast(intermediateValue); - return true; - } - return false; - } - - static bool ReadVarint(int64_t &value, reader &in) - { - uint64_t intermediateValue; - if (ReadVarint(intermediateValue, in)) { - value = BitCast(intermediateValue); - return true; - } - return false; - } - - static bool ReadSignedVarint(int32_t &value, reader &in) - { - uint32_t intermediateValue; - if (ReadVarint(intermediateValue, in)) { - value = ReadZigzagValue(intermediateValue); - return true; - } - return false; - } - - static bool ReadSignedVarint(int64_t &value, reader &in) - { - uint64_t intermediateValue; - if (ReadVarint(intermediateValue, in)) { - value = ReadZigzagValue(intermediateValue); - return true; - } - return false; - } - - static bool ReadSignedFixed(int32_t &value, reader &in) - { - uint32_t intermediateValue; - if (ReadFixed(intermediateValue, in)) { - value = static_cast(intermediateValue); - return true; - } - return false; - } - - static bool ReadSignedFixed(int64_t &value, reader &in) - { - uint64_t intermediateValue; - if (ReadFixed(intermediateValue, in)) { - value = static_cast(intermediateValue); - return true; - } - return false; - } - - template - void WriteField(const T &value, - const SerialDetail::OneofFieldImpl &, Writer &out) - { - using OneOf = SerialDetail::OneofFieldImpl; - Serializer::template SerializeOneof( - OneOf::tag, OneOf::get(value), FlagsType(), out); - } - - template - void WriteField(const T &value, - const SerialDetail::MapFieldImpl &, Writer &out) - { - using Map = SerialDetail::MapFieldImpl; - Serializer::SerializeMap( - Map::tag, Map::get(value), FlagsType(), FlagsType(), out); - } - - template - void WriteField(const T &value, const SerialDetail::FieldImpl &, Writer &out) - { - using Field = SerialDetail::FieldImpl; - Serializer::Serialize( - Field::tag, Field::get(value), FlagsType(), out); - } - - template - void WriteMessage(const T &value, const SerialDetail::MessageImpl &message, Writer &out) - { - message.Visit([&](const auto &field) { WriteField(value, field, out); }); - } - - template - void WriteRepeated(uint32_t tag, It begin, It end, Writer &out) - { - if (begin == end) { - return; - } - if constexpr (SerialDetail::HAS_SERIALIZE_PACKED_V, ValueType, FlagsType, - Writer>) { - WriteVarint(MakeTagWireType(tag, WireType::LENGTH_DELIMETED), out); - WriterSizeCollector sizeCollector; - for (auto it = begin; it != end; ++it) { - Serializer::SerializePacked(*it, FlagsType {}, sizeCollector); - } - WriteVarint(sizeCollector.byte_size, out); - for (auto it = begin; it != end; ++it) { - Serializer::SerializePacked(*it, FlagsType {}, out); - } - } else { - for (auto it = begin; it != end; ++it) { - Serializer::Serialize(tag, *it, FlagsType(), out); - } - } - } - - template - void WriteMapKeyValue(const std::pair &value, Writer &out) - { - Serializer::Serialize(1, value.first, FlagsType {}, out, true); - Serializer::Serialize(2, value.second, FlagsType {}, out, true); - } - - template - void WriteMap(uint32_t tag, const T &value, Writer &out) - { - auto begin = std::begin(value); - auto end = std::end(value); - - for (auto it = begin; it != end; ++it) { - WriteTagWriteType(tag, WireType::LENGTH_DELIMETED, out); - WriterSizeCollector sizeCollector; - WriteMapKeyValue(*it, sizeCollector); - WriteVarint(sizeCollector.byte_size, out); - WriteMapKeyValue(*it, out); - } - } - - template - bool ReadMapKeyValue(std::pair &value, reader &in) - { - static const auto pairAsMessage = Message(Field<1, &std::pair::first, KeyFlags>("key"), - Field<2, &std::pair::second, ValueFlags>("value")); - return ReadMessage(value, pairAsMessage, in); - } - - template - bool ReadMap(WireType wireType, T &value, reader &in) - { - if (wireType != WireType::LENGTH_DELIMETED) { - return false; - } - size_t size; - if (ReadVarint(size, in)) { - LimitedReader limitedIn(in, size); - while (limitedIn.AvailableBytes() > 0) { - std::pair item; - if (!ReadMapKeyValue(item, limitedIn)) { - return false; - } - value.insert(std::move(item)); - } - return true; - } - return false; - } - - template - bool ReadRepeated(WireType wireType, OutputIt output_it, reader &in) - { - if constexpr (SerialDetail::HAS_PARSE_PACKED_V, ValueType, FlagsType, - reader>) { - if (wireType != WireType::LENGTH_DELIMETED) { - return false; - } - - size_t size; - if (ReadVarint(size, in)) { - LimitedReader limitedIn(in, size); - - while (limitedIn.AvailableBytes() > 0) { - ValueType value; - if (!Serializer::ParsePacked(value, FlagsType(), limitedIn)) { - return false; - } - output_it = value; - ++output_it; - } - return true; - } - return false; - } else { - ValueType value; - if (Serializer::Parse(wireType, value, FlagsType(), in)) { - output_it = value; - ++output_it; - return true; - } - return false; - } - } - - template - void ReadField(T &value, uint32_t tag, WireType wireType, - const SerialDetail::OneofFieldImpl &, reader &in) - { - if (Tag != tag) { - return; - } - using OneOf = SerialDetail::OneofFieldImpl; - Serializer::template ParseOneof( - wireType, OneOf::get(value), FlagsType(), in); - } - - template - void ReadField(T &value, uint32_t tag, WireType wireType, - const SerialDetail::MapFieldImpl &, reader &in) - { - if (Tag != tag) { - return; - } - using Map = SerialDetail::MapFieldImpl; - Serializer::ParseMap( - wireType, Map::get(value), FlagsType(), FlagsType(), in); - } - - template - void ReadField(T &value, uint32_t tag, WireType wireType, - const SerialDetail::FieldImpl &, reader &in) - { - if (Tag != tag) { - return; - } - using Field = SerialDetail::FieldImpl; - Serializer::Parse(wireType, Field::get(value), FlagsType(), in); - } - - template bool ReadMessage(T &value, const MessageImpl &message, reader &in) - { - uint32_t tagKey; - while (ReadVarint(tagKey, in)) { - uint32_t tag; - WireType wireType; - ReadTagWireType(tagKey, tag, wireType); - message.Visit([&](const auto &field) { ReadField(value, tag, wireType, field, in); }); - } - return true; - } - } - - template struct Serializer { - // Commion Serializer threat type as Message - static void Serialize(uint32_t tag, const T &value, FlagsType<>, Writer &out, bool force = false) - { - SerialDetail::WriterSizeCollector sizeCollector; - SerialDetail::WriteMessage(value, MessageType(), sizeCollector); - if (!force && sizeCollector.byte_size == 0) { - return; - } - SerialDetail::WriteTagWriteType(tag, WireType::LENGTH_DELIMETED, out); - SerialDetail::WriteVarint(sizeCollector.byte_size, out); - SerialDetail::WriteMessage(value, MessageType(), out); - } - - static bool Parse(WireType wireType, T &value, FlagsType<>, reader &in) - { - if (wireType != WireType::LENGTH_DELIMETED) { - return false; - } - size_t size; - if (SerialDetail::ReadVarint(size, in)) { - SerialDetail::LimitedReader limitedIn(in, size); - return SerialDetail::ReadMessage(value, MessageType(), limitedIn); - } - return false; - } - }; - - template<> struct Serializer { - static void Serialize(uint32_t tag, int32_t value, FlagsType<>, Writer &out, bool force = false) - { - SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); - SerialDetail::WriteVarint(value, out); - } - - static void Serialize(uint32_t tag, int32_t value, FlagsType, Writer &out, bool force = false) - { - SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); - SerialDetail::WriteSignedVarint(value, out); - } - - static void Serialize( - uint32_t tag, int32_t value, FlagsType, Writer &out, bool force = false) - { - SerialDetail::WriteTagWriteType(tag, WireType::FIXED32, out); - SerialDetail::WriteSignedFixed(value, out); - } - - static void SerializePacked(int32_t value, FlagsType<>, Writer &out) - { - SerialDetail::WriteVarint(value, out); - } - - static void SerializePacked(int32_t value, FlagsType, Writer &out) - { - SerialDetail::WriteSignedVarint(value, out); - } - - static void SerializePacked(int32_t value, FlagsType, Writer &out) - { - SerialDetail::WriteSignedFixed(value, out); - } - - static bool Parse(WireType wire_type, int32_t &value, FlagsType<>, reader &in) - { - if (wire_type != WireType::VARINT) - return false; - return SerialDetail::ReadVarint(value, in); - } - - static bool Parse(WireType wire_type, int32_t &value, FlagsType, reader &in) - { - if (wire_type != WireType::VARINT) - return false; - return SerialDetail::ReadSignedVarint(value, in); - } - - static bool Parse(WireType wire_type, int32_t &value, FlagsType, reader &in) - { - if (wire_type != WireType::FIXED32) - return false; - return SerialDetail::ReadSignedFixed(value, in); - } - - static bool ParsePacked(int32_t &value, FlagsType<>, reader &in) - { - return SerialDetail::ReadVarint(value, in); - } - - static bool ParsePacked(int32_t &value, FlagsType, reader &in) - { - return SerialDetail::ReadSignedVarint(value, in); - } - - static bool ParsePacked(int32_t &value, FlagsType, reader &in) - { - return SerialDetail::ReadSignedFixed(value, in); - } - }; - - template<> struct Serializer { - static void Serialize(uint32_t tag, uint32_t value, FlagsType<>, Writer &out, bool force = false) - { - SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); - SerialDetail::WriteVarint(value, out); - } - - static void Serialize(uint32_t tag, uint32_t value, FlagsType, Writer &out, bool force = false) - { - SerialDetail::WriteTagWriteType(tag, WireType::FIXED32, out); - SerialDetail::WriteFixed(value, out); - } - - static void SerializePacked(uint32_t value, FlagsType<>, Writer &out) - { - SerialDetail::WriteVarint(value, out); - } - - static void SerializePacked(uint32_t value, FlagsType, Writer &out) - { - SerialDetail::WriteFixed(value, out); - } - - static bool Parse(WireType wire_type, uint32_t &value, FlagsType<>, reader &in) - { - if (wire_type != WireType::VARINT) - return false; - return SerialDetail::ReadVarint(value, in); - } - - static bool Parse(WireType wire_type, uint32_t &value, FlagsType, reader &in) - { - if (wire_type != WireType::FIXED32) - return false; - return SerialDetail::ReadFixed(value, in); - } - - static bool ParsePacked(uint32_t &value, FlagsType<>, reader &in) - { - return SerialDetail::ReadVarint(value, in); - } - - static bool ParsePacked(uint32_t &value, FlagsType, reader &in) - { - return SerialDetail::ReadFixed(value, in); - } - }; - - template<> struct Serializer { - static void Serialize(uint32_t tag, int64_t value, FlagsType<>, Writer &out, bool force = false) - { - SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); - SerialDetail::WriteVarint(value, out); - } - - static void Serialize(uint32_t tag, int64_t value, FlagsType, Writer &out, bool force = false) - { - SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); - SerialDetail::WriteSignedVarint(value, out); - } - - static void Serialize( - uint32_t tag, int64_t value, FlagsType, Writer &out, bool force = false) - { - SerialDetail::WriteTagWriteType(tag, WireType::FIXED64, out); - SerialDetail::WriteSignedFixed(value, out); - } - - static void SerializePacked(int64_t value, FlagsType<>, Writer &out) - { - SerialDetail::WriteVarint(value, out); - } - - static void SerializePacked(int64_t value, FlagsType, Writer &out) - { - SerialDetail::WriteSignedVarint(value, out); - } - - static void SerializePacked(int64_t value, FlagsType, Writer &out) - { - SerialDetail::WriteSignedFixed(value, out); - } - - static bool Parse(WireType wire_type, int64_t &value, FlagsType<>, reader &in) - { - if (wire_type != WireType::VARINT) - return false; - return SerialDetail::ReadVarint(value, in); - } - - static bool Parse(WireType wire_type, int64_t &value, FlagsType, reader &in) - { - if (wire_type != WireType::VARINT) - return false; - return SerialDetail::ReadSignedVarint(value, in); - } - - static bool Parse(WireType wire_type, int64_t &value, FlagsType, reader &in) - { - if (wire_type != WireType::FIXED64) - return false; - return SerialDetail::ReadSignedFixed(value, in); - } - - static bool ParsePacked(int64_t &value, FlagsType<>, reader &in) - { - return SerialDetail::ReadVarint(value, in); - } - - static bool ParsePacked(int64_t &value, FlagsType, reader &in) - { - return SerialDetail::ReadSignedVarint(value, in); - } - - static bool ParsePacked(int64_t &value, FlagsType, reader &in) - { - return SerialDetail::ReadSignedFixed(value, in); - } - }; - - template<> struct Serializer { - static void Serialize(uint32_t tag, uint64_t value, FlagsType<>, Writer &out, bool force = false) - { - SerialDetail::WriteTagWriteType(tag, WireType::VARINT, out); - SerialDetail::WriteVarint(value, out); - } - - static void Serialize(uint32_t tag, uint64_t value, FlagsType, Writer &out, bool force = false) - { - if (!force && value == UINT64_C(0)) - return; - - SerialDetail::WriteTagWriteType(tag, WireType::FIXED64, out); - SerialDetail::WriteFixed(value, out); - } - - static void SerializePacked(uint64_t value, FlagsType<>, Writer &out) - { - SerialDetail::WriteVarint(value, out); - } - - static void SerializePacked(uint64_t value, FlagsType, Writer &out) - { - SerialDetail::WriteFixed(value, out); - } - - static bool Parse(WireType wire_type, uint64_t &value, FlagsType<>, reader &in) - { - if (wire_type != WireType::VARINT) - return false; - return SerialDetail::ReadVarint(value, in); - } - - static bool Parse(WireType wire_type, uint64_t &value, FlagsType, reader &in) - { - if (wire_type != WireType::FIXED64) - return false; - return SerialDetail::ReadFixed(value, in); - } - - static bool ParsePacked(uint64_t &value, FlagsType<>, reader &in) - { - return SerialDetail::ReadVarint(value, in); - } - - static bool ParsePacked(uint64_t &value, FlagsType, reader &in) - { - return SerialDetail::ReadFixed(value, in); - } - }; - - template<> struct Serializer { - static void Serialize(uint32_t tag, double value, FlagsType<>, Writer &out, bool force = false) - { - if (!force && std::fpclassify(value) == FP_ZERO) { - return; - } - SerialDetail::WriteTagWriteType(tag, WireType::FIXED64, out); - SerialDetail::WriteFixed(value, out); - } - - static void SerializePacked(double value, FlagsType<>, Writer &out) - { - SerialDetail::WriteFixed(value, out); - } - - static bool Parse(WireType wire_type, double &value, FlagsType<>, reader &in) - { - if (wire_type != WireType::FIXED64) { - return false; - } - return SerialDetail::ReadFixed(value, in); - } - - static bool ParsePacked(double &value, FlagsType<>, reader &in) - { - return SerialDetail::ReadFixed(value, in); - } - }; - - template<> struct Serializer { - static void Serialize(uint32_t tag, float value, FlagsType<>, Writer &out, bool force = false) - { - if (!force && std::fpclassify(value) == FP_ZERO) { - return; - } - SerialDetail::WriteTagWriteType(tag, WireType::FIXED32, out); - SerialDetail::WriteFixed(value, out); - } - - static void SerializePacked(float value, FlagsType<>, Writer &out) - { - SerialDetail::WriteFixed(value, out); - } - - static bool Parse(WireType wire_type, float &value, FlagsType<>, reader &in) - { - if (wire_type != WireType::FIXED32) { - return false; - } - return SerialDetail::ReadFixed(value, in); - } - - static bool ParsePacked(float &value, FlagsType<>, reader &in) - { - return SerialDetail::ReadFixed(value, in); - } - }; - - template<> struct Serializer { - static void Serialize(uint32_t tag, bool value, FlagsType<>, Writer &out, bool force = false) - { - Serializer::Serialize(tag, value ? 1 : 0, FlagsType(), out, force); - } - - static void SerializePacked(bool value, FlagsType<>, Writer &out) - { - Serializer::SerializePacked(value ? 1 : 0, FlagsType(), out); - } - - static bool Parse(WireType wire_type, bool &value, FlagsType<>, reader &in) - { - uint32_t intermedaite_value; - if (Serializer::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) { - value = static_cast(intermedaite_value); - return true; - } - return false; - } - - static bool ParsePacked(bool &value, FlagsType<>, reader &in) - { - uint32_t intermedaite_value; - if (Serializer::ParsePacked(intermedaite_value, FlagsType<>(), in)) { - value = static_cast(intermedaite_value); - return true; - } - return false; - } - }; - - template struct Serializer>> { - using U = std::underlying_type_t; - - static void Serialize(uint32_t tag, T value, FlagsType<>, Writer &out, bool force = false) - { - Serializer::Serialize(tag, static_cast(value), FlagsType<>(), out, force); - } - - static void SerializePacked(T value, FlagsType<>, Writer &out) - { - Serializer::SerializePacked(static_cast(value), FlagsType<>(), out); - } - - static bool Parse(WireType wire_type, T &value, FlagsType<>, reader &in) - { - U intermedaite_value; - if (Serializer::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) { - value = static_cast(intermedaite_value); - return true; - } - return false; - } - - static bool ParsePacked(T &value, FlagsType<>, reader &in) - { - U intermedaite_value; - if (Serializer::ParsePacked(intermedaite_value, FlagsType<>(), in)) { - value = static_cast(intermedaite_value); - return true; - } - return false; - } - }; - - template<> struct Serializer { - static void Serialize(uint32_t tag, const std::string &value, FlagsType<>, Writer &out, bool force = false) - { - SerialDetail::WriteTagWriteType(tag, WireType::LENGTH_DELIMETED, out); - SerialDetail::WriteVarint(value.size(), out); - out.Write(value.data(), value.size()); - } - - static bool Parse(WireType wire_type, std::string &value, FlagsType<>, reader &in) - { - if (wire_type != WireType::LENGTH_DELIMETED) { - return false; - } - size_t size; - if (SerialDetail::ReadVarint(size, in)) { - value.resize(size); - if (in.Read(value.data(), size) == size) { - return true; - } - } - return false; - } - }; - - template struct Serializer> { - template - static void Serialize(uint32_t tag, const std::vector &value, FlagsType, Writer &out) - { - SerialDetail::WriteRepeated(tag, value.begin(), value.end(), out); - } - - template - static bool Parse(WireType wire_type, std::vector &value, FlagsType, reader &in) - { - return SerialDetail::ReadRepeated(wire_type, std::back_inserter(value), in); - } - }; - - template struct Serializer> { - template - static void Serialize(uint32_t tag, const std::optional &value, FlagsType, Writer &out) - { - if (!value.has_value()) { - return; - } - Serializer::Serialize(tag, *value, FlagsType(), out); - } - - template - static bool Parse(WireType wire_type, std::optional &value, FlagsType, reader &in) - { - return Serializer::Parse(wire_type, value.emplace(), FlagsType(), in); - } - }; - - template struct Serializer> { - template - static void SerializeOneof(uint32_t tag, const std::variant &value, FlagsType, Writer &out) - { - if (value.index() != Index) - return; - - Serializer>>::Serialize( - tag, std::get(value), FlagsType(), out); - } - - template - static bool ParseOneof(WireType wire_type, std::variant &value, FlagsType, reader &in) - { - return Serializer>>::Parse( - wire_type, value.template emplace(), FlagsType(), in); - } - }; - - template struct Serializer> { - template - static void SerializeMap( - uint32_t tag, const std::map &value, FlagsType, FlagsType, Writer &out) - { - SerialDetail::WriteMap(tag, value, out); - } - - template - static bool ParseMap( - WireType wire_type, std::map &value, FlagsType, FlagsType, reader &in) - { - return SerialDetail::ReadMap(wire_type, value, in); - } - }; - - struct StringWriter : public Writer { - StringWriter(std::string &out) - : _out(out) - { - } - - void Write(const void *bytes, size_t size) override - { - _out.append(reinterpret_cast(bytes), size); - } - - private: - std::string &_out; - }; - - struct StringReader : public reader { - StringReader(const std::string &in) - : _in(in), _pos(0) - { - } - - size_t Read(void *bytes, size_t size) override - { - size_t readSize = std::min(size, _in.size() - _pos); - if (memcpy_s(bytes, size, _in.data() + _pos, readSize) != EOK) { - return readSize; - } - _pos += readSize; - return readSize; - } - - private: - const std::string &_in; - size_t _pos; - }; - // mytype begin, just support base type, but really use protobuf raw type(uint32) - template<> struct Serializer { - static void Serialize(uint32_t tag, uint8_t value, FlagsType<>, Writer &out, bool force = false) - { - Serializer::Serialize(tag, value, FlagsType(), out, force); - } - - static void SerializePacked(uint8_t value, FlagsType<>, Writer &out) - { - Serializer::SerializePacked(value, FlagsType(), out); - } - - static bool Parse(WireType wire_type, uint8_t &value, FlagsType<>, reader &in) - { - uint32_t intermedaite_value; - if (Serializer::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) { - value = static_cast(intermedaite_value); - return true; - } - return false; - } - - static bool ParsePacked(uint8_t &value, FlagsType<>, reader &in) - { - uint32_t intermedaite_value; - if (Serializer::ParsePacked(intermedaite_value, FlagsType<>(), in)) { - value = static_cast(intermedaite_value); - return true; - } - return false; - } - }; - template<> struct Serializer { - static void Serialize(uint32_t tag, uint16_t value, FlagsType<>, Writer &out, bool force = false) - { - Serializer::Serialize(tag, value, FlagsType(), out, force); - } - - static void SerializePacked(uint16_t value, FlagsType<>, Writer &out) - { - Serializer::SerializePacked(value, FlagsType(), out); - } - - static bool Parse(WireType wire_type, uint16_t &value, FlagsType<>, reader &in) - { - uint32_t intermedaite_value; - if (Serializer::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) { - value = static_cast(intermedaite_value); - return true; - } - return false; - } - - static bool ParsePacked(uint16_t &value, FlagsType<>, reader &in) - { - uint32_t intermedaite_value; - if (Serializer::ParsePacked(intermedaite_value, FlagsType<>(), in)) { - value = static_cast(intermedaite_value); - return true; - } - return false; - } - }; - // mytype finish - - template std::string SerializeToString(const T &value) - { - std::string out; - StringWriter stringOut(out); - SerialDetail::WriteMessage(value, MessageType(), stringOut); - return out; - } - - template bool ParseFromString(T &value, const std::string &in) - { - StringReader stringIn(in); - return SerialDetail::ReadMessage(value, MessageType(), stringIn); - } -} -// clang-format on -} // Hdc -#endif // HDC_SERIAL_STRUCT_DEFINE_H diff --git a/services/flashd/common/session.cpp b/services/flashd/common/session.cpp deleted file mode 100755 index bef648a2..00000000 --- a/services/flashd/common/session.cpp +++ /dev/null @@ -1,1062 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "session.h" -#include "serial_struct.h" - -namespace Hdc { -HdcSessionBase::HdcSessionBase(bool serverOrDaemonIn) -{ - // server/daemon common initialization code - string threadNum = std::to_string(SIZE_THREAD_POOL); - uv_os_setenv("UV_THREADPOOL_SIZE", threadNum.c_str()); - uv_loop_init(&loopMain); - WRITE_LOG(LOG_DEBUG, "loopMain init"); - uv_rwlock_init(&mainAsync); - uv_async_init(&loopMain, &asyncMainLoop, MainAsyncCallback); - uv_rwlock_init(&lockMapSession); - serverOrDaemon = serverOrDaemonIn; - ctxUSB = nullptr; - wantRestart = false; - -#ifdef HDC_HOST - if (serverOrDaemon) { - libusb_init((libusb_context **)&ctxUSB); - } -#endif -} - -HdcSessionBase::~HdcSessionBase() -{ - Base::TryCloseHandle((uv_handle_t *)&asyncMainLoop); - uv_loop_close(&loopMain); - // clear base - uv_rwlock_destroy(&mainAsync); - uv_rwlock_destroy(&lockMapSession); -#ifdef HDC_HOST - if (serverOrDaemon) { - libusb_exit((libusb_context *)ctxUSB); - } -#endif - WRITE_LOG(LOG_DEBUG, "~HdcSessionBase free sessionRef:%d instance:%s", uint32_t(sessionRef), - serverOrDaemon ? "server" : "daemon"); -} - -// remove step2 -bool HdcSessionBase::TryRemoveTask(HTaskInfo hTask) -{ - if (hTask->taskFree) { - return true; - } - bool ret = RemoveInstanceTask(OP_REMOVE, hTask); - if (ret) { - hTask->taskFree = true; - } else { - // This is used to check that the memory cannot be cleaned up. If the memory cannot be released, break point - // here to see which task has not been released - // print task clear - } - return ret; -} - -// remove step1 -bool HdcSessionBase::BeginRemoveTask(HTaskInfo hTask) -{ - bool ret = true; - if (hTask->taskStop || hTask->taskFree || !hTask->taskClass) { - return true; - } - - WRITE_LOG(LOG_DEBUG, "BeginRemoveTask taskType:%d", hTask->taskType); - ret = RemoveInstanceTask(OP_CLEAR, hTask); - auto taskClassDeleteRetry = [](uv_idle_t *handle) -> void { - HTaskInfo hTask = (HTaskInfo)handle->data; - HdcSessionBase *thisClass = (HdcSessionBase *)hTask->ownerSessionClass; - if (!thisClass->TryRemoveTask(hTask)) { - return; - } - HSession hSession = thisClass->AdminSession(OP_QUERY, hTask->sessionId, nullptr); - thisClass->AdminTask(OP_REMOVE, hSession, hTask->channelId, nullptr); - WRITE_LOG(LOG_DEBUG, "TaskDelay task remove finish, channelId:%d", hTask->channelId); - delete hTask; - Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseIdleCallback); - }; - Base::IdleUvTask(hTask->runLoop, hTask, taskClassDeleteRetry); - - hTask->taskStop = true; - ret = true; - return ret; -} - -// Clear all Task or a single Task, the regular situation is stopped first, and the specific class memory is cleaned up -// after the end of the LOOP. -// When ChannelIdinput == 0, at this time, all of the LOOP ends, all runs in the class end, so directly skip STOP, -// physical memory deletion class trimming -void HdcSessionBase::ClearOwnTasks(HSession hSession, const uint32_t channelIDInput) -{ - // First case: normal task cleanup process (STOP Remove) - // Second: The task is cleaned up, the session ends - // Third: The task is cleaned up, and the session is directly over the session. - map::iterator iter; - for (iter = hSession->mapTask->begin(); iter != hSession->mapTask->end();) { - uint32_t channelId = iter->first; - HTaskInfo hTask = iter->second; - if (channelIDInput != 0) { // single - if (channelIDInput != channelId) { - ++iter; - continue; - } - BeginRemoveTask(hTask); - WRITE_LOG(LOG_DEBUG, "ClearOwnTasks OP_CLEAR finish,session:%p channelIDInput:%d", hSession, - channelIDInput); - break; - } - // multi - BeginRemoveTask(hTask); - ++iter; - } -} - -void HdcSessionBase::ClearSessions() -{ - // no need to lock mapSession - // broadcast free singal - for (auto v : mapSession) { - HSession hSession = (HSession)v.second; - if (!hSession->isDead) { - FreeSession(hSession->sessionId); - } - } -} - -void HdcSessionBase::ReMainLoopForInstanceClear() -{ // reloop - auto clearSessionsForFinish = [](uv_idle_t *handle) -> void { - HdcSessionBase *thisClass = (HdcSessionBase *)handle->data; - if (thisClass->sessionRef > 0) { - return; - } - // all task has been free - uv_close((uv_handle_t *)handle, Base::CloseIdleCallback); - uv_stop(&thisClass->loopMain); - }; - Base::IdleUvTask(&loopMain, this, clearSessionsForFinish); - uv_run(&loopMain, UV_RUN_DEFAULT); -}; - -void HdcSessionBase::EnumUSBDeviceRegister(void (*pCallBack)(HSession hSession)) -{ - if (!pCallBack) { - return; - } - uv_rwlock_rdlock(&lockMapSession); - map::iterator i; - for (i = mapSession.begin(); i != mapSession.end(); ++i) { - HSession hs = i->second; - if (hs->connType != CONN_USB) { - continue; - } - if (hs->hUSB == nullptr) { - continue; - } - if (pCallBack) { - pCallBack(hs); - } - break; - } - uv_rwlock_rdunlock(&lockMapSession); -} - -// The PC side gives the device information, determines if the USB device is registered -// PDEV and Busid Devid two choices -HSession HdcSessionBase::QueryUSBDeviceRegister(void *pDev, int busIDIn, int devIDIn) -{ -#ifdef HDC_HOST - libusb_device *dev = (libusb_device *)pDev; - HSession hResult = nullptr; - if (!mapSession.size()) { - return nullptr; - } - uint8_t busId = 0; - uint8_t devId = 0; - if (pDev) { - busId = libusb_get_bus_number(dev); - devId = libusb_get_device_address(dev); - } else { - busId = busIDIn; - devId = devIDIn; - } - uv_rwlock_rdlock(&lockMapSession); - map::iterator i; - for (i = mapSession.begin(); i != mapSession.end(); ++i) { - HSession hs = i->second; - if (hs->connType == CONN_USB) { - continue; - } - if (hs->hUSB == nullptr) { - continue; - } - if (hs->hUSB->devId != devId || hs->hUSB->busId != busId) { - continue; - } - hResult = hs; - break; - } - uv_rwlock_rdunlock(&lockMapSession); - return hResult; -#else - return nullptr; -#endif -} - -void HdcSessionBase::AsyncMainLoopTask(uv_idle_t *handle) -{ - AsyncParam *param = (AsyncParam *)handle->data; - HdcSessionBase *thisClass = (HdcSessionBase *)param->thisClass; - switch (param->method) { - case ASYNC_FREE_SESSION: - // Destruction is unified in the main thread - thisClass->FreeSession(param->sid); // todo Double lock - break; - case ASYNC_STOP_MAINLOOP: - uv_stop(&thisClass->loopMain); - break; - default: - break; - } - if (param->data) { - delete[]((uint8_t *)param->data); - } - delete param; - param = nullptr; - Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseIdleCallback); -} - -void HdcSessionBase::MainAsyncCallback(uv_async_t *handle) -{ - HdcSessionBase *thisClass = (HdcSessionBase *)handle->data; - list::iterator i; - list &lst = thisClass->lstMainThreadOP; - uv_rwlock_wrlock(&thisClass->mainAsync); - for (i = lst.begin(); i != lst.end();) { - AsyncParam *param = (AsyncParam *)*i; - Base::IdleUvTask(&thisClass->loopMain, param, AsyncMainLoopTask); - i = lst.erase(i); - } - uv_rwlock_wrunlock(&thisClass->mainAsync); -} - -void HdcSessionBase::PushAsyncMessage(const uint32_t sessionId, const uint8_t method, const void *data, - const int dataSize) -{ - AsyncParam *param = new AsyncParam(); - if (!param) { - return; - } - param->sid = sessionId; - param->thisClass = this; - param->method = method; - if (dataSize > 0) { - param->dataSize = dataSize; - param->data = new uint8_t[param->dataSize](); - if (!param->data) { - delete param; - return; - } - if (memcpy_s((uint8_t *)param->data, param->dataSize, data, dataSize)) { - delete[]((uint8_t *)param->data); - delete param; - return; - } - } - - asyncMainLoop.data = this; - uv_rwlock_wrlock(&mainAsync); - lstMainThreadOP.push_back(param); - uv_rwlock_wrunlock(&mainAsync); - uv_async_send(&asyncMainLoop); -} - -void HdcSessionBase::WorkerPendding() -{ - uv_run(&loopMain, UV_RUN_DEFAULT); - ClearInstanceResource(); -} - -int HdcSessionBase::MallocSessionByConnectType(HSession hSession) -{ - int ret = 0; - switch (hSession->connType) { - case CONN_TCP: { - uv_tcp_init(&loopMain, &hSession->hWorkTCP); - ++hSession->uvRef; - hSession->hWorkTCP.data = hSession; - break; - } - case CONN_USB: { - // Some members need to be placed at the primary thread - HUSB hUSB = new HdcUSB(); - if (!hUSB) { - ret = -1; - break; - } - hSession->hUSB = hUSB; -#ifdef HDC_HOST - constexpr auto maxBufFactor = 1.5; - int max = Base::GetMaxBufSize() * maxBufFactor + sizeof(USBHead); - hUSB->sizeEpBuf = max; - hUSB->bufDevice = new uint8_t[max](); - hUSB->bufHost = new uint8_t[max](); - hUSB->transferRecv = libusb_alloc_transfer(0); - hUSB->transferSend = libusb_alloc_transfer(0); -#else -#endif - break; - } - default: - ret = -1; - break; - } - return ret; -} - -// Avoid unit test when client\server\daemon on the same host, maybe get the same ID value -uint32_t HdcSessionBase::GetSessionPseudoUid() -{ - uint32_t uid = 0; - Hdc::HSession hInput = nullptr; - do { - uid = static_cast(Base::GetRandom()); - } while ((hInput = AdminSession(OP_QUERY, uid, nullptr)) != nullptr); - return uid; -} - -// when client 0 to automatic generated,when daemon First place 1 followed by -HSession HdcSessionBase::MallocSession(bool serverOrDaemon, const ConnType connType, void *classModule, - uint32_t sessionId) -{ - HSession hSession = new HdcSession(); - if (!hSession) { - return nullptr; - } - int ret = 0; - ++sessionRef; - memset_s(hSession->ctrlFd, sizeof(hSession->ctrlFd), 0, sizeof(hSession->ctrlFd)); - hSession->classInstance = this; - hSession->connType = connType; - hSession->classModule = classModule; - hSession->isDead = false; - hSession->sessionId = ((sessionId == 0) ? GetSessionPseudoUid() : sessionId); - hSession->serverOrDaemon = serverOrDaemon; - hSession->hWorkThread = uv_thread_self(); - hSession->mapTask = new map(); - hSession->listKey = new list; - hSession->uvRef = 0; - // pullup child - WRITE_LOG(LOG_DEBUG, "HdcSessionBase NewSession, sessionId:%u", hSession->sessionId); - - uv_tcp_init(&loopMain, &hSession->ctrlPipe[STREAM_MAIN]); - ++hSession->uvRef; - Base::CreateSocketPair(hSession->ctrlFd); - uv_tcp_open(&hSession->ctrlPipe[STREAM_MAIN], hSession->ctrlFd[STREAM_MAIN]); - uv_read_start((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], Base::AllocBufferCallback, ReadCtrlFromSession); - hSession->ctrlPipe[STREAM_MAIN].data = hSession; - hSession->ctrlPipe[STREAM_WORK].data = hSession; - // Activate USB DAEMON's data channel, may not for use - uv_tcp_init(&loopMain, &hSession->dataPipe[STREAM_MAIN]); - ++hSession->uvRef; - Base::CreateSocketPair(hSession->dataFd); - uv_tcp_open(&hSession->dataPipe[STREAM_MAIN], hSession->dataFd[STREAM_MAIN]); - hSession->dataPipe[STREAM_MAIN].data = hSession; - hSession->dataPipe[STREAM_WORK].data = hSession; - Base::SetTcpOptions(&hSession->dataPipe[STREAM_MAIN]); - ret = MallocSessionByConnectType(hSession); - if (ret) { - delete hSession; - hSession = nullptr; - } else { - AdminSession(OP_ADD, hSession->sessionId, hSession); - } - return hSession; -} - -void HdcSessionBase::FreeSessionByConnectType(HSession hSession) -{ - if (CONN_USB == hSession->connType) { - // ibusb All context is applied for sub-threaded, so it needs to be destroyed in the subline - if (!hSession->hUSB) { - return; - } - HUSB hUSB = hSession->hUSB; - if (!hUSB) { - return; - } -#ifdef HDC_HOST - if (hUSB->devHandle) { - libusb_release_interface(hUSB->devHandle, hUSB->interfaceNumber); - libusb_close(hUSB->devHandle); - hUSB->devHandle = nullptr; - } - - delete[] hUSB->bufDevice; - delete[] hUSB->bufHost; - libusb_free_transfer(hUSB->transferRecv); - libusb_free_transfer(hUSB->transferSend); -#else - if (hUSB->bulkIn > 0) { - close(hUSB->bulkIn); - hUSB->bulkIn = 0; - } - if (hUSB->bulkOut > 0) { - close(hUSB->bulkOut); - hUSB->bulkOut = 0; - } -#endif - delete hSession->hUSB; - hSession->hUSB = nullptr; - } -} - -// work when libuv-handle at struct of HdcSession has all callback finished -void HdcSessionBase::FreeSessionFinally(uv_idle_t *handle) -{ - HSession hSession = (HSession)handle->data; - HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance; - if (hSession->uvRef > 0) { - return; - } - // Notify Server or Daemon, just UI or display commandline - thisClass->NotifyInstanceSessionFree(hSession, true); - // all hsession uv handle has been clear - thisClass->AdminSession(OP_REMOVE, hSession->sessionId, nullptr); - WRITE_LOG(LOG_DEBUG, "!!!FreeSessionFinally sessionId:%u finish", hSession->sessionId); - delete hSession; - hSession = nullptr; // fix CodeMars SetNullAfterFree issue - Base::TryCloseHandle((const uv_handle_t *)handle, Base::CloseIdleCallback); - --thisClass->sessionRef; -} - -// work when child-work thread finish -void HdcSessionBase::FreeSessionContinue(HSession hSession) -{ - auto closeSessionTCPHandle = [](uv_handle_t *handle) -> void { - HSession hSession = (HSession)handle->data; - --hSession->uvRef; - Base::TryCloseHandle((uv_handle_t *)handle); - }; - if (CONN_TCP == hSession->connType) { - // Turn off TCP to prevent continuing writing - Base::TryCloseHandle((uv_handle_t *)&hSession->hWorkTCP, true, closeSessionTCPHandle); - } - hSession->availTailIndex = 0; - if (hSession->ioBuf) { - delete[] hSession->ioBuf; - hSession->ioBuf = nullptr; - } - Base::TryCloseHandle((uv_handle_t *)&hSession->ctrlPipe[STREAM_MAIN], true, closeSessionTCPHandle); - Base::TryCloseHandle((uv_handle_t *)&hSession->dataPipe[STREAM_MAIN], true, closeSessionTCPHandle); - delete hSession->mapTask; - HdcAuth::FreeKey(!hSession->serverOrDaemon, hSession->listKey); - delete hSession->listKey; // to clear - FreeSessionByConnectType(hSession); - // finish - Base::IdleUvTask(&loopMain, hSession, FreeSessionFinally); -} - -void HdcSessionBase::FreeSessionOpeate(uv_timer_t *handle) -{ - HSession hSession = (HSession)handle->data; - HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance; - if (hSession->sendRef > 0) { - return; - } -#ifdef HDC_HOST - if (hSession->hUSB != nullptr && (!hSession->hUSB->recvIOComplete || !hSession->hUSB->sendIOComplete)) { - return; - } -#endif - // wait workthread to free - if (hSession->ctrlPipe[STREAM_WORK].loop) { - auto ctrl = BuildCtrlString(SP_STOP_SESSION, 0, nullptr, 0); - Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); - WRITE_LOG(LOG_DEBUG, "FreeSession, send workthread fo free. sessionId:%u", hSession->sessionId); - auto callbackCheckFreeSessionContinue = [](uv_timer_t *handle) -> void { - HSession hSession = (HSession)handle->data; - HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance; - if (!hSession->childCleared) { - return; - } - Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback); - thisClass->FreeSessionContinue(hSession); - }; - Base::TimerUvTask(&thisClass->loopMain, hSession, callbackCheckFreeSessionContinue); - } else { - thisClass->FreeSessionContinue(hSession); - } - Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback); -} - -void HdcSessionBase::FreeSession(const uint32_t sessionId) -{ - HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr); - if (!hSession) { - return; - } - if (hSession->hWorkThread != uv_thread_self()) { - PushAsyncMessage(hSession->sessionId, ASYNC_FREE_SESSION, nullptr, 0); - return; - } - if (hSession->isDead) { - return; - } - hSession->isDead = true; - Base::TimerUvTask(&loopMain, hSession, FreeSessionOpeate); - NotifyInstanceSessionFree(hSession, false); - WRITE_LOG(LOG_DEBUG, "FreeSession sessionId:%u sendref:%u", hSession->sessionId, uint16_t(hSession->sendRef)); -} - -HSession HdcSessionBase::AdminSession(const uint8_t op, const uint32_t sessionId, HSession hInput) -{ - HSession hRet = nullptr; - switch (op) { - case OP_ADD: - uv_rwlock_wrlock(&lockMapSession); - mapSession[sessionId] = hInput; - uv_rwlock_wrunlock(&lockMapSession); - break; - case OP_REMOVE: - uv_rwlock_wrlock(&lockMapSession); - mapSession.erase(sessionId); - uv_rwlock_wrunlock(&lockMapSession); - break; - case OP_QUERY: - uv_rwlock_rdlock(&lockMapSession); - if (mapSession.count(sessionId)) { - hRet = mapSession[sessionId]; - } - uv_rwlock_rdunlock(&lockMapSession); - break; - case OP_UPDATE: - uv_rwlock_wrlock(&lockMapSession); - // remove old - mapSession.erase(sessionId); - mapSession[hInput->sessionId] = hInput; - uv_rwlock_wrunlock(&lockMapSession); - break; - default: - break; - } - return hRet; -} - -// All in the corresponding sub-thread, no need locks -HTaskInfo HdcSessionBase::AdminTask(const uint8_t op, HSession hSession, const uint32_t channelId, HTaskInfo hInput) -{ - HTaskInfo hRet = nullptr; - map &mapTask = *hSession->mapTask; - switch (op) { - case OP_ADD: - mapTask[channelId] = hInput; - break; - case OP_REMOVE: - mapTask.erase(channelId); - break; - case OP_QUERY: - if (mapTask.count(channelId)) { - hRet = mapTask[channelId]; - } - break; - default: - break; - } - return hRet; -} - -int HdcSessionBase::SendByProtocol(HSession hSession, uint8_t *bufPtr, const int bufLen) -{ - if (hSession->isDead) { - return ERR_SESSION_NOFOUND; - } - int ret = 0; - ++hSession->sendRef; - switch (hSession->connType) { - case CONN_TCP: { - if (hSession->hWorkThread == uv_thread_self()) { - ret = Base::SendToStreamEx((uv_stream_t *)&hSession->hWorkTCP, bufPtr, bufLen, nullptr, - (void *)FinishWriteSessionTCP, bufPtr); - } else if (hSession->hWorkChildThread == uv_thread_self()) { - ret = Base::SendToStreamEx((uv_stream_t *)&hSession->hChildWorkTCP, bufPtr, bufLen, nullptr, - (void *)FinishWriteSessionTCP, bufPtr); - } else { - WRITE_LOG(LOG_FATAL, "SendByProtocol uncontrol send"); - ret = ERR_API_FAIL; - } - break; - } - case CONN_USB: { - HdcUSBBase *pUSB = ((HdcUSBBase *)hSession->classModule); - ret = pUSB->SendUSBBlock(hSession, bufPtr, bufLen); - delete[] bufPtr; - break; - } - default: - break; - } - return ret; -} - -int HdcSessionBase::Send(const uint32_t sessionId, const uint32_t channelId, const uint16_t commandFlag, - const uint8_t *data, const int dataSize) -{ - HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr); - if (!hSession) { - WRITE_LOG(LOG_DEBUG, "Send to offline device, drop it, sessionId:%u", sessionId); - return ERR_SESSION_NOFOUND; - } - PayloadProtect protectBuf; // noneed convert to big-endian - protectBuf.channelId = channelId; - protectBuf.commandFlag = commandFlag; - protectBuf.checkSum = (ENABLE_IO_CHECKSUM && dataSize > 0) ? Base::CalcCheckSum(data, dataSize) : 0; - protectBuf.vCode = payloadProtectStaticVcode; - string s = SerialStruct::SerializeToString(protectBuf); - // reserve for encrypt here - // xx-encrypt - - PayloadHead payloadHead; // need convert to big-endian - Base::ZeroStruct(payloadHead); - payloadHead.flag[0] = PACKET_FLAG.at(0); - payloadHead.flag[1] = PACKET_FLAG.at(1); - payloadHead.protocolVer = VER_PROTOCOL; - payloadHead.headSize = htons(s.size()); - payloadHead.dataSize = htonl(dataSize); - int finalBufSize = sizeof(PayloadHead) + s.size() + dataSize; - uint8_t *finayBuf = new uint8_t[finalBufSize](); - if (finayBuf == nullptr) { - return ERR_BUF_ALLOC; - } - bool bufRet = false; - do { - if (memcpy_s(finayBuf, sizeof(PayloadHead), reinterpret_cast(&payloadHead), sizeof(PayloadHead))) { - break; - } - if (memcpy_s(finayBuf + sizeof(PayloadHead), s.size(), - reinterpret_cast(const_cast(s.c_str())), s.size())) { - break; - } - if (dataSize > 0 && memcpy_s(finayBuf + sizeof(PayloadHead) + s.size(), dataSize, data, dataSize)) { - break; - } - bufRet = true; - } while (false); - if (!bufRet) { - delete[] finayBuf; - return ERR_BUF_COPY; - } - return SendByProtocol(hSession, finayBuf, finalBufSize); -} - -int HdcSessionBase::DecryptPayload(HSession hSession, PayloadHead *payloadHeadBe, uint8_t *encBuf) -{ - PayloadProtect protectBuf; - Base::ZeroStruct(protectBuf); - uint16_t headSize = ntohs(payloadHeadBe->headSize); - int dataSize = ntohl(payloadHeadBe->dataSize); - string encString(reinterpret_cast(encBuf), headSize); - SerialStruct::ParseFromString(protectBuf, encString); - if (protectBuf.vCode != payloadProtectStaticVcode) { - WRITE_LOG(LOG_FATAL, "Session recv static vcode failed"); - return ERR_BUF_CHECK; - } - uint8_t *data = encBuf + headSize; - if (protectBuf.checkSum != 0 && (protectBuf.checkSum != Base::CalcCheckSum(data, dataSize))) { - WRITE_LOG(LOG_FATAL, "Session recv CalcCheckSum failed"); - return ERR_BUF_CHECK; - } - if (!FetchCommand(hSession, protectBuf.channelId, protectBuf.commandFlag, data, dataSize)) { - WRITE_LOG(LOG_WARN, "FetchCommand failed"); - return ERR_GENERIC; - } - return RET_SUCCESS; -} - -int HdcSessionBase::OnRead(HSession hSession, uint8_t *bufPtr, const int bufLen) -{ - int ret = ERR_GENERIC; - if (memcmp(bufPtr, PACKET_FLAG.c_str(), PACKET_FLAG.size())) { - return ERR_BUF_CHECK; - } - struct PayloadHead *payloadHead = (struct PayloadHead *)bufPtr; - int tobeReadLen = ntohl(payloadHead->dataSize) + ntohs(payloadHead->headSize); - int packetHeadSize = sizeof(struct PayloadHead); - if (tobeReadLen <= 0 || (uint32_t)tobeReadLen > HDC_BUF_MAX_BYTES) { - // max 1G - return ERR_BUF_CHECK; - } - if (bufLen - packetHeadSize < tobeReadLen) { - return 0; - } - if (DecryptPayload(hSession, payloadHead, bufPtr + packetHeadSize)) { - return ERR_BUF_CHECK; - } - ret = packetHeadSize + tobeReadLen; - return ret; -} - -// Returns <0 error;> 0 receives the number of bytes; 0 untreated -int HdcSessionBase::FetchIOBuf(HSession hSession, uint8_t *ioBuf, int read) -{ - HdcSessionBase *ptrConnect = (HdcSessionBase *)hSession->classInstance; - int indexBuf = 0; - int childRet = 0; - if (read < 0) { - return ERR_IO_FAIL; - } - hSession->availTailIndex += read; - while (!hSession->isDead && hSession->availTailIndex > static_cast(sizeof(PayloadHead))) { - childRet = ptrConnect->OnRead(hSession, ioBuf + indexBuf, hSession->availTailIndex); - if (childRet > 0) { - hSession->availTailIndex -= childRet; - indexBuf += childRet; - } else if (childRet == 0) { - // Not enough a IO - break; - } else { - // <0 - hSession->availTailIndex = 0; // Preventing malicious data packages - indexBuf = ERR_BUF_SIZE; - break; - } - // It may be multi-time IO to merge in a BUF, need to loop processing - } - if (indexBuf > 0 && hSession->availTailIndex > 0) { - memmove_s(hSession->ioBuf, hSession->bufSize, hSession->ioBuf + indexBuf, hSession->availTailIndex); - uint8_t *bufToZero = (uint8_t *)(hSession->ioBuf + hSession->availTailIndex); - Base::ZeroBuf(bufToZero, hSession->bufSize - hSession->availTailIndex); - } - return indexBuf; -} - -void HdcSessionBase::AllocCallback(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) -{ - HSession context = (HSession)handle->data; - Base::ReallocBuf(&context->ioBuf, &context->bufSize, context->availTailIndex, sizeWanted); - buf->base = (char *)context->ioBuf + context->availTailIndex; - buf->len = context->bufSize - context->availTailIndex - 1; // 16Bytes are retained to prevent memory sticking - assert(buf->len >= 0); -} - -void HdcSessionBase::FinishWriteSessionTCP(uv_write_t *req, int status) -{ - HSession hSession = (HSession)req->handle->data; - --hSession->sendRef; - HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance; - if (status < 0) { - Base::TryCloseHandle((uv_handle_t *)req->handle); - if (!hSession->isDead && !hSession->sendRef) { - WRITE_LOG(LOG_DEBUG, "FinishWriteSessionTCP freesession :%p", hSession); - thisClass->FreeSession(hSession->sessionId); - } - } - delete[]((uint8_t *)req->data); - delete req; -} - -bool HdcSessionBase::DispatchSessionThreadCommand(uv_stream_t *uvpipe, HSession hSession, const uint8_t *baseBuf, - const int bytesIO) -{ - bool ret = true; - uint8_t flag = *(uint8_t *)baseBuf; - - switch (flag) { - case SP_JDWP_NEWFD: { - JdwpNewFileDescriptor(baseBuf, bytesIO); - break; - } - default: - WRITE_LOG(LOG_WARN, "Not support session command"); - break; - } - return ret; -} - -void HdcSessionBase::ReadCtrlFromSession(uv_stream_t *uvpipe, ssize_t nread, const uv_buf_t *buf) -{ - HSession hSession = (HSession)uvpipe->data; - HdcSessionBase *hSessionBase = (HdcSessionBase *)hSession->classInstance; - while (true) { - if (nread < 0) { - WRITE_LOG(LOG_DEBUG, "SessionCtrl failed,%s", uv_strerror(nread)); - break; - } - if (nread > 64) { // 64 : max length - WRITE_LOG(LOG_WARN, "HdcSessionBase read overlap data"); - break; - } - // only one command, no need to split command from stream - // if add more commands, consider the format command - hSessionBase->DispatchSessionThreadCommand(uvpipe, hSession, (uint8_t *)buf->base, nread); - break; - } - delete[] buf->base; -} - -bool HdcSessionBase::WorkThreadStartSession(HSession hSession) -{ - bool regOK = false; - int childRet = 0; - if (hSession->connType == CONN_TCP) { - HdcTCPBase *pTCPBase = (HdcTCPBase *)hSession->classModule; - hSession->hChildWorkTCP.data = hSession; - if ((childRet = uv_tcp_init(&hSession->childLoop, &hSession->hChildWorkTCP)) < 0) { - WRITE_LOG(LOG_DEBUG, "HdcSessionBase SessionCtrl failed 1"); - return false; - } - if ((childRet = uv_tcp_open(&hSession->hChildWorkTCP, hSession->fdChildWorkTCP)) < 0) { - WRITE_LOG(LOG_DEBUG, "SessionCtrl failed 2,fd:%d,str:%s", hSession->fdChildWorkTCP, uv_strerror(childRet)); - return false; - } - Base::SetTcpOptions((uv_tcp_t *)&hSession->hChildWorkTCP); - uv_read_start((uv_stream_t *)&hSession->hChildWorkTCP, AllocCallback, pTCPBase->ReadStream); - regOK = true; - } else { // USB - HdcUSBBase *pUSBBase = (HdcUSBBase *)hSession->classModule; - WRITE_LOG(LOG_DEBUG, "USB ReadyForWorkThread"); - regOK = pUSBBase->ReadyForWorkThread(hSession); - } - if (regOK && hSession->serverOrDaemon) { - // session handshake step1 - SessionHandShake handshake; - Base::ZeroStruct(handshake); - handshake.banner = HANDSHAKE_MESSAGE; - handshake.sessionId = hSession->sessionId; - handshake.connectKey = hSession->connectKey; - handshake.authType = AUTH_NONE; - string hs = SerialStruct::SerializeToString(handshake); - Send(hSession->sessionId, 0, CMD_KERNEL_HANDSHAKE, (uint8_t *)hs.c_str(), hs.size()); - } - return regOK; -} - -vector HdcSessionBase::BuildCtrlString(InnerCtrlCommand command, uint32_t channelId, uint8_t *data, - int dataSize) -{ - vector ret; - while (true) { - if (dataSize > BUF_SIZE_MICRO) { - break; - } - CtrlStruct ctrl; - Base::ZeroStruct(ctrl); - ctrl.command = command; - ctrl.channelId = channelId; - ctrl.dataSize = dataSize; - if (dataSize > 0 && data != nullptr && memcpy_s(ctrl.data, sizeof(ctrl.data), data, dataSize) != EOK) { - break; - } - uint8_t *buf = reinterpret_cast(&ctrl); - ret.insert(ret.end(), buf, buf + sizeof(CtrlStruct)); - break; - } - return ret; -} - -bool HdcSessionBase::DispatchMainThreadCommand(HSession hSession, const CtrlStruct *ctrl) -{ - bool ret = true; - uint32_t channelId = ctrl->channelId; // if send not set, it is zero - switch (ctrl->command) { - case SP_START_SESSION: { - WRITE_LOG(LOG_DEBUG, "Dispatch MainThreadCommand START_SESSION sessionId:%u instance:%s", - hSession->sessionId, hSession->serverOrDaemon ? "server" : "daemon"); - ret = WorkThreadStartSession(hSession); - break; - } - case SP_STOP_SESSION: { - WRITE_LOG(LOG_DEBUG, "Dispatch MainThreadCommand STOP_SESSION sessionId:%u", hSession->sessionId); - auto closeSessionChildThreadTCPHandle = [](uv_handle_t *handle) -> void { - HSession hSession = (HSession)handle->data; - Base::TryCloseHandle((uv_handle_t *)handle); - if (--hSession->uvChildRef == 0) { - uv_stop(&hSession->childLoop); - }; - }; - hSession->uvChildRef += 2; - if (hSession->hChildWorkTCP.loop) { // maybe not use it - ++hSession->uvChildRef; - Base::TryCloseHandle((uv_handle_t *)&hSession->hChildWorkTCP, true, closeSessionChildThreadTCPHandle); - } - Base::TryCloseHandle((uv_handle_t *)&hSession->ctrlPipe[STREAM_WORK], true, - closeSessionChildThreadTCPHandle); - Base::TryCloseHandle((uv_handle_t *)&hSession->dataPipe[STREAM_WORK], true, - closeSessionChildThreadTCPHandle); - break; - } - case SP_ATTACH_CHANNEL: { - if (!serverOrDaemon) { - break; // Only Server has this feature - } - AttachChannel(hSession, channelId); - break; - } - case SP_DEATCH_CHANNEL: { - if (!serverOrDaemon) { - break; // Only Server has this feature - } - DeatchChannel(hSession, channelId); - break; - } - default: - WRITE_LOG(LOG_WARN, "Not support main command"); - ret = false; - break; - } - return ret; -} - -// Several bytes of control instructions, generally do not stick -void HdcSessionBase::ReadCtrlFromMain(uv_stream_t *uvpipe, ssize_t nread, const uv_buf_t *buf) -{ - HSession hSession = (HSession)uvpipe->data; - HdcSessionBase *hSessionBase = (HdcSessionBase *)hSession->classInstance; - int formatCommandSize = sizeof(CtrlStruct); - int index = 0; - bool ret = true; - while (true) { - if (nread < 0) { - WRITE_LOG(LOG_DEBUG, "SessionCtrl failed,%s", uv_strerror(nread)); - ret = false; - break; - } - if (nread % formatCommandSize != 0) { - WRITE_LOG(LOG_FATAL, "ReadCtrlFromMain size failed, nread == %d", nread); - ret = false; - break; - } - CtrlStruct *ctrl = reinterpret_cast(buf->base + index); - if (!(ret = hSessionBase->DispatchMainThreadCommand(hSession, ctrl))) { - ret = false; - break; - } - index += sizeof(CtrlStruct); - if (index >= nread) { - break; - } - } - delete[] buf->base; -} - -void HdcSessionBase::ReChildLoopForSessionClear(HSession hSession) -{ - // Restart loop close task - ClearOwnTasks(hSession, 0); - auto clearTaskForSessionFinish = [](uv_idle_t *handle) -> void { - HSession hSession = (HSession)handle->data; - for (auto v : *hSession->mapTask) { - HTaskInfo hTask = (HTaskInfo)v.second; - if (!hTask->taskFree) - return; - } - // all task has been free - uv_close((uv_handle_t *)handle, Base::CloseIdleCallback); - uv_stop(&hSession->childLoop); // stop ReChildLoopForSessionClear pendding - }; - Base::IdleUvTask(&hSession->childLoop, hSession, clearTaskForSessionFinish); - uv_run(&hSession->childLoop, UV_RUN_DEFAULT); - // clear - Base::TryCloseLoop(&hSession->childLoop, "Session childUV"); -} - -void HdcSessionBase::SessionWorkThread(uv_work_t *arg) -{ - int childRet = 0; - HSession hSession = (HSession)arg->data; - HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance; - uv_loop_init(&hSession->childLoop); - hSession->hWorkChildThread = uv_thread_self(); - if ((childRet = uv_tcp_init(&hSession->childLoop, &hSession->ctrlPipe[STREAM_WORK])) < 0) { - WRITE_LOG(LOG_DEBUG, "SessionCtrl err1, %s", uv_strerror(childRet)); - } - if ((childRet = uv_tcp_open(&hSession->ctrlPipe[STREAM_WORK], hSession->ctrlFd[STREAM_WORK])) < 0) { - WRITE_LOG(LOG_DEBUG, "SessionCtrl err2, %s fd:%d", uv_strerror(childRet), hSession->ctrlFd[STREAM_WORK]); - } - uv_read_start((uv_stream_t *)&hSession->ctrlPipe[STREAM_WORK], Base::AllocBufferCallback, ReadCtrlFromMain); - WRITE_LOG(LOG_DEBUG, "!!!Workthread run begin, sessionId:%u instance:%s", hSession->sessionId, - thisClass->serverOrDaemon ? "server" : "daemon"); - uv_run(&hSession->childLoop, UV_RUN_DEFAULT); // work pendding - WRITE_LOG(LOG_DEBUG, "!!!Workthread run again, sessionId:%u", hSession->sessionId); - // main loop has exit - thisClass->ReChildLoopForSessionClear(hSession); // work pending again - hSession->childCleared = true; - WRITE_LOG(LOG_DEBUG, "!!!Workthread run finish, sessionId:%u workthread:%p", hSession->sessionId, uv_thread_self()); -} - -// clang-format off -void HdcSessionBase::LogMsg(const uint32_t sessionId, const uint32_t channelId, - MessageLevel level, const char *msg, ...) -// clang-format on -{ - va_list vaArgs; - va_start(vaArgs, msg); - string log = Base::StringFormat(msg, vaArgs); - va_end(vaArgs); - vector buf; - buf.push_back(level); - buf.insert(buf.end(), log.c_str(), log.c_str() + log.size()); - ServerCommand(sessionId, channelId, CMD_KERNEL_ECHO, buf.data(), buf.size()); -} - -// Heavy and time-consuming work was putted in the new thread to do, and does -// not occupy the main thread -bool HdcSessionBase::DispatchTaskData(HSession hSession, const uint32_t channelId, const uint16_t command, - uint8_t *payload, int payloadSize) -{ - bool ret = false; - while (true) { - HTaskInfo hTaskInfo = AdminTask(OP_QUERY, hSession, channelId, nullptr); - if (!hTaskInfo) { - WRITE_LOG(LOG_DEBUG, "New HTaskInfo"); - hTaskInfo = new TaskInformation(); - hTaskInfo->channelId = channelId; - hTaskInfo->sessionId = hSession->sessionId; - hTaskInfo->runLoop = &hSession->childLoop; - hTaskInfo->serverOrDaemon = serverOrDaemon; - } - if (hTaskInfo->taskStop) { - WRITE_LOG(LOG_DEBUG, "RedirectToTask jump stopped task:%d", channelId); - break; - } - if (hTaskInfo->taskFree) { - WRITE_LOG(LOG_DEBUG, "Jump delete HTaskInfo"); - break; - } - bool result = RedirectToTask(hTaskInfo, hSession, channelId, command, payload, payloadSize); - if (!hTaskInfo->hasInitial) { - AdminTask(OP_ADD, hSession, channelId, hTaskInfo); - hTaskInfo->hasInitial = true; - } - if (result) { - ret = true; - } - break; - } - return ret; -} - -void HdcSessionBase::PostStopInstanceMessage(bool restart) -{ - PushAsyncMessage(0, ASYNC_STOP_MAINLOOP, nullptr, 0); - WRITE_LOG(LOG_DEBUG, "StopDaemon has sended"); - wantRestart = restart; -} -} // namespace Hdc diff --git a/services/flashd/common/session.h b/services/flashd/common/session.h deleted file mode 100755 index fe580717..00000000 --- a/services/flashd/common/session.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_SESSION_H -#define HDC_SESSION_H -#include "common.h" - -namespace Hdc { -enum TaskType { TYPE_UNITY, TYPE_SHELL, TASK_FILE, TASK_FORWARD, TASK_APP, TASK_UPDATER }; - -class HdcSessionBase { -public: - enum AuthType { AUTH_NONE, AUTH_TOKEN, AUTH_SIGNATURE, AUTH_PUBLICKEY, AUTH_OK }; - struct SessionHandShake { - string banner; // must first index - // auth none - uint8_t authType; - uint32_t sessionId; - string connectKey; - string buf; - }; - struct CtrlStruct { - InnerCtrlCommand command; - uint32_t channelId; - uint8_t dataSize; - uint8_t data[BUF_SIZE_MICRO]; - }; - struct PayloadProtect { // reserve for encrypt and decrypt - uint32_t channelId; - uint32_t commandFlag; - uint8_t checkSum; // enable it will be lose about 20% speed - uint8_t vCode; - }; - - HdcSessionBase(bool serverOrDaemonIn); - virtual ~HdcSessionBase(); - virtual void AttachChannel(HSession hSession, const uint32_t channelId) {}; - virtual void DeatchChannel(HSession hSession, const uint32_t channelId) {}; - virtual bool RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, - const uint16_t command, uint8_t *payload, const int payloadSize) - { - return true; - } - virtual void NotifyInstanceSessionFree(HSession hSession, bool freeOrClear) - { - } - // Thread security interface for global stop programs - void PostStopInstanceMessage(bool restart = false); - void ReMainLoopForInstanceClear(); - // server, Two parameters in front of call can be empty - void LogMsg(const uint32_t sessionId, const uint32_t channelId, MessageLevel level, const char *msg, ...); - static void AllocCallback(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf); - static void MainAsyncCallback(uv_async_t *handle); - static void FinishWriteSessionTCP(uv_write_t *req, int status); - static void SessionWorkThread(uv_work_t *arg); - static void ReadCtrlFromMain(uv_stream_t *uvpipe, ssize_t nread, const uv_buf_t *buf); - static void ReadCtrlFromSession(uv_stream_t *uvpipe, ssize_t nread, const uv_buf_t *buf); - HSession QueryUSBDeviceRegister(void *pDev, int busIDIn, int devIDIn); - HSession MallocSession(bool serverOrDaemon, const ConnType connType, void *classModule, uint32_t sessionId = 0); - void FreeSession(const uint32_t sessionId); - void WorkerPendding(); - int OnRead(HSession hSession, uint8_t *bufPtr, const int bufLen); - int Send(const uint32_t sessionId, const uint32_t channelId, const uint16_t commandFlag, const uint8_t *data, - const int dataSize); - int SendByProtocol(HSession hSession, uint8_t *bufPtr, const int bufLen); - HSession AdminSession(const uint8_t op, const uint32_t sessionId, HSession hInput); - int FetchIOBuf(HSession hSession, uint8_t *ioBuf, int read); - void PushAsyncMessage(const uint32_t sessionId, const uint8_t method, const void *data, const int dataSize); - HTaskInfo AdminTask(const uint8_t op, HSession hSession, const uint32_t channelId, HTaskInfo hInput); - bool DispatchTaskData(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, - int payloadSize); - void EnumUSBDeviceRegister(void (*pCallBack)(HSession hSession)); - void ClearOwnTasks(HSession hSession, const uint32_t channelIDInput); - virtual bool FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, - int payloadSize) - { - return true; - } - virtual bool ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, - uint8_t *bufPtr, const int size) - { - return true; - } - virtual bool RemoveInstanceTask(const uint8_t op, HTaskInfo hTask) - { - return true; - } - bool WantRestart() - { - return wantRestart; - } - static vector BuildCtrlString(InnerCtrlCommand command, uint32_t channelId, uint8_t *data, int dataSize); - uv_loop_t loopMain; - bool serverOrDaemon; - uv_async_t asyncMainLoop; - uv_rwlock_t mainAsync; - list lstMainThreadOP; - void *ctxUSB; - -protected: - struct PayloadHead { - uint8_t flag[2]; - uint8_t reserve[2]; // encrypt'flag or others options - uint8_t protocolVer; - uint16_t headSize; - uint32_t dataSize; - } __attribute__((packed)); - void ClearSessions(); - virtual void JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO) - { - } - // must be define in haderfile, cannot in cpp file - template - bool TaskCommandDispatch(HTaskInfo hTaskInfo, uint8_t taskType, const uint16_t command, uint8_t *payload, - const int payloadSize) - { - bool ret = true; - T *ptrTask = nullptr; - if (!hTaskInfo->hasInitial) { - ptrTask = new T(hTaskInfo); - hTaskInfo->taskClass = ptrTask; - hTaskInfo->taskType = taskType; - } else { - ptrTask = (T *)hTaskInfo->taskClass; - } - if (!ptrTask->CommandDispatch(command, payload, payloadSize)) { - ptrTask->TaskFinish(); - } - return ret; - } - template bool DoTaskRemove(HTaskInfo hTaskInfo, const uint8_t op) - { - T *ptrTask = (T *)hTaskInfo->taskClass; - if (OP_CLEAR == op) { - ptrTask->StopTask(); - } else if (OP_REMOVE == op) { - if (!ptrTask->ReadyForRelease()) { - return false; - } - delete ptrTask; - } - return true; - } - bool wantRestart; - -private: - virtual void ClearInstanceResource() - { - } - int DecryptPayload(HSession hSession, PayloadHead *payloadHeadBe, uint8_t *encBuf); - bool DispatchMainThreadCommand(HSession hSession, const CtrlStruct *ctrl); - bool DispatchSessionThreadCommand(uv_stream_t *uvpipe, HSession hSession, const uint8_t *baseBuf, - const int bytesIO); - bool BeginRemoveTask(HTaskInfo hTask); - bool TryRemoveTask(HTaskInfo hTask); - void ReChildLoopForSessionClear(HSession hSession); - void FreeSessionContinue(HSession hSession); - static void FreeSessionFinally(uv_idle_t *handle); - static void AsyncMainLoopTask(uv_idle_t *handle); - static void FreeSessionOpeate(uv_timer_t *handle); - int MallocSessionByConnectType(HSession hSession); - void FreeSessionByConnectType(HSession hSession); - bool WorkThreadStartSession(HSession hSession); - uint32_t GetSessionPseudoUid(); - - map mapSession; - uv_rwlock_t lockMapSession; - std::atomic sessionRef = 0; - const uint8_t payloadProtectStaticVcode = 0x09; -}; -} // namespace Hdc -#endif \ No newline at end of file diff --git a/services/flashd/common/task.cpp b/services/flashd/common/task.cpp deleted file mode 100755 index 11461858..00000000 --- a/services/flashd/common/task.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "task.h" - -namespace Hdc { -// ----------------------------------------------------------- -// notice!!! The constructor is called at the Child thread, so in addition to initialization, do not excess actions, if -// destructor is required, please clean up in the subclasses. -HdcTaskBase::HdcTaskBase(HTaskInfo hTaskInfo) -{ - taskInfo = hTaskInfo; - loopTask = hTaskInfo->runLoop; - clsSession = hTaskInfo->ownerSessionClass; - childReady = false; - singalStop = false; - refCount = 0; -} - -HdcTaskBase::~HdcTaskBase() -{ - WRITE_LOG(LOG_DEBUG, "~HdcTaskBase"); -} - -bool HdcTaskBase::ReadyForRelease() -{ - return refCount == 0; -} - -// Only the Task work thread call is allowed to use only when Workfortask returns FALSE. -void HdcTaskBase::TaskFinish() -{ - uint8_t count = 1; - SendToAnother(CMD_KERNEL_CHANNEL_CLOSE, &count, 1); - WRITE_LOG(LOG_DEBUG, "HdcTaskBase::TaskFinish notify"); -} - -bool HdcTaskBase::SendToAnother(const uint16_t command, uint8_t *bufPtr, const int size) -{ - if (singalStop) { - return false; - } - HdcSessionBase *sessionBase = reinterpret_cast(taskInfo->ownerSessionClass); - return sessionBase->Send(taskInfo->sessionId, taskInfo->channelId, command, bufPtr, size) > 0; -} - -void HdcTaskBase::LogMsg(MessageLevel level, const char *msg, ...) -{ - va_list vaArgs; - va_start(vaArgs, msg); - string log = Base::StringFormat(msg, vaArgs); - va_end(vaArgs); - HdcSessionBase *sessionBase = reinterpret_cast(clsSession); - sessionBase->LogMsg(taskInfo->sessionId, taskInfo->channelId, level, log.c_str()); -} - -void HdcTaskBase::SendRawData(uint8_t *bufPtr, const int size) -{ - HdcSessionBase *sessionBase = (HdcSessionBase *)clsSession; - sessionBase->ServerCommand(taskInfo->sessionId, - taskInfo->channelId, CMD_KERNEL_ECHO_RAW, bufPtr, size); -} - -bool HdcTaskBase::ServerCommand(const uint16_t command, uint8_t *bufPtr, const int size) -{ - HdcSessionBase *hSession = (HdcSessionBase *)taskInfo->ownerSessionClass; - return hSession->ServerCommand(taskInfo->sessionId, taskInfo->channelId, command, bufPtr, size); -} - -// cross thread -int HdcTaskBase::ThreadCtrlCommunicate(const uint8_t *bufPtr, const int size) -{ - HdcSessionBase *sessionBase = (HdcSessionBase *)taskInfo->ownerSessionClass; - HSession hSession = sessionBase->AdminSession(OP_QUERY, taskInfo->sessionId, nullptr); - if (!hSession) { - return -1; - } - uv_stream_t *handleStream = nullptr; - if (uv_thread_self() == hSession->hWorkThread) { - handleStream = (uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN]; - } else if (uv_thread_self() == hSession->hWorkChildThread) { - handleStream = (uv_stream_t *)&hSession->ctrlPipe[STREAM_WORK]; - } else { - return ERR_GENERIC; - } - return Base::SendToStream(handleStream, bufPtr, size); -} -} \ No newline at end of file diff --git a/services/flashd/common/task.h b/services/flashd/common/task.h deleted file mode 100755 index 0d0d5a67..00000000 --- a/services/flashd/common/task.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_TASK_H -#define HDC_TASK_H -#include "common.h" - -namespace Hdc { -// Only allow inheritance -class HdcTaskBase { -public: - HdcTaskBase(HTaskInfo hTaskInfo); - virtual ~HdcTaskBase(); - virtual bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) - { - return true; - } - // The following two functions are used to clean up. To ensure that subclasses are safely cleaned, each subclass is - // directly instantified of these two virtual functions. - virtual void StopTask() - { - singalStop = true; // default opeartion - } - bool ReadyForRelease(); - void TaskFinish(); - void SendRawData(uint8_t *bufPtr, const int size); -protected: // D/S==daemon/server - bool SendToAnother(const uint16_t command, uint8_t *bufPtr, const int size); // D / S corresponds to the Task class - void LogMsg(MessageLevel level, const char *msg, ...); // D / S log Send to Client - bool ServerCommand(const uint16_t command, uint8_t *bufPtr, const int size); // D / s command is sent to Server - int ThreadCtrlCommunicate(const uint8_t *bufPtr, const int size); // main thread and session thread - - uv_loop_t *loopTask; // childuv pointer - void *clsSession; - // Task has stopped running. When Task is officially running, set True as soon as possible, set FALSE after the last - // step, when the value is false, the Task class will be destructured as soon as possible - bool childReady; // Subcompulents have been prepared - bool singalStop; // Request stop signal - HTaskInfo taskInfo; - uint32_t refCount; - -private: -}; -} // namespace Hdc - -#endif \ No newline at end of file diff --git a/services/flashd/common/tcp.cpp b/services/flashd/common/tcp.cpp deleted file mode 100755 index 18f267c7..00000000 --- a/services/flashd/common/tcp.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "tcp.h" - -namespace Hdc { -HdcTCPBase::HdcTCPBase(const bool serverOrDaemonIn, void *ptrMainBase) -{ - // Calling the initialization - InitialChildClass(serverOrDaemonIn, ptrMainBase); -} - -HdcTCPBase::~HdcTCPBase() -{ -} - -// Subclasses must be explicitly called -void HdcTCPBase::InitialChildClass(const bool serverOrDaemonIn, void *ptrMainBase) -{ - serverOrDaemon = serverOrDaemonIn; - clsMainBase = ptrMainBase; -} - -void HdcTCPBase::RecvUDP(uv_udp_t *handle, ssize_t nread, const uv_buf_t *rcvbuf, const struct sockaddr *addr, - unsigned flags) -{ - while (true) { - HdcTCPBase *thisClass = (HdcTCPBase *)handle->data; - if (nread <= 0) { - // ==0 finish;<0 error - break; - } - WRITE_LOG(LOG_DEBUG, "RecvUDP %s", rcvbuf->base); - if (strncmp(rcvbuf->base, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) { - break; - } - thisClass->RecvUDPEntry(addr, handle, rcvbuf); - break; - } - delete[] rcvbuf->base; -} - -void HdcTCPBase::AllocStreamUDP(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) -{ - int bufLen = BUF_SIZE_DEFAULT; - char *pRecvBuf = (char *)new uint8_t[bufLen](); - if (!pRecvBuf) { - return; - } - buf->base = pRecvBuf; - buf->len = bufLen; -} - -void HdcTCPBase::SendUDPFinish(uv_udp_send_t *req, int status) -{ - delete req; -} - -void HdcTCPBase::ReadStream(uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) -{ - HSession hSession = (HSession)tcp->data; - HdcTCPBase *thisClass = (HdcTCPBase *)hSession->classModule; - HdcSessionBase *hSessionBase = (HdcSessionBase *)thisClass->clsMainBase; - bool ret = false; - while (true) { - if (nread == UV_ENOBUFS) { - WRITE_LOG(LOG_DEBUG, "Session IOBuf max"); - break; - } else if (nread < 0) { - // I originally in the IO main thread, no need to send asynchronous messages, close the socket as soon as - // possible - WRITE_LOG(LOG_DEBUG, "HdcTCPBase::ReadStream < 0 %s", uv_strerror(nread)); - break; - } - if (hSessionBase->FetchIOBuf(hSession, hSession->ioBuf, nread) < 0) { - break; - } - ret = true; - break; - } - if (!ret) { - // The first time is closed first, prevent the write function from continuing to write - Base::TryCloseHandle(reinterpret_cast(tcp)); - hSessionBase->FreeSession(hSession->sessionId); - } -} -} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/common/tcp.h b/services/flashd/common/tcp.h deleted file mode 100755 index e7f32a27..00000000 --- a/services/flashd/common/tcp.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_TCP_H -#define HDC_TCP_H -#include "common.h" - -namespace Hdc { -class HdcTCPBase { -public: - HdcTCPBase(const bool serverOrDaemonIn, void *ptrMainBase); - virtual ~HdcTCPBase(); - static void ReadStream(uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf); - -protected: - virtual void RecvUDPEntry(const sockaddr *addrSrc, uv_udp_t *handle, const uv_buf_t *rcvbuf) - { - } - static void RecvUDP( - uv_udp_t *handle, ssize_t nread, const uv_buf_t *rcvbuf, const struct sockaddr *addr, unsigned flags); - static void SendUDPFinish(uv_udp_send_t *req, int status); - static void AllocStreamUDP(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf); - - void *clsMainBase; - bool serverOrDaemon; - -private: - void InitialChildClass(const bool serverOrDaemonIn, void *ptrMainBase); -}; -} // namespace Hdc - -#endif \ No newline at end of file diff --git a/services/flashd/common/transfer.cpp b/services/flashd/common/transfer.cpp deleted file mode 100755 index fc983cfd..00000000 --- a/services/flashd/common/transfer.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "transfer.h" -#include "serial_struct.h" -#include -#ifdef HARMONY_PROJECT -#include -#endif - -namespace Hdc { -constexpr uint64_t HDC_TIME_CONVERT_BASE = 1000000000; - -HdcTransferBase::HdcTransferBase(HTaskInfo hTaskInfo) - : HdcTaskBase(hTaskInfo) -{ - ResetCtx(&ctxNow, true); - commandBegin = 0; - commandData = 0; -} - -HdcTransferBase::~HdcTransferBase() -{ - WRITE_LOG(LOG_DEBUG, "~HdcTransferBase"); -}; - -bool HdcTransferBase::ResetCtx(CtxFile *context, bool full) -{ - context->fsOpenReq.data = context; - context->fsCloseReq.data = context; - context->thisClass = this; - context->closeNotify = false; - context->indexIO = 0; - context->loop = loopTask; - context->cb = OnFileIO; - if (full) { - context->localPath = ""; - context->remotePath = ""; - context->transferBegin = 0; - context->taskQueue.clear(); - Base::ZeroStruct(ctxNow.transferConfig); - } - return true; -} - -int HdcTransferBase::SimpleFileIO(CtxFile *context, uint64_t index, uint8_t *sendBuf, int bytes) -{ - // The first 8 bytes file offset - uint8_t *buf = new uint8_t[bytes](); - CtxFileIO *ioContext = new CtxFileIO(); - bool ret = false; - while (true) { - if (!buf || !ioContext || bytes < 0) { - break; - } - uv_fs_t *req = &ioContext->fs; - ioContext->bufIO = buf; - ioContext->context = context; - req->data = ioContext; - ++refCount; - if (context->master) { // master just read, and slave just write.when master/read, sendBuf can be nullptr - uv_buf_t iov = uv_buf_init(reinterpret_cast(buf), bytes); - uv_fs_read(context->loop, req, context->fsOpenReq.result, &iov, 1, index, context->cb); - } else { - // The US_FS_WRITE here must be brought into the actual file offset, which cannot be incorporated with local - // accumulated index because UV_FS_WRITE will be executed multiple times and then trigger a callback. - if (bytes > 0 && memcpy_s(ioContext->bufIO, bytes, sendBuf, bytes) != EOK) { - break; - } - uv_buf_t iov = uv_buf_init(reinterpret_cast(ioContext->bufIO), bytes); - uv_fs_write(context->loop, req, context->fsOpenReq.result, &iov, 1, index, context->cb); - } - ret = true; - break; - } - if (!ret) { - WRITE_LOG(LOG_WARN, "SimpleFileIO error"); - if (buf != nullptr) { - delete[] buf; - buf = nullptr; - } - if (ioContext != nullptr) { - delete ioContext; - ioContext = nullptr; - } - return -1; - } - return bytes; -} - -void HdcTransferBase::OnFileClose(uv_fs_t *req) -{ - uv_fs_req_cleanup(req); - CtxFile *context = (CtxFile *)req->data; - HdcTransferBase *thisClass = (HdcTransferBase *)context->thisClass; - if (context->closeNotify) { - // close-step2 - thisClass->WhenTransferFinish(context); - } - --thisClass->refCount; - return; -} - -void HdcTransferBase::SetFileTime(CtxFile *context) -{ - if (!context->transferConfig.holdTimestamp) { - return; - } - if (!context->transferConfig.mtime) { - return; - } - uv_fs_t fs; - double aTimeSec = static_cast(context->transferConfig.atime) / HDC_TIME_CONVERT_BASE; - double mTimeSec = static_cast(context->transferConfig.mtime) / HDC_TIME_CONVERT_BASE; - uv_fs_futime(nullptr, &fs, context->fsOpenReq.result, aTimeSec, mTimeSec, nullptr); - uv_fs_req_cleanup(&fs); -} - -bool HdcTransferBase::SendIOPayload(CtxFile *context, int index, uint8_t *data, int dataSize) -{ - TransferPayload payloadHead; - string head; - int compressSize = 0; - int sendBufSize = payloadPrefixReserve + dataSize; - uint8_t *sendBuf = new uint8_t[sendBufSize](); - if (!sendBuf) { - return false; - } - payloadHead.compressType = context->transferConfig.compressType; - payloadHead.uncompressSize = dataSize; - payloadHead.index = index; - if (dataSize > 0) { - switch (payloadHead.compressType) { -#ifdef HARMONY_PROJECT - case COMPRESS_LZ4: { - compressSize = LZ4_compress_default((const char *)data, (char *)sendBuf + payloadPrefixReserve, - dataSize, dataSize); - break; - } -#endif - default: { // COMPRESS_NONE - if (memcpy_s(sendBuf + payloadPrefixReserve, sendBufSize - payloadPrefixReserve, data, dataSize) - != EOK) { - delete[] sendBuf; - return false; - } - compressSize = dataSize; - break; - } - } - } - payloadHead.compressSize = compressSize; - head = SerialStruct::SerializeToString(payloadHead); - if (head.size() + 1 > payloadPrefixReserve) { - delete[] sendBuf; - return false; - } - int errCode = memcpy_s(sendBuf, sendBufSize, head.c_str(), head.size() + 1); - if (errCode != EOK) { - delete[] sendBuf; - return false; - } - bool ret = SendToAnother(commandData, sendBuf, payloadPrefixReserve + compressSize) > 0; - delete[] sendBuf; - return ret; -} - -void HdcTransferBase::OnFileIO(uv_fs_t *req) -{ - bool tryFinishIO = false; - CtxFileIO *contextIO = (CtxFileIO *)req->data; - CtxFile *context = (CtxFile *)contextIO->context; - HdcTransferBase *thisClass = (HdcTransferBase *)context->thisClass; - uint8_t *bufIO = contextIO->bufIO; - uv_fs_req_cleanup(req); - --thisClass->refCount; - while (true) { - if (req->result < 0) { - WRITE_LOG(LOG_DEBUG, "OnFileIO error: %s", uv_strerror((int)req->result)); - context->closeNotify = true; - tryFinishIO = true; - break; - } - context->indexIO += req->result; - if (req->fs_type == UV_FS_READ) { - if (!thisClass->SendIOPayload(context, context->indexIO - req->result, bufIO, req->result)) { - tryFinishIO = true; - break; - } - if (context->indexIO < context->fileSize) { - // read continue until result >0, let single file packet +packet header less than GetMaxBufSize() - constexpr auto maxBufFactor = 0.8; - thisClass->SimpleFileIO(context, context->indexIO, nullptr, Base::GetMaxBufSize() * maxBufFactor); - } - } else if (req->fs_type == UV_FS_WRITE) { // write - if (context->indexIO >= context->fileSize) { - // The active end must first read it first, but you can't make Finish first, because Slave may not - // end.Only slave receives complete talents Finish - context->closeNotify = true; - tryFinishIO = true; - thisClass->SetFileTime(context); - } - } else { - tryFinishIO = true; - } - break; - } - delete[] bufIO; - delete contextIO; // Req is part of the Contextio structure, no free release - if (tryFinishIO) { - // close-step1 - ++thisClass->refCount; - uv_fs_close(thisClass->loopTask, &context->fsCloseReq, context->fsOpenReq.result, OnFileClose); - } -} - -void HdcTransferBase::OnFileOpen(uv_fs_t *req) -{ - CtxFile *context = (CtxFile *)req->data; - HdcTransferBase *thisClass = (HdcTransferBase *)context->thisClass; - uv_fs_req_cleanup(req); - WRITE_LOG(LOG_DEBUG, "Filemod openfile:%s", context->localPath.c_str()); - --thisClass->refCount; - if (req->result < 0) { - thisClass->LogMsg(MSG_FAIL, "Error opening file: %s, path:%s", uv_strerror((int)req->result), - context->localPath.c_str()); - thisClass->TaskFinish(); - return; - } - thisClass->ResetCtx(context); - if (context->master) { - // init master - uv_fs_t fs; - Base::ZeroStruct(fs.statbuf); - uv_fs_fstat(nullptr, &fs, context->fsOpenReq.result, nullptr); - TransferConfig &st = context->transferConfig; - st.fileSize = fs.statbuf.st_size; - st.optionalName = context->localName; - if (st.holdTimestamp) { - st.atime = fs.statbuf.st_atim.tv_sec * HDC_TIME_CONVERT_BASE + fs.statbuf.st_atim.tv_nsec; - st.mtime = fs.statbuf.st_mtim.tv_sec * HDC_TIME_CONVERT_BASE + fs.statbuf.st_mtim.tv_nsec; - } - st.path = context->remotePath; - // update ctxNow=context child value - context->fileSize = st.fileSize; - - uv_fs_req_cleanup(&fs); - thisClass->CheckMaster(context); - } else { // write - thisClass->SendToAnother(thisClass->commandBegin, nullptr, 0); - } -} - -bool HdcTransferBase::MatchPackageExtendName(string fileName, string extName) -{ - bool match = false; - int subfixIndex = fileName.rfind(extName); - if ((fileName.size() - subfixIndex) != extName.size()) { - return false; - } - match = true; - return match; -} - -// filter can be empty -int HdcTransferBase::GetSubFiles(const char *path, string filter, vector *out) -{ - int retNum = 0; - uv_fs_t req; - Base::ZeroStruct(req); - uv_dirent_t dent; - vector filterStrings; - if (!strlen(path)) { - return retNum; - } - if (filter.size()) { - Base::SplitString(filter, ";", filterStrings); - } - - if (uv_fs_scandir(nullptr, &req, path, 0, nullptr) < 0) { - uv_fs_req_cleanup(&req); - return retNum; - } - while (uv_fs_scandir_next(&req, &dent) != UV_EOF) { - // Skip. File - if (strcmp(dent.name, ".") == 0 || strcmp(dent.name, "..") == 0) - continue; - if (!(static_cast(dent.type) & UV_DIRENT_FILE)) - continue; - string fileName = dent.name; - for (auto &&s : filterStrings) { - int subfixIndex = fileName.rfind(s); - if ((fileName.size() - subfixIndex) != s.size()) - continue; - string fullPath = string(path) + "/"; - fullPath += fileName; - out->push_back(fullPath); - ++retNum; - } - } - uv_fs_req_cleanup(&req); - return retNum; -} - -// https://en.cppreference.com/w/cpp/filesystem/is_directory -// return true if file exist, false if file not exist -bool HdcTransferBase::SmartSlavePath(string &cwd, string &localPath, const char *optName) -{ - if (taskInfo->serverOrDaemon) { - // slave and server - ExtractRelativePath(cwd, localPath); - } - if (Base::CheckDirectoryOrPath(localPath.c_str(), true, false)) { - return true; - } - uv_fs_t req; - int r = uv_fs_lstat(nullptr, &req, localPath.c_str(), nullptr); - uv_fs_req_cleanup(&req); - if (r == 0 && req.statbuf.st_mode & S_IFDIR) { // is dir - localPath = Base::StringFormat("%s%c%s", localPath.c_str(), Base::GetPathSep(), optName); - } - return false; -} - -bool HdcTransferBase::RecvIOPayload(CtxFile *context, uint8_t *data, int dataSize) -{ - uint8_t *clearBuf = nullptr; - string serialStrring((char *)data, payloadPrefixReserve); - TransferPayload pld; - bool ret = false; - SerialStruct::ParseFromString(pld, serialStrring); - clearBuf = new uint8_t[pld.uncompressSize](); - if (!clearBuf) { - return false; - } - int clearSize = 0; - if (pld.compressSize > 0) { - switch (pld.compressType) { -#ifdef HARMONY_PROJECT - case COMPRESS_LZ4: { - clearSize = LZ4_decompress_safe((const char *)data + payloadPrefixReserve, (char *)clearBuf, - pld.compressSize, pld.uncompressSize); - break; - } -#endif - default: { // COMPRESS_NONE - if (memcpy_s(clearBuf, pld.uncompressSize, data + payloadPrefixReserve, pld.compressSize) != EOK) { - delete[] clearBuf; - return false; - } - clearSize = pld.compressSize; - break; - } - } - } - while (true) { - if ((uint32_t)clearSize != pld.uncompressSize) { - break; - } - if (SimpleFileIO(context, pld.index, clearBuf, clearSize) < 0) { - break; - } - ret = true; - break; - } - delete[] clearBuf; - return ret; -} - -bool HdcTransferBase::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) -{ - bool ret = true; - while (true) { - if (command == commandBegin) { - CtxFile *context = &ctxNow; - SimpleFileIO(context, context->indexIO, nullptr, Base::GetMaxBufSize()); - context->transferBegin = Base::GetRuntimeMSec(); - } else if (command == commandData) { - // The size of the actual HOST end may be larger than maxbuf - constexpr auto doubleSize = 2; - if (payloadSize > MAX_SIZE_IOBUF * doubleSize || payloadSize < 0) { - ret = false; - break; - } - // Note, I will trigger FileIO after multiple times. - CtxFile *context = &ctxNow; - if (!RecvIOPayload(context, payload, payloadSize)) { - ret = false; - break; - } - } else { - // Other subclass commands - } - break; - } - return ret; -} - -void HdcTransferBase::ExtractRelativePath(string &cwd, string &path) -{ - bool absPath = Base::IsAbsolutePath(path); - if (!absPath) { - path = cwd + path; - } -} -} // namespace Hdc diff --git a/services/flashd/common/transfer.h b/services/flashd/common/transfer.h deleted file mode 100755 index c03b3dea..00000000 --- a/services/flashd/common/transfer.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_TRANSFER_H -#define HDC_TRANSFER_H -#include "common.h" - -namespace Hdc { -class HdcTransferBase : public HdcTaskBase { -public: - enum CompressType { COMPRESS_NONE, COMPRESS_LZ4, COMPRESS_LZ77, COMPRESS_LZMA, COMPRESS_BROTLI }; - // used for child class - struct TransferConfig { - uint64_t fileSize; - uint64_t atime; // ns - uint64_t mtime; // ns - string options; - string path; - string optionalName; - bool updateIfNew; - uint8_t compressType; - bool holdTimestamp; - string functionName; - string clientCwd; - string reserve1; - string reserve2; - }; - // used for HdcTransferBase. just base class use, not public - struct TransferPayload { - uint64_t index; - uint8_t compressType; - uint32_t compressSize; - uint32_t uncompressSize; - }; - HdcTransferBase(HTaskInfo hTaskInfo); - virtual ~HdcTransferBase(); - virtual void StopTask() - { - } - bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); - -protected: - // Static file context - struct CtxFile { // The structure cannot be initialized by MEMSET - bool master; // Document transmission initiative - bool closeNotify; - void *thisClass; - uint64_t fileSize; - uint64_t indexIO; // Id or written IO bytes - uv_loop_t *loop; - uv_fs_cb cb; - string localName; - string localPath; - string remotePath; - uv_fs_t fsOpenReq; - uv_fs_t fsCloseReq; - uint64_t transferBegin; - vector taskQueue; - TransferConfig transferConfig; // Used for network IO configuration initialization - }; - // Just app-mode use - enum AppModType { - APPMOD_NONE, - APPMOD_INSTALL, - APPMOD_UNINSTALL, - APPMOD_SIDELOAD, - }; - - static void OnFileOpen(uv_fs_t *req); - static void OnFileClose(uv_fs_t *req); - int GetSubFiles(const char *path, string filter, vector *out); - virtual void CheckMaster(CtxFile *context) - { - } - virtual void WhenTransferFinish(CtxFile *context) - { - } - bool MatchPackageExtendName(string fileName, string extName); - bool ResetCtx(CtxFile *context, bool full = false); - bool SmartSlavePath(string &cwd, string &localPath, const char *optName); - void SetFileTime(CtxFile *context); - void ExtractRelativePath(string &cwd, string &path); - - CtxFile ctxNow; - uint16_t commandBegin; - uint16_t commandData; - const string CMD_OPTION_CLIENTCWD = "-cwd"; - const uint8_t payloadPrefixReserve = 64; -private: - // dynamic IO context - struct CtxFileIO { - uv_fs_t fs; - uint8_t *bufIO; - CtxFile *context; - }; - static void OnFileIO(uv_fs_t *req); - int SimpleFileIO(CtxFile *context, uint64_t index, uint8_t *sendBuf, int bytesIO); - bool SendIOPayload(CtxFile *context, int index, uint8_t *data, int dataSize); - bool RecvIOPayload(CtxFile *context, uint8_t *data, int dataSize); -}; -} // namespace Hdc - -#endif \ No newline at end of file diff --git a/services/flashd/common/usb.cpp b/services/flashd/common/usb.cpp deleted file mode 100755 index db39a445..00000000 --- a/services/flashd/common/usb.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "usb.h" - -namespace Hdc { -HdcUSBBase::HdcUSBBase(const bool serverOrDaemonIn, void *ptrMainBase) -{ - serverOrDaemon = serverOrDaemonIn; - clsMainBase = ptrMainBase; - modRunning = true; -} - -HdcUSBBase::~HdcUSBBase() -{ -} - -void HdcUSBBase::ReadUSB(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) -{ - HSession hSession = (HSession)stream->data; - HdcSessionBase *hSessionBase = (HdcSessionBase *)hSession->classInstance; - if (hSessionBase->FetchIOBuf(hSession, hSession->ioBuf, nread) < 0) { - hSessionBase->FreeSession(hSession->sessionId); - } -} - -bool HdcUSBBase::ReadyForWorkThread(HSession hSession) -{ - // Server-end USB IO is handed over to each sub-thread, only the daemon is still read by the main IO to distribute - // to each sub-thread by DataPipe. - if (uv_tcp_init(&hSession->childLoop, &hSession->dataPipe[STREAM_WORK]) - || uv_tcp_open(&hSession->dataPipe[STREAM_WORK], hSession->dataFd[STREAM_WORK])) { - WRITE_LOG(LOG_FATAL, "USBBase ReadyForWorkThread init child TCP failed"); - return false; - } - hSession->dataPipe[STREAM_WORK].data = hSession; - HdcSessionBase *pSession = (HdcSessionBase *)hSession->classInstance; - Base::SetTcpOptions(&hSession->dataPipe[STREAM_WORK]); - if (uv_read_start((uv_stream_t *)&hSession->dataPipe[STREAM_WORK], pSession->AllocCallback, ReadUSB)) { - WRITE_LOG(LOG_FATAL, "USBBase ReadyForWorkThread child TCP read failed"); - return false; - } - WRITE_LOG(LOG_DEBUG, "USBBase ReadyForWorkThread finish"); - return true; -}; - -// USB big data stream, block transmission, mainly to prevent accidental data packets from writing through EP port, -// inserting the send queue causes the program to crash -int HdcUSBBase::SendUSBBlock(HSession hSession, uint8_t *data, const int length) -{ - // Format:USBPacket1 payload1...USBPacketn payloadn; - // [USBHead1(PayloadHead1+Payload1)]+[USBHead2(Payload2)]+...+[USBHeadN(PayloadN)] - int maxIOSize = Base::GetMaxBufSize(); - int sizeUSBPacketHead = sizeof(USBHead); - int singleSize = maxIOSize - sizeUSBPacketHead; - int iMod = length % singleSize; - int iCount = (length - iMod) / singleSize + 1; - int offset = 0; - int i = 0; // It doesn't matter of 0 or 1, start from 1 to send it according to the serial number. - uint8_t *ioBuf = new uint8_t[maxIOSize](); - if (!ioBuf) { - return ERR_BUF_ALLOC; - } - for (i = 0; i < iCount; ++i) { - USBHead *pUSBHead = (USBHead *)ioBuf; - int errCode = memcpy_s(pUSBHead->flag, sizeof(pUSBHead->flag), PACKET_FLAG.c_str(), PACKET_FLAG.size()); - if (errCode != EOK) { - offset = ERR_BUF_COPY; - break; - } - pUSBHead->sessionId = hSession->sessionId; - if (i != iCount - 1) { - pUSBHead->dataSize = static_cast(singleSize); - } else { - pUSBHead->dataSize = static_cast(iMod); - pUSBHead->option = pUSBHead->option | USB_OPTION_TAIL; - } - uint8_t *payload = ioBuf + sizeUSBPacketHead; - if (EOK != memcpy_s(payload, maxIOSize - sizeUSBPacketHead, (uint8_t *)data + offset, pUSBHead->dataSize)) { - offset = ERR_BUF_COPY; - break; - } - offset += pUSBHead->dataSize; - if (SendUSBRaw(hSession, ioBuf, sizeUSBPacketHead + pUSBHead->dataSize) <= 0) { - offset = ERR_IO_FAIL; - break; - } - } - delete[] ioBuf; - return offset; -} - -int HdcUSBBase::SendToHdcStream(HSession hSession, uv_stream_t *stream, uint8_t *appendData, int dataSize) -{ - HUSB hUSB = hSession->hUSB; - vector &bufRecv = hUSB->bufRecv; - bufRecv.insert(bufRecv.end(), appendData, appendData + dataSize); - int ret = RET_SUCCESS; - while (bufRecv.size() > sizeof(USBHead)) { - USBHead *usbHeader = (USBHead *)bufRecv.data(); - if (memcmp(usbHeader->flag, PACKET_FLAG.c_str(), PACKET_FLAG.size())) { - WRITE_LOG(LOG_FATAL, "Error usb packet"); - ret = ERR_BUF_CHECK; - break; - } - if (bufRecv.size() < sizeof(USBHead) + usbHeader->dataSize) { - WRITE_LOG(LOG_DEBUG, "SendToHdcStream not enough"); - break; // successful , but not enough - } - if (usbHeader->sessionId != hSession->sessionId) { - // Only server do it here, daemon 'SendUsbSoftReset' no use - // hilog + ctrl^C to reproduction scene - // - // Because the USB-reset API does not work on all platforms, the last session IO data may be - // recveived, we need to ignore it. - if (hSession->serverOrDaemon && !hUSB->resetIO) { - WRITE_LOG(LOG_WARN, "SendToHdcStream sessionId not matched"); - SendUsbSoftReset(hUSB, usbHeader->sessionId); - hUSB->resetIO = true; - } - } else { - // usb data to logic - if (Base::SendToStream(stream, bufRecv.data() + sizeof(USBHead), usbHeader->dataSize) < 0) { - ret = ERR_IO_FAIL; - WRITE_LOG(LOG_FATAL, "Error usb send to stream"); - break; - } - } - bufRecv.erase(bufRecv.begin(), bufRecv.begin() + sizeof(USBHead) + usbHeader->dataSize); - } - return ret; -} -} \ No newline at end of file diff --git a/services/flashd/common/usb.h b/services/flashd/common/usb.h deleted file mode 100755 index 8b49c54c..00000000 --- a/services/flashd/common/usb.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_USB_H -#define HDC_USB_H -#include "common.h" - -namespace Hdc { -class HdcUSBBase { -public: - HdcUSBBase(const bool serverOrDaemonIn, void *ptrMainBase); - virtual ~HdcUSBBase(); - virtual int SendUSBRaw(HSession hSession, uint8_t *data, const int length) - { - return 0; - } - virtual bool ReadyForWorkThread(HSession hSession); - virtual void SendUsbSoftReset(HUSB hUSB, uint32_t sessionId) {}; - int SendUSBBlock(HSession hSession, uint8_t *data, const int length); - static void ReadUSB(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); - int SendToHdcStream(HSession hSession, uv_stream_t *stream, uint8_t *appendData, int dataSize); - -protected: - void *clsMainBase; - bool serverOrDaemon; - bool modRunning; -}; -} // namespace Hdc - -#endif \ No newline at end of file diff --git a/services/flashd/daemon/daemon.cpp b/services/flashd/daemon/daemon.cpp index fa34ef8b..fcf55dfa 100755 --- a/services/flashd/daemon/daemon.cpp +++ b/services/flashd/daemon/daemon.cpp @@ -13,9 +13,13 @@ * limitations under the License. */ #include "daemon.h" -#include "../common/serial_struct.h" + #include +#include "daemon_updater.h" +#include "flash_define.h" +#include "serial_struct.h" + namespace Hdc { HdcDaemon::HdcDaemon(bool serverOrDaemonIn) : HdcSessionBase(serverOrDaemonIn) @@ -91,13 +95,6 @@ void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB) enableSecure = (Base::Trim(secure) == "1"); } -void HdcDaemon::SendAndCloseChannel(HSession hSession, const uint32_t channelId, const std::string &info) -{ - Send(hSession->sessionId, channelId, CMD_KERNEL_ECHO_RAW, (uint8_t *)info.data(), info.size()); - uint8_t count = 1; - Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1); -} - // clang-format off #ifdef HDC_SUPPORT_FLASHD bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, @@ -122,7 +119,10 @@ bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uin ret = TaskCommandDispatch(hTaskInfo, TASK_UPDATER, command, payload, payloadSize); break; default: - SendAndCloseChannel(hSession, channelId, "Command not support in flashd\n"); + std::string info = "Command not support in flashd\n"; + Send(hSession->sessionId, channelId, CMD_KERNEL_ECHO_RAW, (uint8_t *)info.data(), info.size()); + uint8_t count = 1; + Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1); break; } return ret; @@ -131,55 +131,11 @@ bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uin bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, const int payloadSize) { - bool ret = true; - hTaskInfo->ownerSessionClass = this; - switch (command) { - case CMD_UNITY_EXECUTE: - case CMD_UNITY_REMOUNT: - case CMD_UNITY_REBOOT: - case CMD_UNITY_RUNMODE: - case CMD_UNITY_HILOG: - case CMD_UNITY_ROOTRUN: - case CMD_UNITY_TERMINATE: - case CMD_UNITY_BUGREPORT_INIT: - case CMD_UNITY_JPID: - ret = TaskCommandDispatch(hTaskInfo, TYPE_UNITY, command, payload, payloadSize); - break; - case CMD_SHELL_INIT: - case CMD_SHELL_DATA: - ret = TaskCommandDispatch(hTaskInfo, TYPE_SHELL, command, payload, payloadSize); - break; - case CMD_FILE_CHECK: - case CMD_FILE_DATA: - case CMD_FILE_FINISH: - case CMD_FILE_INIT: - case CMD_FILE_BEGIN: - ret = TaskCommandDispatch(hTaskInfo, TASK_FILE, command, payload, payloadSize); - break; - // One-way function, so fewer options - case CMD_APP_CHECK: - case CMD_APP_DATA: - case CMD_APP_UNINSTALL: - ret = TaskCommandDispatch(hTaskInfo, TASK_APP, command, payload, payloadSize); - break; - case CMD_FORWARD_INIT: - case CMD_FORWARD_CHECK: - case CMD_FORWARD_ACTIVE_SLAVE: - case CMD_FORWARD_DATA: - case CMD_FORWARD_FREE_CONTEXT: - case CMD_FORWARD_CHECK_RESULT: - ret = TaskCommandDispatch(hTaskInfo, TASK_FORWARD, command, payload, payloadSize); - break; - case CMD_UPDATER_CHECK: - case CMD_UPDATER_ERASE: - case CMD_UPDATER_FORMAT: - SendAndCloseChannel(hSession, channelId, "Command not support in hdcd\n"); - break; - default: - ret = false; - break; - } - return ret; + std::string info = "Command not support in hdcd\n"; + Send(hSession->sessionId, channelId, CMD_KERNEL_ECHO_RAW, (uint8_t *)info.data(), info.size()); + uint8_t count = 1; + Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1); + return true; } // clang-format on #endif diff --git a/services/flashd/daemon/daemon.h b/services/flashd/daemon/daemon.h deleted file mode 100755 index 4eb7df29..00000000 --- a/services/flashd/daemon/daemon.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_DAEMON_H -#define HDC_DAEMON_H -#include "daemon_common.h" - -namespace Hdc { -class HdcDaemon : public HdcSessionBase { -public: - HdcDaemon(bool serverOrDaemonIn); - virtual ~HdcDaemon(); - void InitMod(bool bEnableTCP, bool bEnableUSB); - bool FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, - const int payloadSize); - bool ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, uint8_t *bufPtr, - const int size); - void *clsTCPServ; - void *clsUSBServ; - void *clsJdwp; - -private: - bool RemoveInstanceTask(const uint8_t op, HTaskInfo hTask); - bool RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, const uint16_t command, - uint8_t *payload, const int payloadSize); - void SendAndCloseChannel(HSession hSession, const uint32_t channelId, const std::string &info); - void JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO); - bool HandDaemonAuth(HSession hSession, const uint32_t channelId, SessionHandShake &handshake); - void ClearInstanceResource(); - bool DaemonSessionHandshake(HSession hSession, const uint32_t channelId, uint8_t *payload, int payloadSize); - void TryStopInstance(); - - bool enableSecure; -}; -} // namespace Hdc -#endif \ No newline at end of file diff --git a/services/flashd/daemon/daemon_app.cpp b/services/flashd/daemon/daemon_app.cpp deleted file mode 100755 index 4f04dc93..00000000 --- a/services/flashd/daemon/daemon_app.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "daemon_app.h" - -namespace Hdc { -HdcDaemonApp::HdcDaemonApp(HTaskInfo hTaskInfo) - : HdcTransferBase(hTaskInfo) -{ - commandBegin = CMD_APP_BEGIN; - commandData = CMD_APP_DATA; - funcAppModFinish = nullptr; -} - -HdcDaemonApp::~HdcDaemonApp() -{ - WRITE_LOG(LOG_DEBUG, "~HdcDaemonApp"); -} - -bool HdcDaemonApp::ReadyForRelease() -{ - if (!HdcTaskBase::ReadyForRelease()) { - return false; - } - if (!asyncCommand.ReadyForRelease()) { - return false; - } - return true; -} - -bool HdcDaemonApp::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) -{ - if (!HdcTransferBase::CommandDispatch(command, payload, payloadSize)) { - return false; - } - bool ret = true; - switch (command) { - case CMD_APP_CHECK: { - string tmpData = "/data/local/tmp/"; - string tmpSD = "/sdcard/tmp/"; - string dstPath = tmpData; - string bufString((char *)payload, payloadSize); - SerialStruct::ParseFromString(ctxNow.transferConfig, bufString); - // update transferconfig to main context - ctxNow.master = false; - ctxNow.fsOpenReq.data = &ctxNow; - // -lrtsdpg, -l -r -t -s.., - if (ctxNow.transferConfig.functionName == CMDSTR_APP_INSTALL - && ctxNow.transferConfig.options.find("s") != std::string::npos) { - dstPath = tmpSD; - } -#ifdef HDC_PCDEBUG - char tmpPath[256] = ""; - size_t size = 256; - uv_os_tmpdir(tmpPath, &size); - dstPath = tmpPath; - dstPath += Base::GetPathSep(); -#endif - dstPath += ctxNow.transferConfig.optionalName; - ctxNow.localPath = dstPath; - ctxNow.transferBegin = Base::GetRuntimeMSec(); - ctxNow.fileSize = ctxNow.transferConfig.fileSize; - ++refCount; - uv_fs_open(loopTask, &ctxNow.fsOpenReq, ctxNow.localPath.c_str(), - UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IRUSR, OnFileOpen); - break; - } - case CMD_APP_UNINSTALL: { - // This maybe has a command implanting risk, since it is a controllable device, it can be ignored - string bufString(reinterpret_cast(payload), payloadSize); - PackageShell(false, "", bufString); - break; - } - default: - break; - } - return ret; -}; - -bool HdcDaemonApp::AsyncInstallFinish(bool finish, int64_t exitStatus, const string result) -{ - if (mode == APPMOD_INSTALL) { - unlink(ctxNow.localPath.c_str()); - } - asyncCommand.DoRelease(); - string echo = result; - echo = Base::ReplaceAll(echo, "\n", " "); - vector vecBuf; - vecBuf.push_back(mode); - vecBuf.push_back(exitStatus == 0); - vecBuf.insert(vecBuf.end(), (uint8_t *)echo.c_str(), (uint8_t *)echo.c_str() + echo.size()); - SendToAnother(CMD_APP_FINISH, vecBuf.data(), vecBuf.size()); - --refCount; -#ifdef UNIT_TEST - Base::WriteBinFile((UT_TMP_PATH + "/appinstall.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(), - MESSAGE_SUCCESS.size(), true); -#endif - return true; -} - -void HdcDaemonApp::PackageShell(bool installOrUninstall, const char *options, const string package) -{ - ++refCount; - // asynccmd Other processes, no RunningProtect protection - chmod(package.c_str(), 0644); // 0644 : permission - string doBuf; - if (installOrUninstall) { - doBuf = Base::StringFormat("bm install %s -p %s", options, package.c_str()); - } else { - doBuf = Base::StringFormat("bm uninstall %s -n %s", options, package.c_str()); - } - funcAppModFinish = std::bind(&HdcDaemonApp::AsyncInstallFinish, this, std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3); - if (installOrUninstall) { - mode = APPMOD_INSTALL; - } else { - mode = APPMOD_UNINSTALL; - } - asyncCommand.Initial(loopTask, funcAppModFinish); - asyncCommand.ExecuteCommand(doBuf); -} - -void HdcDaemonApp::Sideload(const char *pathOTA) -{ - mode = APPMOD_SIDELOAD; - LogMsg(MSG_OK, "[placeholders] sideload %s", pathOTA); - TaskFinish(); - unlink(pathOTA); -} - -void HdcDaemonApp::WhenTransferFinish(CtxFile *context) -{ - if (ctxNow.transferConfig.functionName == CMDSTR_APP_SIDELOAD) { - Sideload(context->localPath.c_str()); - } else if (ctxNow.transferConfig.functionName == CMDSTR_APP_INSTALL) { - PackageShell(true, context->transferConfig.options.c_str(), context->localPath.c_str()); - } else { - } -}; -} \ No newline at end of file diff --git a/services/flashd/daemon/daemon_app.h b/services/flashd/daemon/daemon_app.h deleted file mode 100755 index 7546fc39..00000000 --- a/services/flashd/daemon/daemon_app.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_DAEMON_APP_H -#define HDC_DAEMON_APP_H -#include "daemon_common.h" - -namespace Hdc { -class HdcDaemonApp : public HdcTransferBase { -public: - HdcDaemonApp(HTaskInfo hTaskInfo); - virtual ~HdcDaemonApp(); - bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); - bool ReadyForRelease(); - -private: - void WhenTransferFinish(CtxFile *context); - void PackageShell(bool installOrUninstall, const char *options, const string package); - bool AsyncInstallFinish(bool finish, int64_t exitStatus, const string result); - void Sideload(const char *pathOTA); - - AsyncCmd asyncCommand; - AsyncCmd::CmdResultCallback funcAppModFinish; - AppModType mode = APPMOD_NONE; -}; -} // namespace Hdc -#endif \ No newline at end of file diff --git a/services/flashd/daemon/daemon_common.h b/services/flashd/daemon/daemon_common.h deleted file mode 100755 index 35786e03..00000000 --- a/services/flashd/daemon/daemon_common.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_DAEMON_COMMON_H -#define HDC_DAEMON_COMMON_H - -// clang-format off -#include "../common/common.h" -#include "../common/define.h" -#include "../common/file.h" -#include "../common/forward.h" -#include "../common/async_cmd.h" -#include "../common/serial_struct.h" -#include "jdwp.h" -#include "daemon.h" -#include "daemon_unity.h" -#include "daemon_tcp.h" -#include "daemon_app.h" -#include "daemon_usb.h" -#include "daemon_forward.h" -#ifdef HDC_SUPPORT_FLASHD -#include "daemon_updater.h" -#endif -#include "shell.h" - -// clang-format on - -namespace Hdc { -} -#endif \ No newline at end of file diff --git a/services/flashd/daemon/daemon_forward.cpp b/services/flashd/daemon/daemon_forward.cpp deleted file mode 100755 index 25ddb710..00000000 --- a/services/flashd/daemon/daemon_forward.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "daemon_forward.h" - -namespace Hdc { -HdcDaemonForward::HdcDaemonForward(HTaskInfo hTaskInfo) - : HdcForwardBase(hTaskInfo) -{ -} - -HdcDaemonForward::~HdcDaemonForward() -{ -} - -void HdcDaemonForward::SetupJdwpPointCallBack(uv_idle_t *handle) -{ - HCtxForward ctxPoint = (HCtxForward)handle->data; - HdcDaemonForward *thisClass = reinterpret_cast(ctxPoint->thisClass); - thisClass->SetupPointContinue(ctxPoint, 1); // It usually works - Base::TryCloseHandle((const uv_handle_t *)handle, Base::CloseIdleCallback); - WRITE_LOG(LOG_DEBUG, "Setup JdwpPointCallBack finish"); - --thisClass->refCount; - return; -} - -bool HdcDaemonForward::SetupJdwpPoint(HCtxForward ctxPoint) -{ - HdcDaemon *daemon = (HdcDaemon *)taskInfo->ownerSessionClass; - HdcJdwp *clsJdwp = (HdcJdwp *)daemon->clsJdwp; - uint32_t pid = std::stol(ctxPoint->localArgs[1]); - if (ctxPoint->checkPoint) { // checke - bool ret = clsJdwp->CheckPIDExist(pid); - SetupPointContinue(ctxPoint, (int)ret); - WRITE_LOG(LOG_DEBUG, "Jdwp jump checkpoint"); - return true; - } - // do slave connect - // fd[0] for forward, fd[1] for jdwp - // forward to close fd[0], fd[1] for jdwp close - int fds[2] = { 0 }; - bool ret = false; - Base::CreateSocketPair(fds); - if (uv_tcp_init(loopTask, &ctxPoint->tcp)) { - return ret; - } - ctxPoint->tcp.data = ctxPoint; - if (uv_tcp_open(&ctxPoint->tcp, fds[0])) { - return ret; - } - constexpr auto len = sizeof(uint32_t); - uint8_t flag[1 + len + len]; - flag[0] = SP_JDWP_NEWFD; - if (memcpy_s(flag + 1, sizeof(flag) - 1, &pid, len) || - memcpy_s(flag + 1 + len, sizeof(flag) - len - 1, &fds[1], len)) { - return ret; - } - if (ThreadCtrlCommunicate(flag, sizeof(flag)) > 0) { - ret = true; - } - WRITE_LOG(LOG_DEBUG, "SendJdwpNewFD Finish,ret:%d fd0:%d fd1:%d", ret, fds[0], fds[1]); - if (!ret) { - Base::CloseSocketPair(fds); - return ret; - } - - ++refCount; - Base::IdleUvTask(loopTask, ctxPoint, SetupJdwpPointCallBack); - return ret; -} -} \ No newline at end of file diff --git a/services/flashd/daemon/daemon_forward.h b/services/flashd/daemon/daemon_forward.h deleted file mode 100755 index 5dfae60a..00000000 --- a/services/flashd/daemon/daemon_forward.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_DAEMON_FORWARD_H -#define HDC_DAEMON_FORWARD_H -#include "daemon_common.h" - -namespace Hdc { -class HdcDaemonForward : public HdcForwardBase { -public: - HdcDaemonForward(HTaskInfo hTaskInfo); - virtual ~HdcDaemonForward(); - -private: - bool SetupJdwpPoint(HCtxForward ctxPoint); - static void SetupJdwpPointCallBack(uv_idle_t *handle); -}; -} // namespace Hdc - -#endif \ No newline at end of file diff --git a/services/flashd/daemon/daemon_tcp.cpp b/services/flashd/daemon/daemon_tcp.cpp deleted file mode 100755 index 64d16aeb..00000000 --- a/services/flashd/daemon/daemon_tcp.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "daemon_tcp.h" - -namespace Hdc { -HdcDaemonTCP::HdcDaemonTCP(const bool serverOrDaemonIn, void *ptrMainBase) - : HdcTCPBase(serverOrDaemonIn, ptrMainBase) -{ - // If the listening value for the property setting is obtained, it will be 0 randomly assigned. - char strTCPPort[BUF_SIZE_TINY] = ""; - const uint16_t BUFF_SIZE = 8; - Base::GetHdcProperty("persist.hdc.port", strTCPPort, BUFF_SIZE); - tcpListenPort = atoi(strTCPPort); - if (tcpListenPort <= 0) { - tcpListenPort = 10178; // 10178 def port - } - Base::ZeroStruct(servUDP); - Base::ZeroStruct(servTCP); -#ifdef HDC_DEBUG - const uint16_t DEBUG_TCP_PORT = 10178; - tcpListenPort = DEBUG_TCP_PORT; -#endif -} - -HdcDaemonTCP::~HdcDaemonTCP() -{ -} - -void HdcDaemonTCP::Stop() -{ - Base::TryCloseHandle((const uv_handle_t *)&servUDP); - Base::TryCloseHandle((const uv_handle_t *)&servTCP); - WRITE_LOG(LOG_DEBUG, "~HdcDaemonTCP"); -} - -void HdcDaemonTCP::TransmitConfig(const sockaddr *addrSrc, uv_udp_t *handle) -{ - char srcIP[BUF_SIZE_TINY] = ""; - struct sockaddr addrSrcIPPort; - uv_udp_send_t *req = new uv_udp_send_t(); - if (!req) { - return; - } - string sendBuf = Base::StringFormat("%s-%d", HANDSHAKE_MESSAGE.c_str(), tcpListenPort); - uv_buf_t sndbuf = uv_buf_init((char *)sendBuf.c_str(), sendBuf.size()); - uv_ip4_name((sockaddr_in *)addrSrc, srcIP, sizeof(srcIP)); - uv_ip4_addr(srcIP, DEFAULT_PORT, (sockaddr_in *)&addrSrcIPPort); - uv_udp_send(req, handle, &sndbuf, 1, &addrSrcIPPort, SendUDPFinish); -} - -void HdcDaemonTCP::AcceptClient(uv_stream_t *server, int status) -{ - uv_loop_t *ptrLoop = server->loop; - uv_tcp_t *pServTCP = (uv_tcp_t *)server; - HdcDaemonTCP *thisClass = (HdcDaemonTCP *)pServTCP->data; - HdcSessionBase *ptrConnect = (HdcSessionBase *)thisClass->clsMainBase; - HdcSessionBase *daemon = reinterpret_cast(thisClass->clsMainBase); - const uint16_t maxWaitTime = UV_DEFAULT_INTERVAL; - auto ctrl = daemon->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0); - HSession hSession = ptrConnect->MallocSession(false, CONN_TCP, thisClass); - if (!hSession) { - return; - } - if (uv_accept(server, (uv_stream_t *)&hSession->hWorkTCP) < 0) { - goto Finish; - } - if ((hSession->fdChildWorkTCP = Base::DuplicateUvSocket(&hSession->hWorkTCP)) < 0) { - goto Finish; - }; - Base::TryCloseHandle((uv_handle_t *)&hSession->hWorkTCP); - Base::StartWorkThread(ptrLoop, ptrConnect->SessionWorkThread, Base::FinishWorkThread, hSession); - // wait for thread up - while (hSession->childLoop.active_handles == 0) { - usleep(maxWaitTime); - } - Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); - return; -Finish: - ptrConnect->FreeSession(hSession->sessionId); -} - -void HdcDaemonTCP::RecvUDPEntry(const sockaddr *addrSrc, uv_udp_t *handle, const uv_buf_t *rcvbuf) -{ - TransmitConfig(addrSrc, handle); -} - -void HdcDaemonTCP::SetUDPListen() -{ - struct sockaddr_in addr; - int r; - HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase; - // udp broadcast - servUDP.data = this; - r = uv_udp_init(&ptrConnect->loopMain, &servUDP); - r = uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &addr); - r = uv_udp_bind(&servUDP, (const struct sockaddr *)&addr, UV_UDP_REUSEADDR); - r = uv_udp_recv_start(&servUDP, AllocStreamUDP, RecvUDP); -} - -// Set the daemon-side TCP listening -int HdcDaemonTCP::SetTCPListen() -{ - // tcp listen - HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase; - servTCP.data = this; - struct sockaddr_in addr; - int namelen; - const int DEFAULT_BACKLOG = 128; - - uv_tcp_init(&ptrConnect->loopMain, &servTCP); - uv_ip4_addr("0.0.0.0", tcpListenPort, &addr); // tcpListenPort == 0 - uv_tcp_bind(&servTCP, (const struct sockaddr *)&addr, 0); - if (uv_listen((uv_stream_t *)&servTCP, DEFAULT_BACKLOG, (uv_connection_cb)AcceptClient)) { - return ERR_API_FAIL; - } - // Get listen port - Base::ZeroStruct(addr); - namelen = sizeof(addr); - if (uv_tcp_getsockname(&servTCP, (sockaddr *)&addr, &namelen)) { - return ERR_API_FAIL; - } - tcpListenPort = ntohs(addr.sin_port); - return RET_SUCCESS; -} - -int HdcDaemonTCP::Initial() -{ - WRITE_LOG(LOG_DEBUG, "HdcDaemonTCP init"); - SetUDPListen(); - if (SetTCPListen() != RET_SUCCESS) { - WRITE_LOG(LOG_FATAL, "TCP listen failed"); - return ERR_GENERIC; - } -#ifndef UNIT_TEST - WRITE_LOG(LOG_INFO, "TCP listen on port:[%d]", tcpListenPort); -#endif - return RET_SUCCESS; -} -} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/daemon/daemon_tcp.h b/services/flashd/daemon/daemon_tcp.h deleted file mode 100755 index bd399ea6..00000000 --- a/services/flashd/daemon/daemon_tcp.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_DAEMON_TCP_H -#define HDC_DAEMON_TCP_H -#include "daemon_common.h" - -namespace Hdc { -class HdcDaemonTCP : public HdcTCPBase { -public: - HdcDaemonTCP(const bool serverOrDaemonIn, void *ptrMainBase); - virtual ~HdcDaemonTCP(); - void RecvUDPEntry(const sockaddr *addrSrc, uv_udp_t *handle, const uv_buf_t *rcvbuf); - uint16_t tcpListenPort; - int Initial(); - void Stop(); - -private: - static void AcceptClient(uv_stream_t *server, int status); - void TransmitConfig(const sockaddr *addrSrc, uv_udp_t *handle); - int SetTCPListen(); - void SetUDPListen(); - - uv_tcp_t servTCP; - uv_udp_t servUDP; -}; -} // namespace Hdc - -#endif diff --git a/services/flashd/daemon/daemon_unity.h b/services/flashd/daemon/daemon_unity.h deleted file mode 100755 index c816487f..00000000 --- a/services/flashd/daemon/daemon_unity.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_DAEMON_UNITY_H -#define HDC_DAEMON_UNITY_H -#include "daemon_common.h" - -namespace Hdc { -class HdcDaemonUnity : public HdcTaskBase { -public: - HdcDaemonUnity(HTaskInfo hTaskInfo); - virtual ~HdcDaemonUnity(); - bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); - void StopTask(); - bool ReadyForRelease(); - -private: - static void OnFdRead(uv_fs_t *req); - int ExecuteShell(const char *shellCommand); - bool FindMountDeviceByPath(const char *toQuery, char *dev); - bool RemountPartition(const char *dir); - bool RemountDevice(); - bool RebootDevice(const string &cmd); - bool SetDeviceRunMode(void *daemonIn, const char *cmd); - bool GetHiLog(const char *cmd); - bool ListJdwpProcess(void *daemonIn); - bool AsyncCmdOut(bool finish, int64_t exitStatus, const string result); - - const string rebootProperty = "sys.powerctl"; - AsyncCmd asyncCommand; - uint16_t currentDataCommand; -#ifdef UNIT_TEST - int countUt = 0; -#endif -}; -} // namespace Hdc -#endif // HDC_DAEMON_UNITY_H diff --git a/services/flashd/daemon/daemon_updater.cpp b/services/flashd/daemon/daemon_updater.cpp index 1cd520b7..2e84fe75 100755 --- a/services/flashd/daemon/daemon_updater.cpp +++ b/services/flashd/daemon/daemon_updater.cpp @@ -16,6 +16,7 @@ #include "daemon_common.h" #include "flashd/flashd.h" #include "flash_utils.h" +#include "flash_define.h" namespace Hdc { DaemonUpdater::DaemonUpdater(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo) @@ -46,6 +47,7 @@ bool DaemonUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, co } switch (command) { case CMD_UPDATER_DATA: { + const uint8_t payloadPrefixReserve = 64; string serialStrring((char *)payload, payloadPrefixReserve); TransferPayload pld {}; SerialStruct::ParseFromString(pld, serialStrring); diff --git a/services/flashd/daemon/daemon_usb.cpp b/services/flashd/daemon/daemon_usb.cpp deleted file mode 100755 index 6f5a33b6..00000000 --- a/services/flashd/daemon/daemon_usb.cpp +++ /dev/null @@ -1,498 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "daemon_usb.h" -#include "usb_ffs.h" - -namespace Hdc { -HdcDaemonUSB::HdcDaemonUSB(const bool serverOrDaemonIn, void *ptrMainBase) - : HdcUSBBase(serverOrDaemonIn, ptrMainBase) -{ - Base::ZeroStruct(sendEP); - Base::ZeroStruct(usbHandle); - uv_mutex_init(&sendEP); -} - -HdcDaemonUSB::~HdcDaemonUSB() -{ - // Closed in the IO loop, no longer closing CLOSE ENDPOINT - uv_mutex_destroy(&sendEP); - if (controlEp > 0) { - close(controlEp); - } -} - -void HdcDaemonUSB::Stop() -{ - WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB Stop"); - // Here only clean up the IO-related resources, session related resources clear reason to clean up the session - // module - modRunning = false; - WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB Stop free main session"); - Base::TryCloseHandle((uv_handle_t *)&checkEP); - CloseEndpoint(&usbHandle); - WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB Stop free main session finish"); -} - -string HdcDaemonUSB::GetDevPath(const std::string &path) -{ - DIR *dir = ::opendir(path.c_str()); - if (dir == nullptr) { - WRITE_LOG(LOG_WARN, "%s: cannot open devpath: errno: %d", path.c_str(), errno); - return ""; - } - - string res = USB_FFS_BASE; - string node; - int count = 0; - struct dirent *entry = nullptr; - while ((entry = ::readdir(dir))) { - if (*entry->d_name == '.') { - continue; - } - node = entry->d_name; - ++count; - } - if (count > 1) { - res += "hdc"; - } else { - res += node; - } - ::closedir(dir); - return res; -} - -int HdcDaemonUSB::Initial() -{ - // after Linux-3.8,kernel switch to the USB Function FS - // Implement USB hdc function in user space - WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB init"); - basePath = GetDevPath(USB_FFS_BASE); - if (access((basePath + "/ep0").c_str(), F_OK) != 0) { - WRITE_LOG(LOG_DEBUG, "Only support usb-ffs, make sure kernel3.8+ and usb-ffs enabled, usbmode disabled"); - return -1; - } - HdcDaemon *daemon = (HdcDaemon *)clsMainBase; - WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB::Initiall"); - uv_timer_init(&daemon->loopMain, &checkEP); - checkEP.data = this; - uv_timer_start(&checkEP, WatchEPTimer, 0, TIME_BASE); - return 0; -} - -// DAEMON end USB module USB-FFS EP port connection -int HdcDaemonUSB::ConnectEPPoint(HUSB hUSB) -{ - int ret = ERR_GENERIC; - while (true) { - if (controlEp <= 0) { - // After the control port sends the instruction, the device is initialized by the device to the HOST host, - // which can be found for USB devices. Do not send initialization to the EP0 control port, the USB - // device will not be initialized by Host - WRITE_LOG(LOG_DEBUG, "Begin send to control(EP0) for usb descriptor init"); - string ep0Path = basePath + "/ep0"; - if ((controlEp = open(ep0Path.c_str(), O_RDWR)) < 0) { - WRITE_LOG(LOG_WARN, "%s: cannot open control endpoint: errno=%d", ep0Path.c_str(), errno); - break; - } - if (write(controlEp, &USB_FFS_DESC, sizeof(USB_FFS_DESC)) < 0) { - WRITE_LOG(LOG_WARN, "%s: write ffs configs failed: errno=%d", ep0Path.c_str(), errno); - break; - } - if (write(controlEp, &USB_FFS_VALUE, sizeof(USB_FFS_VALUE)) < 0) { - WRITE_LOG(LOG_WARN, "%s: write USB_FFS_VALUE failed: errno=%d", ep0Path.c_str(), errno); - break; - } - // active usbrc,Send USB initialization singal - Base::SetHdcProperty("sys.usb.ffs.ready", "1"); - WRITE_LOG(LOG_DEBUG, "ConnectEPPoint ctrl init finish, set usb-ffs ready"); - } - string outPath = basePath + "/ep1"; - if ((hUSB->bulkOut = open(outPath.c_str(), O_RDWR)) < 0) { - WRITE_LOG(LOG_WARN, "%s: cannot open bulk-out ep: errno=%d", outPath.c_str(), errno); - break; - } - string inPath = basePath + "/ep2"; - if ((hUSB->bulkIn = open(inPath.c_str(), O_RDWR)) < 0) { - WRITE_LOG(LOG_WARN, "%s: cannot open bulk-in ep: errno=%d", inPath.c_str(), errno); - break; - } - // cannot open with O_CLOEXEC, must fcntl - fcntl(controlEp, F_SETFD, FD_CLOEXEC); - fcntl(hUSB->bulkOut, F_SETFD, FD_CLOEXEC); - fcntl(hUSB->bulkIn, F_SETFD, FD_CLOEXEC); - - WRITE_LOG(LOG_DEBUG, "New bulk in\\out open bulkout:%d bulkin:%d", hUSB->bulkOut, hUSB->bulkIn); - hUSB->bufRecv.clear(); - ret = RET_SUCCESS; - break; - } - if (ret != RET_SUCCESS) { - CloseEndpoint(hUSB, true); - } - return ret; -} - -void HdcDaemonUSB::CloseEndpoint(HUSB hUSB, bool closeCtrlEp) -{ - if (hUSB->bulkIn > 0) { - close(hUSB->bulkIn); - hUSB->bulkIn = 0; - } - if (hUSB->bulkOut > 0) { - close(hUSB->bulkOut); - hUSB->bulkOut = 0; - } - if (controlEp > 0 && closeCtrlEp) { - close(controlEp); - controlEp = 0; - } - isAlive = false; - WRITE_LOG(LOG_FATAL, "DaemonUSB close endpoint"); -} - -void HdcDaemonUSB::ResetOldSession(const uint32_t sessionId) -{ - HdcDaemon *daemon = reinterpret_cast(clsMainBase); - HSession hSession = daemon->AdminSession(OP_QUERY, sessionId, nullptr); - if (hSession == nullptr) { - return; - } - hSession->hUSB->resetIO = true; - // The Host side is restarted, but the USB cable is still connected - WRITE_LOG(LOG_WARN, "Hostside softreset to restart daemon, old sessionId:%u", sessionId); - daemon->PushAsyncMessage(sessionId, ASYNC_FREE_SESSION, nullptr, 0); -} - -// Prevent other USB data misfortunes to send the program crash -int HdcDaemonUSB::AvailablePacket(uint8_t *ioBuf, uint32_t *sessionId) -{ - int ret = RET_SUCCESS; - constexpr auto maxBufFactor = 1.2; - while (true) { - struct USBHead *usbPayloadHeader = (struct USBHead *)ioBuf; - if (memcmp(usbPayloadHeader->flag, PACKET_FLAG.c_str(), PACKET_FLAG.size())) { - ret = ERR_BUF_CHECK; - break; - } - if (usbPayloadHeader->dataSize > MAX_SIZE_IOBUF * maxBufFactor + sizeof(USBHead)) { - ret = ERR_BUF_SIZE; - break; - } - if ((usbPayloadHeader->option & USB_OPTION_RESET)) { - ResetOldSession(usbPayloadHeader->sessionId); - ret = ERR_IO_SOFT_RESET; - break; - } - *sessionId = usbPayloadHeader->sessionId; - break; - } - return ret; -} - -// Work in subcrete,Work thread is ready -bool HdcDaemonUSB::ReadyForWorkThread(HSession hSession) -{ - HdcUSBBase::ReadyForWorkThread(hSession); - return true; -}; - -int HdcDaemonUSB::CloseBulkEp(bool bulkInOut, int bulkFd, uv_loop_t *loop) -{ - struct CtxCloseBulkEp { - uv_fs_t req; - HdcDaemonUSB *thisClass; - bool bulkInOut; - }; - CtxCloseBulkEp *ctx = new CtxCloseBulkEp(); - uv_fs_t *req = &ctx->req; - req->data = ctx; - ctx->bulkInOut = bulkInOut; - ctx->thisClass = this; - isAlive = false; - uv_fs_close(loop, req, bulkFd, [](uv_fs_t *req) { - auto ctx = (CtxCloseBulkEp *)req->data; - if (ctx->bulkInOut) { - ctx->thisClass->usbHandle.bulkIn = 0; - } else { - ctx->thisClass->usbHandle.bulkOut = 0; - } - WRITE_LOG(LOG_DEBUG, "Try to abort blukin write callback %s", ctx->bulkInOut ? "bulkin" : "bulkout"); - uv_fs_req_cleanup(req); - delete ctx; - }); - return 0; -} - -int HdcDaemonUSB::SendUSBIOSync(HSession hSession, HUSB hMainUSB, const uint8_t *data, const int length) -{ - int bulkIn = hMainUSB->bulkIn; - int childRet = 0; - int ret = ERR_IO_FAIL; - int offset = 0; - while (modRunning && isAlive && !hSession->isDead && !hSession->hUSB->resetIO) { - childRet = write(bulkIn, (uint8_t *)data + offset, length - offset); - if (childRet <= 0) { - int err = errno; - if (err == EINTR) { - WRITE_LOG(LOG_DEBUG, "BulkinWrite write EINTR, try again"); - continue; - } else { - WRITE_LOG(LOG_FATAL, "BulkinWrite write fatal errno %d", err); - isAlive = false; - } - break; - } - offset += childRet; - if (offset >= length) { - break; - } - } - if (offset == length) { - ret = length; - } else { - WRITE_LOG(LOG_FATAL, - "BulkinWrite write failed, nsize:%d really:%d modRunning:%d isAlive:%d SessionDead:%d usbReset:%d", - length, offset, modRunning, isAlive, hSession->isDead, hSession->hUSB->resetIO); - } - USBHead *pUSBHead = (USBHead *)data; - if ((pUSBHead->option & USB_OPTION_TAIL) || ret < 0) { - // tail or failed, dec Ref - hSession->sendRef--; - } - return ret; -} - -int HdcDaemonUSB::SendUSBRaw(HSession hSession, uint8_t *data, const int length) -{ - HdcDaemon *daemon = (HdcDaemon *)hSession->classInstance; - // Prevent memory stacking, send temporary way to use asynchronous - // Generally sent in the same thread, but when new session is created, there is a possibility that the old session - // is not retired. - // At present, the radical transmission method is currently opened directly in various threads, and - // it can be used exclusive File-DESC transmission mode in each thread. The late stage can be used as asynchronous + - // SendPipe to the main thread transmission. - uv_mutex_lock(&sendEP); - int ret = SendUSBIOSync(hSession, &usbHandle, data, length); - if (ret < 0) { - daemon->FreeSession(hSession->sessionId); - WRITE_LOG(LOG_DEBUG, "SendUSBRaw try to freesession"); - } - uv_mutex_unlock(&sendEP); - return ret; -} - -// cross thread call -void HdcDaemonUSB::OnNewHandshakeOK(const uint32_t sessionId) -{ - currentSessionId = sessionId; // real Id -} - -HSession HdcDaemonUSB::PrepareNewSession(uint32_t sessionId, uint8_t *pRecvBuf, int recvBytesIO) -{ - HdcDaemon *daemon = reinterpret_cast(clsMainBase); - HSession hChildSession = daemon->MallocSession(false, CONN_USB, this, sessionId); - if (!hChildSession) { - return nullptr; - } - if (currentSessionId != 0) { - // reset old session - // The Host side is restarted, but the USB cable is still connected - WRITE_LOG(LOG_WARN, "New session coming, restart old sessionId:%u", currentSessionId); - daemon->PushAsyncMessage(currentSessionId, ASYNC_FREE_SESSION, nullptr, 0); - } - Base::StartWorkThread(&daemon->loopMain, daemon->SessionWorkThread, Base::FinishWorkThread, hChildSession); - auto funcNewSessionUp = [](uv_timer_t *handle) -> void { - HSession hChildSession = reinterpret_cast(handle->data); - HdcDaemon *daemon = reinterpret_cast(hChildSession->classInstance); - if (hChildSession->childLoop.active_handles == 0) { - return; - } - if (!hChildSession->isDead) { - auto ctrl = daemon->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0); - Base::SendToStream((uv_stream_t *)&hChildSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); - WRITE_LOG(LOG_DEBUG, "Main thread usbio mirgate finish"); - } - Base::TryCloseHandle(reinterpret_cast(handle), Base::CloseTimerCallback); - }; - Base::TimerUvTask(&daemon->loopMain, hChildSession, funcNewSessionUp); - return hChildSession; -} - -int HdcDaemonUSB::DispatchToWorkThread(const uint32_t sessionId, uint8_t *readBuf, int readBytes) -{ - // Format:USBPacket1 payload1...USBPacketn - // payloadn-[USBHead1(PayloadHead1+Payload1)]+[USBHead2(Payload2)]+...+[USBHeadN(PayloadN)] - HSession hChildSession = nullptr; - HdcDaemon *daemon = reinterpret_cast(clsMainBase); - hChildSession = daemon->AdminSession(OP_QUERY, sessionId, nullptr); - if (!hChildSession) { - hChildSession = PrepareNewSession(sessionId, readBuf, readBytes); - if (!hChildSession) { - return ERR_SESSION_NOFOUND; - } - } - if (hChildSession->childCleared) { - return ERR_SESSION_DEAD; - } - if (SendToHdcStream(hChildSession, reinterpret_cast(&hChildSession->dataPipe[STREAM_MAIN]), readBuf, - readBytes) - != RET_SUCCESS) { - return ERR_IO_FAIL; - } - return readBytes; -} - -bool HdcDaemonUSB::JumpAntiquePacket(const uint8_t &buf, ssize_t bytes) const -{ - constexpr size_t antiqueFlagSize = 4; - constexpr size_t antiqueFullSize = 24; - // anti CNXN 0x4e584e43 - uint8_t flag[] = { 0x43, 0x4e, 0x58, 0x4e }; - if (bytes == antiqueFullSize && !memcmp(&buf, flag, antiqueFlagSize)) { - return true; - } - return false; -} - -// Only physically swap EP ports will be reset -void HdcDaemonUSB::OnUSBRead(uv_fs_t *req) -{ // Only read at the main thread - auto ctxIo = reinterpret_cast(req->data); - auto hUSB = reinterpret_cast(ctxIo->data); - auto thisClass = reinterpret_cast(ctxIo->thisClass); - uint8_t *bufPtr = ctxIo->buf; - ssize_t bytesIOBytes = req->result; - uint32_t sessionId = 0; - bool ret = false; - int childRet = 0; - --thisClass->ref; - while (thisClass->isAlive) { - // Don't care is module running, first deal with this - if (bytesIOBytes < 0) { - WRITE_LOG(LOG_WARN, "USBIO failed1 %s", uv_strerror(bytesIOBytes)); - break; - } else if (bytesIOBytes == 0) { - // zero packet - ret = true; - break; - } - if (thisClass->JumpAntiquePacket(*bufPtr, bytesIOBytes)) { - WRITE_LOG(LOG_DEBUG, "JumpAntiquePacket auto jump"); - ret = true; - break; - } - // guess is head of packet - if ((childRet = thisClass->AvailablePacket((uint8_t *)bufPtr, &sessionId)) != RET_SUCCESS) { - if (childRet != ERR_IO_SOFT_RESET) { - WRITE_LOG(LOG_WARN, "AvailablePacket check failed, ret:%d buf:%-50s", bytesIOBytes, bufPtr); - break; - } - // reset packet - } else { - // AvailablePacket case - if (thisClass->DispatchToWorkThread(sessionId, bufPtr, bytesIOBytes) < 0) { - WRITE_LOG(LOG_FATAL, "DispatchToWorkThread failed"); - break; - } - } - if (thisClass->LoopUSBRead(hUSB) < 0) { - WRITE_LOG(LOG_FATAL, "LoopUSBRead failed"); - break; - } - ret = true; - break; - } - if (!ret) { - thisClass->isAlive = false; - } - delete[] ctxIo->buf; - uv_fs_req_cleanup(req); - delete ctxIo; -} - -int HdcDaemonUSB::LoopUSBRead(HUSB hUSB) -{ - int ret = -1; - HdcDaemon *daemon = reinterpret_cast(clsMainBase); - // must > available size, or it will be incorrect - int readMax = Base::GetMaxBufSize() + sizeof(USBHead) + EXTRA_ALLOC_SIZE; - auto ctxIo = new CtxUvFileCommonIo(); - auto buf = new uint8_t[readMax](); - uv_fs_t *req = nullptr; - uv_buf_t iov; - if (ctxIo == nullptr || buf == nullptr) { - goto FAILED; - } - ctxIo->buf = buf; - ctxIo->bufSize = readMax; - ctxIo->data = hUSB; - ctxIo->thisClass = this; - req = &ctxIo->req; - req->data = ctxIo; - iov = uv_buf_init(reinterpret_cast(ctxIo->buf), ctxIo->bufSize); - ret = uv_fs_read(&daemon->loopMain, req, hUSB->bulkOut, &iov, 1, -1, OnUSBRead); - if (ret < 0) { - WRITE_LOG(LOG_FATAL, "uv_fs_read < 0"); - goto FAILED; - } - ++this->ref; - return 0; -FAILED: - if (ctxIo != nullptr) { - delete ctxIo; - } - if (buf != nullptr) { - delete[] buf; - } - return -1; -} - -// Because USB can connect to only one host,daemonUSB is only one Session by default -void HdcDaemonUSB::WatchEPTimer(uv_timer_t *handle) -{ - HdcDaemonUSB *thisClass = (HdcDaemonUSB *)handle->data; - HUSB hUSB = &thisClass->usbHandle; - HdcDaemon *daemon = reinterpret_cast(thisClass->clsMainBase); - if (thisClass->isAlive || thisClass->ref > 0) { - return; - } - bool resetEp = false; - do { - if (hUSB->bulkIn > 0) { - thisClass->CloseBulkEp(true, thisClass->usbHandle.bulkIn, &daemon->loopMain); - resetEp = true; - } - if (hUSB->bulkOut > 0) { - thisClass->CloseBulkEp(false, thisClass->usbHandle.bulkOut, &daemon->loopMain); - resetEp = true; - } - if (thisClass->controlEp > 0) { - close(thisClass->controlEp); - thisClass->controlEp = 0; - resetEp = true; - } - } while (false); - if (resetEp || thisClass->usbHandle.bulkIn != 0 || thisClass->usbHandle.bulkOut != 0) { - return; - } - // until all bulkport reset - if (thisClass->ConnectEPPoint(hUSB) != RET_SUCCESS) { - return; - } - // connect OK - thisClass->isAlive = true; - thisClass->LoopUSBRead(hUSB); -} -} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/daemon/daemon_usb.h b/services/flashd/daemon/daemon_usb.h deleted file mode 100755 index 38dc5244..00000000 --- a/services/flashd/daemon/daemon_usb.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_DAEMON_USB_H -#define HDC_DAEMON_USB_H -#include "daemon_common.h" - -namespace Hdc { -class HdcDaemonUSB : public HdcUSBBase { -public: - HdcDaemonUSB(const bool serverOrDaemonIn, void *ptrMainBase); - virtual ~HdcDaemonUSB(); - int Initial(); - void Stop(); - int SendUSBRaw(HSession hSession, uint8_t *data, const int length); - void OnNewHandshakeOK(const uint32_t sessionId); - -private: - struct CtxUvFileCommonIo { - uv_fs_t req; - uint8_t *buf; - int bufSize; - void *thisClass; - void *data; - }; - static void OnUSBRead(uv_fs_t *req); - static void WatchEPTimer(uv_timer_t *handle); - int ConnectEPPoint(HUSB hUSB); - int DispatchToWorkThread(const uint32_t sessionId, uint8_t *readBuf, int readBytes); - int AvailablePacket(uint8_t *ioBuf, uint32_t *sessionId); - void CloseEndpoint(HUSB hUSB, bool closeCtrlEp = false); - string GetDevPath(const std::string &path); - bool ReadyForWorkThread(HSession hSession); - int LoopUSBRead(HUSB hUSB); - HSession PrepareNewSession(uint32_t sessionId, uint8_t *pRecvBuf, int recvBytesIO); - bool JumpAntiquePacket(const uint8_t &buf, ssize_t bytes) const; - int SendUSBIOSync(HSession hSession, HUSB hMainUSB, const uint8_t *data, const int length); - int CloseBulkEp(bool bulkInOut, int bulkFd, uv_loop_t *loop); - void ResetOldSession(const uint32_t sessionId); - - HdcUSB usbHandle; - string basePath; // usb device's base path - uint32_t currentSessionId = 0; // USB mode,limit only one session - std::atomic ref = 0; - uv_timer_t checkEP; // server-use - uv_mutex_t sendEP; - bool isAlive = false; - int controlEp = 0; // EP0 -}; -} // namespace Hdc -#endif \ No newline at end of file diff --git a/services/flashd/daemon/flashd_main.cpp b/services/flashd/daemon/flashd_main.cpp index 56e801b8..f5270bc2 100755 --- a/services/flashd/daemon/flashd_main.cpp +++ b/services/flashd/daemon/flashd_main.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include "daemon_common.h" +#include "daemon_updater.h" #include "flashd/flashd.h" #include "updater/updater.h" diff --git a/services/flashd/daemon/jdwp.cpp b/services/flashd/daemon/jdwp.cpp deleted file mode 100755 index 7a3b1526..00000000 --- a/services/flashd/daemon/jdwp.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "jdwp.h" - -namespace Hdc { -HdcJdwp::HdcJdwp(uv_loop_t *loopIn) -{ - Base::ZeroStruct(listenPipe); - listenPipe.data = this; - loop = loopIn; - refCount = 0; - uv_rwlock_init(&lockMapContext); -} - -HdcJdwp::~HdcJdwp() -{ - uv_rwlock_destroy(&lockMapContext); -} - -bool HdcJdwp::ReadyForRelease() -{ - return refCount == 0; -} - -void HdcJdwp::Stop() -{ - auto funcListenPipeClose = [](uv_handle_t *handle) -> void { - HdcJdwp *thisClass = (HdcJdwp *)handle->data; - --thisClass->refCount; - }; - Base::TryCloseHandle((const uv_handle_t *)&listenPipe, funcListenPipeClose); - for (auto &&obj : mapCtxJdwp) { - HCtxJdwp v = obj.second; - FreeContext(v); - } - AdminContext(OP_CLEAR, 0, nullptr); -} - -void *HdcJdwp::MallocContext() -{ - HCtxJdwp ctx = nullptr; - if ((ctx = new ContextJdwp()) == nullptr) { - return nullptr; - } - ctx->thisClass = this; - ctx->pipe.data = ctx; - ++refCount; - return ctx; -} - -// Single thread, two parameters can be used -void HdcJdwp::FreeContext(HCtxJdwp ctx) -{ - if (ctx->finish) { - return; - } - Base::TryCloseHandle((const uv_handle_t *)&ctx->pipe); - ctx->finish = true; - AdminContext(OP_REMOVE, ctx->pid, nullptr); - auto funcReqClose = [](uv_idle_t *handle) -> void { - HCtxJdwp ctx = (HCtxJdwp)handle->data; - --ctx->thisClass->refCount; - Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseIdleCallback); - delete ctx; - }; - Base::IdleUvTask(loop, ctx, funcReqClose); -} - -void HdcJdwp::ReadStream(uv_stream_t *pipe, ssize_t nread, const uv_buf_t *buf) -{ - bool ret = true; - HCtxJdwp ctxJdwp = (HCtxJdwp)pipe->data; - HdcJdwp *thisClass = (HdcJdwp *)ctxJdwp->thisClass; - char *p = ctxJdwp->buf; - uint32_t pid = 0; - - if (nread == UV_ENOBUFS) { // It is definite enough, usually only 4 bytes - ret = false; - WRITE_LOG(LOG_DEBUG, "HdcJdwp::ReadStream IOBuf max"); - } else if (nread == 0) { - return; - } else if (nread < 0 || nread != 4) { // 4 : 4 bytes - ret = false; - WRITE_LOG(LOG_DEBUG, "HdcJdwp::ReadStream program exit pid:%d", ctxJdwp->pid); - } - if (ret) { - pid = atoi(p); - if (pid > 0) { - WRITE_LOG(LOG_DEBUG, "JDWP accept pid:%d", pid); - ctxJdwp->pid = pid; - thisClass->AdminContext(OP_ADD, pid, ctxJdwp); - ret = true; - } - } - Base::ZeroArray(ctxJdwp->buf); - if (!ret) { - thisClass->FreeContext(ctxJdwp); - } -} - -void HdcJdwp::AcceptClient(uv_stream_t *server, int status) -{ - uv_pipe_t *listenPipe = (uv_pipe_t *)server; - HdcJdwp *thisClass = (HdcJdwp *)listenPipe->data; - HCtxJdwp ctxJdwp = (HCtxJdwp)thisClass->MallocContext(); - if (!ctxJdwp) { - return; - } - uv_pipe_init(thisClass->loop, &ctxJdwp->pipe, 1); - if (uv_accept(server, (uv_stream_t *)&ctxJdwp->pipe) < 0) { - WRITE_LOG(LOG_DEBUG, "uv_accept failed"); - thisClass->FreeContext(ctxJdwp); - return; - } - auto funAlloc = [](uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf) -> void { - HCtxJdwp ctxJdwp = (HCtxJdwp)handle->data; - buf->base = (char *)ctxJdwp->buf ; - buf->len = sizeof(ctxJdwp->buf); - }; - uv_read_start((uv_stream_t *)&ctxJdwp->pipe, funAlloc, ReadStream); -} - -// Test bash connnet(UNIX-domain sockets):nc -U path/jdwp-control < hexpid.file -// Test uv connect(pipe): 'uv_pipe_connect' -bool HdcJdwp::JdwpListen() -{ -#ifdef HDC_PCDEBUG - // if test, canbe enable - return true; - const char jdwpCtrlName[] = { 'j', 'd', 'w', 'p', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', 0 }; - unlink(jdwpCtrlName); -#else - const char jdwpCtrlName[] = { '\0', 'j', 'd', 'w', 'p', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', 0 }; -#endif - const int DEFAULT_BACKLOG = 4; - bool ret = false; - while (true) { - uv_pipe_init(loop, &listenPipe, 0); - listenPipe.data = this; - if ((uv_pipe_bind(&listenPipe, jdwpCtrlName))) { - WRITE_LOG(LOG_WARN, "Bind error : %d: %s", errno, strerror(errno)); - return 1; - } - if (uv_listen((uv_stream_t *)&listenPipe, DEFAULT_BACKLOG, AcceptClient)) { - break; - } - ++refCount; - ret = true; - break; - } - // listenPipe close by stop - return ret; -} - -// Working in the main thread, but will be accessed by each session thread, so we need to set thread lock -void *HdcJdwp::AdminContext(const uint8_t op, const uint32_t pid, HCtxJdwp ctxJdwp) -{ - HCtxJdwp hRet = nullptr; - switch (op) { - case OP_ADD: { - uv_rwlock_wrlock(&lockMapContext); - mapCtxJdwp[pid] = ctxJdwp; - uv_rwlock_wrunlock(&lockMapContext); - break; - } - case OP_REMOVE: - uv_rwlock_wrlock(&lockMapContext); - mapCtxJdwp.erase(pid); - uv_rwlock_wrunlock(&lockMapContext); - break; - case OP_QUERY: { - uv_rwlock_rdlock(&lockMapContext); - if (mapCtxJdwp.count(pid)) { - hRet = mapCtxJdwp[pid]; - } - uv_rwlock_rdunlock(&lockMapContext); - break; - } - case OP_CLEAR: { - uv_rwlock_wrlock(&lockMapContext); - mapCtxJdwp.clear(); - uv_rwlock_wrunlock(&lockMapContext); - break; - } - default: - break; - } - return hRet; -} - -// work on main thread -void HdcJdwp::SendCallbackJdwpNewFD(uv_write_t *req, int status) -{ - // It usually works successful, not notify session work - HCtxJdwp ctx = (HCtxJdwp)req->data; - if (status >= 0) { - WRITE_LOG(LOG_DEBUG, "SendCallbackJdwpNewFD successful %d, active jdwp forward", ctx->pid); - } else { - WRITE_LOG(LOG_WARN, "SendCallbackJdwpNewFD failed %d", ctx->pid); - } - // close my process's fd - Base::TryCloseHandle((const uv_handle_t *)&ctx->jvmTCP); - delete req; - --ctx->thisClass->refCount; -} - -// Each session calls the interface through the main thread message queue, which cannot be called directly across -// threads -// work on main thread -bool HdcJdwp::SendJdwpNewFD(uint32_t targetPID, int fd) -{ - bool ret = false; - while (true) { - HCtxJdwp ctx = (HCtxJdwp)AdminContext(OP_QUERY, targetPID, nullptr); - if (!ctx) { - break; - } - ctx->dummy = (uint8_t)'!'; - if (uv_tcp_init(loop, &ctx->jvmTCP)) { - break; - } - if (uv_tcp_open(&ctx->jvmTCP, fd)) { - break; - } - // transfer fd to jvm - // clang-format off - if (Base::SendToStreamEx((uv_stream_t *)&ctx->pipe, (uint8_t *)&ctx->dummy, 1, (uv_stream_t *)&ctx->jvmTCP, - (void *)SendCallbackJdwpNewFD, (const void *)ctx) < 0) { - break; - } - // clang-format on - ++refCount; - ret = true; - WRITE_LOG(LOG_DEBUG, "SendJdwpNewFD successful targetPID:%d fd%d", targetPID, fd); - break; - } - return ret; -} - -// cross thread call begin -bool HdcJdwp::CheckPIDExist(uint32_t targetPID) -{ - HCtxJdwp ctx = (HCtxJdwp)AdminContext(OP_QUERY, targetPID, nullptr); - return ctx != nullptr; -} - -string HdcJdwp::GetProcessList() -{ - string ret; - uv_rwlock_rdlock(&lockMapContext); - for (auto &&v : mapCtxJdwp) { - ret += std::to_string(v.first) + "\n"; - } - uv_rwlock_rdunlock(&lockMapContext); - return ret; -} -// cross thread call finish - -// jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8000 -int HdcJdwp::Initial() -{ - if (!JdwpListen()) { - return ERR_MODULE_JDWP_FAILED; - } - return RET_SUCCESS; -} -} \ No newline at end of file diff --git a/services/flashd/daemon/jdwp.h b/services/flashd/daemon/jdwp.h deleted file mode 100755 index 93b3b902..00000000 --- a/services/flashd/daemon/jdwp.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_JDWP_H -#define HDC_JDWP_H -#include "daemon_common.h" - -namespace Hdc { -class HdcJdwp { -public: - HdcJdwp(uv_loop_t *loopIn); - virtual ~HdcJdwp(); - int Initial(); - void Stop(); - bool ReadyForRelease(); - - string GetProcessList(); - bool SendJdwpNewFD(uint32_t targetPID, int fd); - bool CheckPIDExist(uint32_t targetPID); - -private: - struct ContextJdwp { - uint32_t pid; - uv_pipe_t pipe; - HdcJdwp *thisClass; - bool finish; - char buf[sizeof(uint32_t)]; - uint8_t dummy; - uv_tcp_t jvmTCP; - }; - using HCtxJdwp = struct ContextJdwp *; - - bool JdwpListen(); - static void AcceptClient(uv_stream_t *server, int status); - static void ReadStream(uv_stream_t *pipe, ssize_t nread, const uv_buf_t *buf); - static void SendCallbackJdwpNewFD(uv_write_t *req, int status); - void *MallocContext(); - void FreeContext(HCtxJdwp ctx); - void *AdminContext(const uint8_t op, const uint32_t pid, HCtxJdwp ctxJdwp); - - uv_loop_t *loop; - uv_pipe_t listenPipe; - uint32_t refCount; - map mapCtxJdwp; - uv_rwlock_t lockMapContext; -}; -} // namespace Hdc -#endif \ No newline at end of file diff --git a/services/flashd/daemon/main.cpp b/services/flashd/daemon/main.cpp deleted file mode 100755 index fcd82e87..00000000 --- a/services/flashd/daemon/main.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "daemon_common.h" -using namespace Hdc; - -static bool g_enableUsb = false; -static bool g_enableTcp = false; -static bool g_rootRun = false; -static bool g_backgroundRun = false; -namespace Hdc { -bool RestartDaemon(bool forkchild) -{ - char path[256] = ""; - size_t nPathSize = 256; - uv_exepath(path, &nPathSize); - execl(path, "hdcd", forkchild ? "-forkchild" : nullptr, nullptr); - return true; -} - -bool ForkChildCheck(int argc, const char *argv[]) -{ - // hdcd #service start forground - // hdcd -b #service start backgroundRun - // hdcd -fork #fork - char modeSet[BUF_SIZE_TINY] = ""; - Base::GetHdcProperty("persist.hdc.mode", modeSet, BUF_SIZE_TINY); - Base::PrintMessage("Background mode, persist.hdc.mode"); - string workMode = modeSet; - workMode = Base::Trim(workMode); - if (workMode == CMDSTR_TMODE_TCP) { - WRITE_LOG(LOG_DEBUG, "Property enable TCP"); - g_enableTcp = true; - } else if (workMode == CMDSTR_TMODE_USB) { - WRITE_LOG(LOG_DEBUG, "Property enable USB"); - g_enableUsb = true; - } else if (workMode == "all") { - WRITE_LOG(LOG_DEBUG, "Property enable USB and TCP"); - g_enableUsb = true; - g_enableTcp = true; - } else { - WRITE_LOG(LOG_DEBUG, "Default USB mode"); - g_enableUsb = true; - } - if (argc == CMD_ARG1_COUNT) { - if (!strcmp(argv[1], "-forkchild")) { - g_backgroundRun = false; // forkchild,Forced foreground - } else if (!strcmp(argv[1], "-b")) { - g_backgroundRun = true; - } - } - return true; -} - -int BackgroundRun() -{ - pid_t pc = fork(); // create process as daemon process - if (pc < 0) { - return -1; - } else if (!pc) { - int i; - const int MAX_NUM = 64; - for (i = 0; i < MAX_NUM; ++i) { - close(i); - } - RestartDaemon(true); - } else { // >0 orig process - } - return 0; -} - -string DaemonUsage() -{ - string ret; - ret = "\n Harmony device connector daemon(HDCD) Usage: hdcd [options]...\n\n" - "\n" - "general options:\n" - " -h - Print help\n" - " -l 0-5 - Print runtime log\n" - "\n" - "daemon mode options:\n" - " -b - Daemon run in background/fork mode\n" - " -u - Enable USB mode\n" - " -t - Enable TCP mode\n"; - return ret; -} - -bool GetDaemonCommandlineOptions(int argc, const char *argv[]) -{ - int ch; - // hdcd -l4 ... - WRITE_LOG(LOG_DEBUG, "Fgcli mode"); - // Both settings are running with parameters - while ((ch = getopt(argc, (char *const *)argv, "utl:")) != -1) { - switch (ch) { - case 'l': { - int logLevel = atoi(optarg); - if (logLevel < 0 || logLevel > LOG_LAST) { - WRITE_LOG(LOG_DEBUG, "Loglevel error!\n"); - return -1; - } - Base::SetLogLevel(logLevel); - break; - } - case 'u': { - Base::PrintMessage("Option USB enabled"); - g_enableUsb = true; - break; - } - case 't': { - Base::PrintMessage("Option TCP enabled"); - g_enableTcp = true; - break; - } - default: - Base::PrintMessage("Option:%c non-supported!", ch); - exit(0); - break; - } - } - return true; -} - -void NeedDropPriv() -{ - char droprootSet[BUF_SIZE_TINY] = ""; - Base::GetHdcProperty("persist.hdc.root", droprootSet, BUF_SIZE_TINY); - droprootSet[sizeof(droprootSet) - 1] = '\0'; - string rootMode = droprootSet; - if (Base::Trim(rootMode) == "1") { - setuid(0); - g_rootRun = true; - WRITE_LOG(LOG_DEBUG, "Root run"); - } else if (Base::Trim(rootMode) == "0") { - setuid(AID_SHELL); - } -} -} // namespace Hdc - -#ifndef UNIT_TEST -// daemon running with default behavior. options also can be given to custom its behavior including b/t/u/l etc. -int main(int argc, const char *argv[]) -{ - // check property - if (argc == 2 && !strcmp(argv[1], "-h")) { - string usage = DaemonUsage(); - fprintf(stderr, "%s", usage.c_str()); - return 0; - } - if (argc == CMD_ARG1_COUNT && !strcmp(argv[1], "-v")) { - string ver = Hdc::Base::GetVersion(); - fprintf(stderr, "%s\n", ver.c_str()); - return 0; - } - if (argc == 1 || (argc == CMD_ARG1_COUNT && (!strcmp(argv[1], "-forkchild") || !strcmp(argv[1], "-b")))) { - Base::SetLogLevel(LOG_LEVEL_FULL); - ForkChildCheck(argc, argv); - } else { - GetDaemonCommandlineOptions(argc, argv); - } - if (!g_enableTcp && !g_enableUsb) { - Base::PrintMessage("Both TCP and USB are disable, cannot run continue\n"); - return -1; - } - if (g_backgroundRun) { - return BackgroundRun(); - } - NeedDropPriv(); - umask(0); - signal(SIGPIPE, SIG_IGN); - signal(SIGCHLD, SIG_IGN); - WRITE_LOG(LOG_DEBUG, "HdcDaemon main run"); - HdcDaemon daemon(false); - daemon.InitMod(g_enableTcp, g_enableUsb); - daemon.WorkerPendding(); - bool wantRestart = daemon.WantRestart(); - WRITE_LOG(LOG_DEBUG, "Daemon finish"); - // There is no daemon, we can only restart myself. - if (g_rootRun && wantRestart) { - // just root can self restart, low privilege will be exit and start by service(root) - WRITE_LOG(LOG_INFO, "Daemon restart"); - RestartDaemon(false); - } - return 0; -} -#endif diff --git a/services/flashd/daemon/shell.cpp b/services/flashd/daemon/shell.cpp deleted file mode 100755 index 8a434221..00000000 --- a/services/flashd/daemon/shell.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "shell.h" -#include - -namespace Hdc { -std::mutex HdcShell::mutexPty; - -HdcShell::HdcShell(HTaskInfo hTaskInfo) - : HdcTaskBase(hTaskInfo) -{ - childShell = nullptr; - fdPTY = 0; -} - -HdcShell::~HdcShell() -{ - WRITE_LOG(LOG_DEBUG, "HdcShell deinit"); -}; - -bool HdcShell::ReadyForRelease() -{ - if (!HdcTaskBase::ReadyForRelease()) { - return false; - } - if (!childReady) { - return true; - } - if (!childShell->ReadyForRelease()) { - return false; - } - delete childShell; - childShell = nullptr; - if (fdPTY > 0) { - close(fdPTY); - } - return true; -} - -void HdcShell::StopTask() -{ - singalStop = true; - WRITE_LOG(LOG_DEBUG, "HdcShell::StopTask"); - if (!childReady) { - return; - } - if (childShell) { - childShell->StopWork(false, nullptr); - } - kill(pidShell, SIGKILL); - int status; - waitpid(pidShell, &status, 0); - WRITE_LOG(LOG_DEBUG, "StopTask, kill pidshell:%d", pidShell); -}; - -bool HdcShell::SpecialSignal(uint8_t ch) -{ - const uint8_t TXT_SIGNAL_ETX = 0x3; - bool ret = true; - switch (ch) { - case TXT_SIGNAL_ETX: { // Ctrl+C - pid_t tpgid = tcgetpgrp(fdPTY); - kill(tpgid, SIGINT); - break; - } - default: - ret = false; - break; - } - return ret; -} - -bool HdcShell::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) -{ - switch (command) { - case CMD_SHELL_INIT: { // initial - if (StartShell()) { - LogMsg(MSG_FAIL, "Shell initialize failed"); - } - break; - } - case CMD_SHELL_DATA: - if (!childReady) { - WRITE_LOG(LOG_DEBUG, "Shell not running"); - return false; - } - if (payloadSize == 1 && SpecialSignal(payload[0])) { - } else { - childShell->Write(payload, payloadSize); - } - break; - default: - break; - } - return true; -} - -int HdcShell::ChildForkDo(int pts, const char *cmd, const char *arg0, const char *arg1) -{ - dup2(pts, STDIN_FILENO); - dup2(pts, STDOUT_FILENO); - dup2(pts, STDERR_FILENO); - close(pts); - string text = "/proc/self/oom_score_adj"; - int fd = 0; - if ((fd = open(text.c_str(), O_WRONLY)) >= 0) { - write(fd, "0", 1); - close(fd); - } - char *env = nullptr; - if ((env = getenv("HOME")) && chdir(env) < 0) { - } - execl(cmd, cmd, arg0, arg1, nullptr); - _Exit(1); - return 0; -} - -int HdcShell::ShellFork(const char *cmd, const char *arg0, const char *arg1) -{ - pid_t pid; - pid = fork(); - if (pid < 0) { - WRITE_LOG(LOG_DEBUG, "Fork shell failed:%s", strerror(errno)); - return ERR_GENERIC; - } - if (pid == 0) { - HdcShell::mutexPty.unlock(); - setsid(); - close(ptm); - int pts = 0; - if ((pts = open(devname, O_RDWR | O_CLOEXEC)) < 0) { - return -1; - } - ChildForkDo(pts, cmd, arg0, arg1); - // proc finish - } else { - return pid; - } - return 0; -} - -int HdcShell::CreateSubProcessPTY(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) -{ - ptm = open(devPTMX.c_str(), O_RDWR | O_CLOEXEC); - if (ptm < 0) { - WRITE_LOG(LOG_DEBUG, "Cannot open ptmx, error:%s", strerror(errno)); - return ERR_FILE_OPEN; - } - if (grantpt(ptm) || unlockpt(ptm)) { - WRITE_LOG(LOG_DEBUG, "Cannot open2 ptmx, error:%s", strerror(errno)); - close(ptm); - return ERR_API_FAIL; - } - if (ptsname_r(ptm, devname, sizeof(devname)) != 0) { - WRITE_LOG(LOG_DEBUG, "Trouble with ptmx, error:%s", strerror(errno)); - close(ptm); - return ERR_API_FAIL; - } - *pid = ShellFork(cmd, arg0, arg1); - return ptm; -} - -bool HdcShell::FinishShellProc(const void *context, const bool result, const string exitMsg) -{ - WRITE_LOG(LOG_DEBUG, "FinishShellProc finish"); - HdcShell *thisClass = (HdcShell *)context; - thisClass->TaskFinish(); - --thisClass->refCount; - return true; -}; - -bool HdcShell::ChildReadCallback(const void *context, uint8_t *buf, const int size) -{ - HdcShell *thisClass = (HdcShell *)context; - return thisClass->SendToAnother(CMD_KERNEL_ECHO_RAW, (uint8_t *)buf, size); -}; - -int HdcShell::StartShell() -{ - WRITE_LOG(LOG_DEBUG, "StartShell..."); - int ret = 0; - HdcShell::mutexPty.lock(); - do { - if ((fdPTY = CreateSubProcessPTY(Base::GetShellPath().c_str(), "-", 0, &pidShell)) < 0) { - ret = ERR_PROCESS_SUB_FAIL; - break; - } - childShell = new HdcFileDescriptor(loopTask, fdPTY, this, ChildReadCallback, FinishShellProc); - if (!childShell->StartWork()) { - ret = ERR_API_FAIL; - break; - } - childReady = true; - ++refCount; - } while (false); - if (ret != RET_SUCCESS) { - if (pidShell > 0) { - kill(pidShell, SIGKILL); - } - // fdPTY close by ~clase - } - HdcShell::mutexPty.unlock(); - return ret; -} -} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/daemon/shell.h b/services/flashd/daemon/shell.h deleted file mode 100755 index 1c2cda83..00000000 --- a/services/flashd/daemon/shell.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_SHELL_H -#define HDC_SHELL_H -#include "daemon_common.h" -#include - -namespace Hdc { -class HdcShell : public HdcTaskBase { -public: - HdcShell(HTaskInfo hTaskInfo); - virtual ~HdcShell(); - bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); - void StopTask(); - bool ReadyForRelease(); - -private: - static bool FinishShellProc(const void *context, const bool result, const string exitMsg); - static bool ChildReadCallback(const void *context, uint8_t *buf, const int size); - int StartShell(); - int CreateSubProcessPTY(const char *cmd, const char *arg0, const char *arg1, pid_t *pid); - int ChildForkDo(int pts, const char *cmd, const char *arg0, const char *arg1); - bool SpecialSignal(uint8_t ch); - int ShellFork(const char *cmd, const char *arg0, const char *arg1); - - HdcFileDescriptor *childShell; - pid_t pidShell = 0; - int fdPTY; - int ptm = 0; - const string devPTMX = "/dev/ptmx"; - static std::mutex mutexPty; - char devname[BUF_SIZE_SMALL] = ""; -}; -} // namespace Hdc -#endif \ No newline at end of file diff --git a/services/flashd/daemon/usb_ffs.h b/services/flashd/daemon/usb_ffs.h deleted file mode 100755 index 1998daaf..00000000 --- a/services/flashd/daemon/usb_ffs.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_USBFFS_H -#define HDC_USBFFS_H -// clang-format off -#include -#include "daemon_common.h" -// clang-format on - -namespace Hdc { -constexpr auto HDC_USBDR_SND = 0x0; -constexpr auto HDC_USBDR_RCV = 0x80; -constexpr auto HDC_USBMD_BLK = 0X02; -constexpr auto HDC_USBMD_RCV = 0X03; -constexpr auto HDC_CLASS = 0xff; -constexpr auto HDC_SUBCLASS = 0x50; -constexpr auto HDC_FSPKT_SIZE_MAX = 64; -constexpr auto HDC_HSPKT_SIZE_MAX = 512; -constexpr uint16_t HDC_SSPKT_SIZE_MAX = 1024; -constexpr auto USB_FFS_BASE = "/dev/usb-ffs/"; -constexpr auto HDC_USBTF_DEV = 0x01; -constexpr auto HDC_USBTF_CFG = 0x02; -constexpr auto HDC_USBTF_STR = 0x03; -constexpr auto HDC_USBTF_ITF = 0x04; -constexpr auto HDC_USBTF_EPS = 0x05; - -#define SHORT_LE(x) htole16(x) -#define LONG_LE(x) htole32(x) -#define HDC_INTERFACE_NAME "HDC Interface" - -struct UsbFunctionDesc { - struct usb_interface_descriptor ifDesc; - struct usb_endpoint_descriptor_no_audio from; - struct usb_endpoint_descriptor_no_audio to; -} __attribute__((packed)); - -static const struct { - struct usb_functionfs_strings_head head; - struct { - __le16 code; - const char name[sizeof(HDC_INTERFACE_NAME)]; - } __attribute__((packed)) firstItem; -} __attribute__((packed)) USB_FFS_VALUE = { - .head = - { - .magic = LONG_LE(FUNCTIONFS_STRINGS_MAGIC), - .length = LONG_LE(sizeof(USB_FFS_VALUE)), - .str_count = LONG_LE(1), - .lang_count = LONG_LE(1), - }, - .firstItem = - { - SHORT_LE(0x0409), - HDC_INTERFACE_NAME, - }, -}; - -struct UsbFunctionfsDescsHeadOld { - __le32 magic; - __le32 length; - __le32 config1Count; - __le32 config2Count; -} __attribute__((packed)); - -struct UsbFuncConfig { - struct usb_interface_descriptor ifDesc; - struct usb_endpoint_descriptor_no_audio from; - struct usb_ss_ep_comp_descriptor pairFrom; - struct usb_endpoint_descriptor_no_audio to; - struct usb_ss_ep_comp_descriptor pairTo; -} __attribute__((packed)); - -static struct UsbFuncConfig config3 = { - .ifDesc = { - .bLength = sizeof(config3.ifDesc), - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bNumEndpoints = 2, - .bInterfaceClass = HDC_CLASS, - .bInterfaceSubClass = HDC_SUBCLASS, - .bInterfaceProtocol = VER_PROTOCOL, - .iInterface = 1 - }, - .from = { - .bLength = sizeof(config3.from), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 1 | USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = HDC_SSPKT_SIZE_MAX, - }, - .pairFrom = { - .bLength = sizeof(config3.pairFrom), - .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, - .bMaxBurst = 4, - }, - .to = { - .bLength = sizeof(config3.to), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 2 | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = HDC_SSPKT_SIZE_MAX, - }, - .pairTo = { - .bLength = sizeof(config3.pairTo), - .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, - .bMaxBurst = 4, - }, -}; - -static struct UsbFunctionDesc config1 = { - .ifDesc = { - .bLength = sizeof(config1.ifDesc), - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bNumEndpoints = 2, - .bInterfaceClass = HDC_CLASS, - .bInterfaceSubClass = HDC_SUBCLASS, - .bInterfaceProtocol = VER_PROTOCOL, - .iInterface = 1 - }, - .from = { - .bLength = sizeof(config1.from), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 1 | USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = HDC_FSPKT_SIZE_MAX, - }, - .to = { - .bLength = sizeof(config1.to), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 2 | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = HDC_FSPKT_SIZE_MAX, - }, -}; - -static struct UsbFunctionDesc config2 = { - .ifDesc = { - .bLength = sizeof(config2.ifDesc), - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bNumEndpoints = 2, - .bInterfaceClass = HDC_CLASS, - .bInterfaceSubClass = HDC_SUBCLASS, - .bInterfaceProtocol = VER_PROTOCOL, - .iInterface = 1 - }, - .from = { - .bLength = sizeof(config2.from), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 1 | USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = HDC_HSPKT_SIZE_MAX, - }, - .to = { - .bLength = sizeof(config2.to), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 2 | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = HDC_HSPKT_SIZE_MAX, - }, -}; - -static const struct { - struct usb_functionfs_descs_head_v2 head; - __le32 config1Count; - __le32 config2Count; - __le32 config3Count; - __le32 configWosCount; - struct UsbFunctionDesc config1Desc, config2Desc; - struct UsbFuncConfig config3Desc; - struct usb_os_desc_header wosHead; - struct usb_ext_compat_desc wosDesc; -} __attribute__((packed)) USB_FFS_DESC = { - .head = - { - .magic = LONG_LE(FUNCTIONFS_DESCRIPTORS_MAGIC_V2), - .length = LONG_LE(sizeof(USB_FFS_DESC)), - .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC | - FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC - }, - .config1Count = 3, - .config2Count = 3, - .config3Count = 5, - .configWosCount = 1, - .config1Desc = config1, - .config2Desc = config2, - .config3Desc = config3, - .wosHead = { - .interface = 1, - .dwLength = LONG_LE(sizeof(USB_FFS_DESC.wosHead) + sizeof(USB_FFS_DESC.wosDesc)), - .bcdVersion = SHORT_LE(1), - .wIndex = SHORT_LE(4), - .bCount = 1, - .Reserved = 0, - }, - .wosDesc = { - .bFirstInterfaceNumber = 0, - .Reserved1 = 1, - .CompatibleID = { 'W', 'I', 'N', 'U', 'S', 'B', '\0', '\0'}, - .SubCompatibleID = {0}, - .Reserved2 = {0}, - } -}; -} // namespace Hdc -#endif diff --git a/services/flashd/host/client.cpp b/services/flashd/host/client.cpp index efefabc5..9dc38afe 100755 --- a/services/flashd/host/client.cpp +++ b/services/flashd/host/client.cpp @@ -13,9 +13,12 @@ * limitations under the License. */ #include "client.h" + +#include "host_updater.h" #include "server.h" namespace Hdc { +bool terminalStateChange = false; HdcClient::HdcClient(const bool serverOrClient, const string &addrString, uv_loop_t *loopMainIn) : HdcChannelBase(serverOrClient, addrString, loopMainIn) { @@ -26,9 +29,8 @@ HdcClient::HdcClient(const bool serverOrClient, const string &addrString, uv_loo HdcClient::~HdcClient() { #ifndef _WIN32 - if (terminalChanged) { + if (terminalStateChange) { tcsetattr(STDIN_FILENO, TCSAFLUSH, &terminalState); - terminalChanged = false; } #endif Base::TryCloseLoop(loopMain, "ExecuteCommand finish"); @@ -217,8 +219,22 @@ void HdcClient::CommandWorker(uv_timer_t *handle) WRITE_LOG(LOG_DEBUG, "Cmd \'%s\' has been canceld", thisClass->command.c_str()); return; } - if (closeInput) { - thisClass->CloseInput(); + while (closeInput) { +#ifndef _WIN32 + if (tcgetattr(STDIN_FILENO, &thisClass->terminalState)) { + break; + } + termios tio; + if (tcgetattr(STDIN_FILENO, &tio)) { + break; + } + cfmakeraw(&tio); + tio.c_cc[VTIME] = 0; + tio.c_cc[VMIN] = 1; + tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); + terminalStateChange = true; +#endif + break; } thisClass->Send(thisClass->channel->channelId, (uint8_t *)thisClass->command.c_str(), thisClass->command.size() + 1); @@ -253,12 +269,21 @@ void HdcClient::ModifyTty(bool setOrRestore, uv_tty_t *tty) #ifdef _WIN32 uv_tty_set_mode(tty, UV_TTY_MODE_RAW); #else - CloseInput(); + if (tcgetattr(STDIN_FILENO, &terminalState)) { + return; + } + termios tio; + if (tcgetattr(STDIN_FILENO, &tio)) { + return; + } + cfmakeraw(&tio); + tio.c_cc[VTIME] = 0; + tio.c_cc[VMIN] = 1; + tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); #endif } else { #ifndef _WIN32 tcsetattr(STDIN_FILENO, TCSAFLUSH, &terminalState); - terminalChanged = false; #endif } } @@ -352,20 +377,4 @@ int HdcClient::ReadChannel(HChannel hChannel, uint8_t *buf, const int bytesIO) fflush(stdout); return 0; } - -void HdcClient::CloseInput() -{ -#ifndef _WIN32 - if (tcgetattr(STDIN_FILENO, &terminalState)) - return; - termios tio; - if (tcgetattr(STDIN_FILENO, &tio)) - return; - cfmakeraw(&tio); - tio.c_cc[VTIME] = 0; - tio.c_cc[VMIN] = 1; - tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); - terminalChanged = true; -#endif -} } // namespace Hdc diff --git a/services/flashd/host/client.h b/services/flashd/host/client.h deleted file mode 100755 index 3efc5700..00000000 --- a/services/flashd/host/client.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_CLIENT_H -#define HDC_CLIENT_H -#include "host_common.h" - -namespace Hdc { -class HdcClient : public HdcChannelBase { -public: - HdcClient(const bool serverOrClient, const string &addrString, uv_loop_t *loopMainIn); - virtual ~HdcClient(); - int Initial(const string &connectKeyIn); - int ExecuteCommand(const string &commandIn); - int CtrlServiceWork(const char *commandIn); - void CloseInput(); -protected: -private: - static void DoCtrlServiceWork(uv_check_t *handle); - static void Connect(uv_connect_t *connection, int status); - static void AllocStdbuf(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf); - static void ReadStd(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); - static void CommandWorker(uv_timer_t *handle); - int ConnectServerForClient(const char *ip, uint16_t port); - int ReadChannel(HChannel hChannel, uint8_t *buf, const int bytesIO); - int PreHandshake(HChannel hChannel, const uint8_t *buf); - string AutoConnectKey(string &doCommand, const string &preConnectKey) const; - uint32_t GetLastPID(); - bool StartKillServer(const char *cmd, bool startOrKill); - void BindLocalStd(); - void BindLocalStd(HChannel hChannel); - void ModifyTty(bool setOrRestore, uv_tty_t *tty); - void NotifyInstanceChannelFree(HChannel hChannel); - -#ifndef _WIN32 - termios terminalState; - bool terminalChanged = false; -#endif - string connectKey; - string command; - uint16_t debugRetryCount; - bool bShellInteractive = false; - uv_timer_t waitTimeDoCmd; - uv_check_t ctrlServerWork; - HChannel channel; -}; -} // namespace Hdc -#endif \ No newline at end of file diff --git a/services/flashd/host/host_app.cpp b/services/flashd/host/host_app.cpp deleted file mode 100755 index 938af005..00000000 --- a/services/flashd/host/host_app.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "host_app.h" - -namespace Hdc { -HdcHostApp::HdcHostApp(HTaskInfo hTaskInfo) - : HdcTransferBase(hTaskInfo) -{ - commandBegin = CMD_APP_BEGIN; - commandData = CMD_APP_DATA; -} - -HdcHostApp::~HdcHostApp() -{ -} - -bool HdcHostApp::BeginInstall(CtxFile *context, const char *command) -{ - int argc = 0; - bool ret = false; - string options; - char **argv = Base::SplitCommandToArgs(command, &argc); - if (argc < 1) { - goto Finish; - } - - for (int i = 0; i < argc; ++i) { - if (!strcmp(argv[i], CMD_OPTION_CLIENTCWD.c_str())) { - if (i + 1 < argc) { - context->transferConfig.clientCwd = argv[i + 1]; - i += 1; // add content index - } - } else if (!strncmp(argv[i], "-", 1)) { - if (options.size()) { - options += " "; - } - options += argv[i]; - } else { - string path = argv[i]; - ExtractRelativePath(context->transferConfig.clientCwd, path); - if (MatchPackageExtendName(path, ".hap")) { - context->taskQueue.push_back(path); - } else { - GetSubFiles(argv[i], ".hap", &context->taskQueue); - } - } - } - if (!context->taskQueue.size()) { - LogMsg(MSG_FAIL, "Not any installation package was found"); - return false; - } - // remove repeate - sort(context->taskQueue.begin(), context->taskQueue.end()); - context->taskQueue.erase(unique(context->taskQueue.begin(), context->taskQueue.end()), context->taskQueue.end()); - - context->transferConfig.options = options; - context->transferConfig.functionName = CMDSTR_APP_INSTALL; - RunQueue(context); - ret = true; -Finish: - if (argv) { - delete[]((char *)argv); - } - return ret; -} - -bool HdcHostApp::BeginSideload(CtxFile *context, const char *localPath) -{ - bool ret = false; - context->transferConfig.functionName = CMDSTR_APP_SIDELOAD; - context->taskQueue.push_back(localPath); - RunQueue(context); - ret = true; - return ret; -} - -void HdcHostApp::RunQueue(CtxFile *context) -{ - ++refCount; - context->localPath = context->taskQueue.back(); - uv_fs_open(loopTask, &context->fsOpenReq, context->localPath.c_str(), O_RDONLY, 0, OnFileOpen); - context->master = true; -} - -void HdcHostApp::CheckMaster(CtxFile *context) -{ - uv_fs_t fs; - Base::ZeroStruct(fs.statbuf); - uv_fs_fstat(nullptr, &fs, context->fsOpenReq.result, nullptr); - context->transferConfig.fileSize = fs.statbuf.st_size; - uv_fs_req_cleanup(&fs); - - context->transferConfig.optionalName - = Base::GetRandomString(9); // Prevent the name of illegal APP leads to pm unable to install - if (context->localPath.find(".hap") != (size_t)-1) { - context->transferConfig.optionalName += ".hap"; - } else { - context->transferConfig.optionalName += ".bundle"; - } - string bufString = SerialStruct::SerializeToString(context->transferConfig); - SendToAnother(CMD_APP_CHECK, (uint8_t *)bufString.c_str(), bufString.size()); -} - -bool HdcHostApp::CheckInstallContinue(AppModType mode, bool lastResult, const char *msg) -{ - string modeDesc; - switch (mode) { - case APPMOD_INSTALL: - modeDesc = "App install"; - break; - case APPMOD_UNINSTALL: - modeDesc = "App uninstall"; - break; - case APPMOD_SIDELOAD: - modeDesc = "Side load"; - break; - default: - modeDesc = "Unknow"; - break; - } - ctxNow.taskQueue.pop_back(); - LogMsg(MSG_INFO, "%s path:%s, queuesize:%d, msg:%s", modeDesc.c_str(), ctxNow.localPath.c_str(), - ctxNow.taskQueue.size(), msg); - if (singalStop || !ctxNow.taskQueue.size()) { - LogMsg(MSG_OK, "AppMod finish"); - return false; - } - RunQueue(&ctxNow); - return true; -} - -bool HdcHostApp::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) -{ - if (!HdcTransferBase::CommandDispatch(command, payload, payloadSize)) { - return false; - } - bool ret = true; - constexpr int cmdOffset = 2; - switch (command) { - case CMD_APP_INIT: { - ret = BeginInstall(&ctxNow, (const char *)payload); - break; - } - case CMD_APP_FINISH: { - AppModType mode = (AppModType)payload[0]; - bool result = (bool)payload[1]; - string s(reinterpret_cast(payload + cmdOffset), payloadSize - cmdOffset); - ret = CheckInstallContinue(mode, result, s.c_str()); - break; - } - case CMD_APP_UNINSTALL: { - SendToAnother(CMD_APP_UNINSTALL, payload, payloadSize); - ctxNow.taskQueue.push_back(reinterpret_cast(payload)); // just compatible - break; - } - case CMD_APP_SIDELOAD: { - BeginSideload(&ctxNow, (const char *)payload); - break; - } - default: - break; - } - return ret; -}; -} \ No newline at end of file diff --git a/services/flashd/host/host_app.h b/services/flashd/host/host_app.h deleted file mode 100755 index ad3c8845..00000000 --- a/services/flashd/host/host_app.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_HOST_APP_H -#define HDC_HOST_APP_H -#include "host_common.h" - -namespace Hdc { -class HdcHostApp : public HdcTransferBase { -public: - HdcHostApp(HTaskInfo hTaskInfo); - virtual ~HdcHostApp(); - bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); - -private: - bool BeginInstall(CtxFile *context, const char *command); - void CheckMaster(CtxFile *context); - bool CheckInstallContinue(AppModType mode, bool lastResult, const char *msg); - void RunQueue(CtxFile *context); - bool BeginSideload(CtxFile *context, const char *localPath); -}; -} -#endif \ No newline at end of file diff --git a/services/flashd/host/host_common.h b/services/flashd/host/host_common.h deleted file mode 100755 index e6be2ba5..00000000 --- a/services/flashd/host/host_common.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_HOST_COMMON_H -#define HDC_HOST_COMMON_H - -// clang-format off -#include "../common/common.h" -#include "../common/file.h" -#include "../common/transfer.h" -#include "../common/forward.h" -#include "../common/async_cmd.h" -#include "../common/serial_struct.h" - -#include "host_tcp.h" -#include "host_usb.h" -#include "translate.h" -#include "server_for_client.h" -#include "client.h" -#include "host_app.h" -#include "host_forward.h" -#include "host_unity.h" -#include "host_updater.h" -// clang-format on - -#endif \ No newline at end of file diff --git a/services/flashd/host/host_forward.cpp b/services/flashd/host/host_forward.cpp deleted file mode 100755 index 72cd3f83..00000000 --- a/services/flashd/host/host_forward.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "host_forward.h" - -namespace Hdc { -HdcHostForward::HdcHostForward(HTaskInfo hTaskInfo) - : HdcForwardBase(hTaskInfo) -{ -} - -HdcHostForward::~HdcHostForward() -{ -} -} \ No newline at end of file diff --git a/services/flashd/host/host_forward.h b/services/flashd/host/host_forward.h deleted file mode 100755 index 5c984106..00000000 --- a/services/flashd/host/host_forward.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_HOST_FORWARD_H -#define HDC_HOST_FORWARD_H -#include "host_common.h" - -namespace Hdc { -class HdcHostForward : public HdcForwardBase { -public: - HdcHostForward(HTaskInfo hTaskInfo); - virtual ~HdcHostForward(); - -private: -}; -} // namespace Hdc - -#endif \ No newline at end of file diff --git a/services/flashd/host/host_tcp.cpp b/services/flashd/host/host_tcp.cpp deleted file mode 100755 index 49463605..00000000 --- a/services/flashd/host/host_tcp.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "host_tcp.h" -#include "server.h" - -namespace Hdc { -HdcHostTCP::HdcHostTCP(const bool serverOrDaemonIn, void *ptrMainBase) - : HdcTCPBase(serverOrDaemonIn, ptrMainBase) -{ - broadcastFindWorking = false; -} - -HdcHostTCP::~HdcHostTCP() -{ - WRITE_LOG(LOG_DEBUG, "~HdcHostTCP"); -} - -void HdcHostTCP::Stop() -{ -} - -void HdcHostTCP::RecvUDPEntry(const sockaddr *addrSrc, uv_udp_t *handle, const uv_buf_t *rcvbuf) -{ - char bufString[BUF_SIZE_TINY]; - uint16_t port = 0; - char *p = strstr(rcvbuf->base, "-"); - if (!p) { - return; - } - port = atoi(p + 1); - if (!port) { - return; - } - uv_ip4_name((sockaddr_in *)addrSrc, bufString, sizeof(bufString)); - string addrPort = string(bufString); - addrPort += string(":") + std::to_string(port); - lstDaemonResult.push_back(addrPort); -} - -void HdcHostTCP::BroadcastTimer(uv_idle_t *handle) -{ - uv_stop(handle->loop); -} - -// Executive Administration Network Broadcast Discovery, broadcastLanIP==which interface to broadcast -void HdcHostTCP::BroadcatFindDaemon(const char *broadcastLanIP) -{ - if (broadcastFindWorking) { - return; - } - broadcastFindWorking = true; - lstDaemonResult.clear(); - - uv_loop_t loopBroadcast; - uv_loop_init(&loopBroadcast); - struct sockaddr_in addr; - uv_udp_send_t req; - uv_udp_t client; - // send - uv_ip4_addr(broadcastLanIP, 0, &addr); - uv_udp_init(&loopBroadcast, &client); - uv_udp_bind(&client, (const struct sockaddr *)&addr, 0); - uv_udp_set_broadcast(&client, 1); - uv_ip4_addr("255.255.255.255", DEFAULT_PORT, &addr); - uv_buf_t buf = uv_buf_init((char *)HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size()); - uv_udp_send(&req, &client, &buf, 1, (const struct sockaddr *)&addr, nullptr); - // recv - uv_udp_t server; - server.data = this; - uv_ip4_addr(broadcastLanIP, DEFAULT_PORT, &addr); - uv_udp_init(&loopBroadcast, &server); - uv_udp_bind(&server, (const struct sockaddr *)&addr, UV_UDP_REUSEADDR); - uv_udp_recv_start(&server, AllocStreamUDP, RecvUDP); - // find timeout - uv_timer_t tLastCheck; - uv_timer_init(&loopBroadcast, &tLastCheck); - uv_timer_start(&tLastCheck, (uv_timer_cb)BroadcastTimer, TIME_BASE, 0); // timeout debug 1s - - uv_run(&loopBroadcast, UV_RUN_DEFAULT); - uv_loop_close(&loopBroadcast); - broadcastFindWorking = false; -} - -void HdcHostTCP::Connect(uv_connect_t *connection, int status) -{ - HSession hSession = (HSession)connection->data; - delete connection; - HdcSessionBase *ptrConnect = (HdcSessionBase *)hSession->classInstance; - auto ctrl = ptrConnect->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0); - if (status < 0) { - goto Finish; - } - if ((hSession->fdChildWorkTCP = Base::DuplicateUvSocket(&hSession->hWorkTCP)) < 0) { - goto Finish; - } - uv_read_stop((uv_stream_t *)&hSession->hWorkTCP); - Base::SetTcpOptions((uv_tcp_t *)&hSession->hWorkTCP); - WRITE_LOG(LOG_DEBUG, "HdcHostTCP::Connect"); - Base::StartWorkThread(&ptrConnect->loopMain, ptrConnect->SessionWorkThread, Base::FinishWorkThread, hSession); - // wait for thread up - while (hSession->childLoop.active_handles == 0) { - uv_sleep(MINOR_TIMEOUT); - } - Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); - return; -Finish: - WRITE_LOG(LOG_FATAL, "Connect failed"); - ptrConnect->FreeSession(hSession->sessionId); -} - -HSession HdcHostTCP::ConnectDaemon(const string &connectKey) -{ - char ip[BUF_SIZE_TINY] = ""; - uint16_t port = 0; - if (Base::ConnectKey2IPPort(connectKey.c_str(), ip, &port) < 0) { - return nullptr; - } - - HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase; - HSession hSession = ptrConnect->MallocSession(true, CONN_TCP, this); - if (!hSession) { - return nullptr; - } - hSession->connectKey = connectKey; - struct sockaddr_in dest; - uv_ip4_addr(ip, port, &dest); - uv_connect_t *conn = new uv_connect_t(); - conn->data = hSession; - uv_tcp_connect(conn, (uv_tcp_t *)&hSession->hWorkTCP, (const struct sockaddr *)&dest, Connect); - return hSession; -} - -void HdcHostTCP::FindLanDaemon() -{ - uv_interface_address_t *info; - int count, i; - char ipAddr[BUF_SIZE_TINY] = ""; - if (broadcastFindWorking) { - return; - } - lstDaemonResult.clear(); - uv_interface_addresses(&info, &count); - i = count; - while (--i) { - uv_interface_address_t interface = info[i]; - if (interface.address.address4.sin_family == AF_INET6) { - continue; - } - uv_ip4_name(&interface.address.address4, ipAddr, sizeof(ipAddr)); - BroadcatFindDaemon(ipAddr); - } - uv_free_interface_addresses(info, count); -} -} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/host/host_tcp.h b/services/flashd/host/host_tcp.h deleted file mode 100755 index b5b85ab6..00000000 --- a/services/flashd/host/host_tcp.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_HOST_TCP_H -#define HDC_HOST_TCP_H -#include "host_common.h" - -namespace Hdc { -class HdcHostTCP : public HdcTCPBase { -public: - HdcHostTCP(const bool serverOrDaemonIn, void *ptrMainBase); - virtual ~HdcHostTCP(); - void FindLanDaemon(); - HSession ConnectDaemon(const string &connectKey); - void Stop(); - list lstDaemonResult; - -private: - static void BroadcastTimer(uv_idle_t *handle); - static void Connect(uv_connect_t *connection, int status); - void BroadcatFindDaemon(const char *broadcastLanIP); - void RecvUDPEntry(const sockaddr *addrSrc, uv_udp_t *handle, const uv_buf_t *rcvbuf); - - bool broadcastFindWorking; -}; -} // namespace Hdc -#endif \ No newline at end of file diff --git a/services/flashd/host/host_unity.cpp b/services/flashd/host/host_unity.cpp deleted file mode 100755 index 276682eb..00000000 --- a/services/flashd/host/host_unity.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "host_unity.h" - -namespace Hdc { -HdcHostUnity::HdcHostUnity(HTaskInfo hTaskInfo) - : HdcTaskBase(hTaskInfo) -{ - Base::ZeroStruct(opContext); - opContext.thisClass = this; -} - -HdcHostUnity::~HdcHostUnity() -{ - WRITE_LOG(LOG_DEBUG, "HdcHostUnity::~HdcHostUnity finish"); -} - -bool HdcHostUnity::ReadyForRelease() -{ - if (!HdcTaskBase::ReadyForRelease()) { - return false; - } - if (opContext.enableLog && !opContext.hasFilelogClosed) { - return false; - } - return true; -} - -void HdcHostUnity::StopTask() -{ - // Do not detect RunningProtect, force to close - if (opContext.hasFilelogClosed) { - return; - } - if (opContext.enableLog) { - ++refCount; - opContext.fsClose.data = &opContext; - uv_fs_close(loopTask, &opContext.fsClose, opContext.fileLog, OnFileClose); - } -}; - -void HdcHostUnity::OnFileClose(uv_fs_t *req) -{ - uv_fs_req_cleanup(req); - ContextUnity *context = (ContextUnity *)req->data; - HdcHostUnity *thisClass = (HdcHostUnity *)context->thisClass; - context->hasFilelogClosed = true; - --thisClass->refCount; - return; -} - -bool HdcHostUnity::InitLocalLog(const char *path) -{ - uv_fs_t reqFs; - // block open - if (uv_fs_open(nullptr, &reqFs, path, UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, nullptr) - < 0) - return false; - uv_fs_req_cleanup(&reqFs); - opContext.fileLog = reqFs.result; - return true; -} - -void HdcHostUnity::OnFileIO(uv_fs_t *req) -{ - CtxUnityIO *contextIO = (CtxUnityIO *)req->data; - ContextUnity *context = (ContextUnity *)contextIO->context; - HdcHostUnity *thisClass = (HdcHostUnity *)context->thisClass; - uint8_t *bufIO = contextIO->bufIO; - uv_fs_req_cleanup(req); - --thisClass->refCount; - while (true) { - if (req->result <= 0) { - if (req->result < 0) { - WRITE_LOG(LOG_DEBUG, "Error OnFileIO: %s", uv_strerror((int)req->result)); - } - break; - } - context->fileIOIndex += req->result; - break; - } - delete[] bufIO; - delete contextIO; // req is part of contextIO, no need to release -} - -bool HdcHostUnity::AppendLocalLog(const char *bufLog, const int sizeLog) -{ - auto buf = new uint8_t[sizeLog]; - auto contextIO = new CtxUnityIO(); - if (!buf || !contextIO) { - if (buf) { - delete[] buf; - } - if (contextIO) { - delete contextIO; - } - return false; - } - uv_fs_t *req = &contextIO->fs; - contextIO->bufIO = buf; - contextIO->context = &opContext; - req->data = contextIO; - ++refCount; - - if (memcpy_s(buf, sizeLog, bufLog, sizeLog)) { - } - uv_buf_t iov = uv_buf_init((char *)buf, sizeLog); - uv_fs_write(loopTask, req, opContext.fileLog, &iov, 1, opContext.fileBufIndex, OnFileIO); - opContext.fileBufIndex += sizeLog; - return true; -} - -bool HdcHostUnity::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) -{ - bool ret = true; - // Both are executed, do not need to detect ChildReady - switch (command) { - case CMD_UNITY_BUGREPORT_INIT: { - if (strlen((char *)payload)) { // enable local log - if (!InitLocalLog((const char *)payload)) { - LogMsg(MSG_FAIL, "Cannot set locallog"); - ret = false; - break; - }; - opContext.enableLog = true; - } - SendToAnother(CMD_UNITY_BUGREPORT_INIT, nullptr, 0); - break; - } - case CMD_UNITY_BUGREPORT_DATA: { - if (opContext.enableLog) { - AppendLocalLog((const char *)payload, payloadSize); - } else { - ServerCommand(CMD_KERNEL_ECHO_RAW, payload, payloadSize); - } - break; - } - default: - break; - } - return ret; -}; -} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/host/host_unity.h b/services/flashd/host/host_unity.h deleted file mode 100755 index e4cb08f8..00000000 --- a/services/flashd/host/host_unity.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_HOST_UNITY_H -#define HDC_HOST_UNITY_H -#include "host_common.h" - -namespace Hdc { -class HdcHostUnity : public HdcTaskBase { -public: - HdcHostUnity(HTaskInfo hTaskInfo); - virtual ~HdcHostUnity(); - bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); - void StopTask(); - bool ReadyForRelease(); - -private: - struct ContextUnity { - bool enableLog; - uv_file fileLog; - uint64_t fileIOIndex; - uint64_t fileBufIndex; - bool hasFilelogClosed; - uv_fs_t fsClose; - HdcHostUnity *thisClass; - }; - struct CtxUnityIO { - uv_fs_t fs; - uint8_t *bufIO; - ContextUnity *context; - }; - static void OnFileIO(uv_fs_t *req); - static void OnFileClose(uv_fs_t *req); - bool InitLocalLog(const char *path); - bool AppendLocalLog(const char *bufLog, const int sizeLog); - - ContextUnity opContext; -}; -} // namespace Hdc -#endif // HDC_HOST_UNITY_H \ No newline at end of file diff --git a/services/flashd/host/host_updater.cpp b/services/flashd/host/host_updater.cpp index 1092abc0..641bc1d9 100755 --- a/services/flashd/host/host_updater.cpp +++ b/services/flashd/host/host_updater.cpp @@ -16,6 +16,7 @@ #include #include "common.h" +#include "flash_define.h" #include "transfer.h" #include "serial_struct.h" @@ -164,7 +165,7 @@ bool HostUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, cons bool ret = true; switch (command) { case CMD_UPDATER_BEGIN: { - std::string s(" Processing: 0%%"); + std::string s("Processing: 0%%"); sendProgress = true; SendRawData(reinterpret_cast(s.data()), s.size()); break; @@ -211,7 +212,7 @@ void HostUpdater::ProcessProgress(uint32_t percentage) if (!sendProgress) { return; } - std::string backStr = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"; + std::string backStr = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"; std::string breakStr = "\n"; WRITE_LOG(LOG_INFO, "ProcessProgress %d", percentage); const int bufferSize = 128; @@ -222,7 +223,7 @@ void HostUpdater::ProcessProgress(uint32_t percentage) sendProgress = false; return; } - int len = sprintf_s(buffer.data(), buffer.size() - 1, "%s Processing: %3d%%", backStr.c_str(), percentage); + int len = sprintf_s(buffer.data(), buffer.size() - 1, "%sProcessing: %3d%%", backStr.c_str(), percentage); HOSTUPDATER_CHECK(len > 0, return, "Failed to format progress info "); SendRawData(reinterpret_cast(buffer.data()), len); if (percentage == PERCENT_FINISH) { @@ -312,7 +313,7 @@ bool HostUpdater::ConfirmCommand(const string &commandIn, bool &closeInput) const size_t minLen = strlen("yes"); int retryCount = 0; do { - printf(" %s ? (Yes/No) ", tip.c_str()); + printf("%s ? (Yes/No) ", tip.c_str()); fflush(stdin); std::string info = {}; size_t i = 0; @@ -347,4 +348,13 @@ bool HostUpdater::ConfirmCommand(const string &commandIn, bool &closeInput) } return true; } + +void HostUpdater::SendRawData(uint8_t *bufPtr, const int size) +{ +#ifndef UPDATER_UT + HdcSessionBase *sessionBase = (HdcSessionBase *)clsSession; + sessionBase->ServerCommand(taskInfo->sessionId, + taskInfo->channelId, CMD_KERNEL_ECHO_RAW, bufPtr, size); +#endif +} } // namespace Hdc \ No newline at end of file diff --git a/services/flashd/host/host_updater.h b/services/flashd/host/host_updater.h index 174dfd4f..f11a5d03 100755 --- a/services/flashd/host/host_updater.h +++ b/services/flashd/host/host_updater.h @@ -47,16 +47,12 @@ private: void RunQueue(CtxFile &context); std::string GetFileName(const std::string &fileName) const; void ProcessProgress(uint32_t percentage); + void SendRawData(uint8_t *bufPtr, const int size); #ifdef UPDATER_UT void LogMsg(MessageLevel level, const char *msg, ...) { return; } - void SendRawData(uint8_t *bufPtr, const int size) - { - std::string s((char *)bufPtr, size); - WRITE_LOG(LOG_DEBUG, "SendRawData %d %s", size, s.c_str()); - } bool SendToAnother(const uint16_t command, uint8_t *bufPtr, const int size) { std::string s((char *)bufPtr, size); diff --git a/services/flashd/host/host_usb.cpp b/services/flashd/host/host_usb.cpp deleted file mode 100755 index 2b9a9f6d..00000000 --- a/services/flashd/host/host_usb.cpp +++ /dev/null @@ -1,550 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "host_usb.h" -#include "server.h" - -namespace Hdc { -HdcHostUSB::HdcHostUSB(const bool serverOrDaemonIn, void *ptrMainBase, void *ctxUSBin) - : HdcUSBBase(serverOrDaemonIn, ptrMainBase) -{ - modRunning = false; - if (!ctxUSBin) { - return; - } - HdcServer *pServer = (HdcServer *)ptrMainBase; - uv_idle_init(&pServer->loopMain, &usbWork); - ctxUSB = (libusb_context *)ctxUSBin; - uv_timer_init(&pServer->loopMain, &devListWatcher); -} - -HdcHostUSB::~HdcHostUSB() -{ - if (modRunning) { - Stop(); - } - WRITE_LOG(LOG_DEBUG, "~HdcHostUSB"); -} - -void HdcHostUSB::Stop() -{ - if (!ctxUSB) { - return; - } - Base::TryCloseHandle((uv_handle_t *)&usbWork); - Base::TryCloseHandle((uv_handle_t *)&devListWatcher); - modRunning = false; -} - -int HdcHostUSB::Initial() -{ - if (!ctxUSB) { - WRITE_LOG(LOG_FATAL, "USB mod ctxUSB is nullptr, recompile please"); - return -1; - } - WRITE_LOG(LOG_DEBUG, "HdcHostUSB init"); - modRunning = true; - StartupUSBWork(); // Main thread registration, IO in sub-thread - return 0; -} - -// windows/mac's control port reset seems invalid? So we try to use soft interrupt -// if all platform 'libusb_reset_device()' work ok, commit this function and use it replace -// main thread call -void HdcHostUSB::SendUsbSoftReset(HUSB hUSB, uint32_t sessionId) -{ - struct ResetCtx { - USBHead usbPayloadHeader; - HUSB hUSB; - }; - ResetCtx *ctxReset = new ResetCtx(); - ctxReset->hUSB = hUSB; - - USBHead &usbPayloadHeader = ctxReset->usbPayloadHeader; - usbPayloadHeader.option = USB_OPTION_RESET; - usbPayloadHeader.sessionId = sessionId; - if (memcpy_s(usbPayloadHeader.flag, sizeof(usbPayloadHeader.flag), PACKET_FLAG.c_str(), - sizeof(usbPayloadHeader.flag)) - != EOK) { - delete ctxReset; - return; - } - auto resetUsbCallback = [](struct libusb_transfer *transfer) -> void LIBUSB_CALL { - ResetCtx *ctxReset = (ResetCtx *)transfer->user_data; - if (LIBUSB_TRANSFER_COMPLETED != transfer->status) { - WRITE_LOG(LOG_FATAL, "SendUSBRaw status:%d", transfer->status); - } - ctxReset->hUSB->sendIOComplete = true; - delete ctxReset; - libusb_free_transfer(transfer); - // has send soft reset, next reset daemon's send - WRITE_LOG(LOG_DEBUG, "Device reset singal send"); - }; - hUSB->lockDeviceHandle.lock(); - libusb_transfer *transferUsb = libusb_alloc_transfer(0); - libusb_fill_bulk_transfer(transferUsb, hUSB->devHandle, hUSB->epHost, (uint8_t *)&usbPayloadHeader, sizeof(USBHead), - resetUsbCallback, ctxReset, GLOBAL_TIMEOUT * TIME_BASE); - int err = libusb_submit_transfer(transferUsb); - if (err < 0) { - WRITE_LOG(LOG_FATAL, "libusb_submit_transfer failed, err:%d", err); - delete ctxReset; - } else { - hUSB->sendIOComplete = false; - } - hUSB->lockDeviceHandle.unlock(); -} - -bool HdcHostUSB::DetectMyNeed(libusb_device *device, string &sn) -{ - bool ret = false; - HUSB hUSB = new HdcUSB(); - hUSB->device = device; - // just get usb SN, close handle immediately - int childRet = OpenDeviceMyNeed(hUSB); - if (childRet < 0) { - delete hUSB; - return false; - } - libusb_release_interface(hUSB->devHandle, hUSB->interfaceNumber); - libusb_close(hUSB->devHandle); - hUSB->devHandle = nullptr; - - WRITE_LOG(LOG_INFO, "Needed device found, busid:%d devid:%d connectkey:%s", hUSB->busId, hUSB->devId, - hUSB->serialNumber.c_str()); - // USB device is automatically connected after recognition, auto connect USB - UpdateUSBDaemonInfo(hUSB, nullptr, STATUS_READY); - HdcServer *hdcServer = (HdcServer *)clsMainBase; - HSession hSession = hdcServer->MallocSession(true, CONN_USB, this); - hSession->connectKey = hUSB->serialNumber; - uv_timer_t *waitTimeDoCmd = new uv_timer_t; - uv_timer_init(&hdcServer->loopMain, waitTimeDoCmd); - waitTimeDoCmd->data = hSession; - constexpr uint16_t PRECONNECT_INTERVAL = 3000; - uv_timer_start(waitTimeDoCmd, hdcServer->UsbPreConnect, 0, PRECONNECT_INTERVAL); - mapIgnoreDevice[sn] = HOST_USB_REGISTER; - ret = true; - delete hUSB; - return ret; -} - -// sub-thread all called -void HdcHostUSB::PenddingUSBIO(uv_idle_t *handle) -{ - libusb_context *ctxUSB = (libusb_context *)handle->data; - // every plug,handle,libusb_handle_events - struct timeval zerotime; - int nComplete = 0; - zerotime.tv_sec = 0; - zerotime.tv_usec = 1; // if == 0,windows will be high CPU load - libusb_handle_events_timeout_completed(ctxUSB, &zerotime, &nComplete); -} - -void HdcHostUSB::KickoutZombie(HSession hSession) -{ - HdcServer *ptrConnect = (HdcServer *)hSession->classInstance; - HUSB hUSB = hSession->hUSB; - if (!hUSB->devHandle || hSession->isDead) { - return; - } - if (LIBUSB_ERROR_NO_DEVICE != libusb_kernel_driver_active(hUSB->devHandle, hUSB->interfaceNumber)) { - return; - } - ptrConnect->FreeSession(hSession->sessionId); -} - -void HdcHostUSB::RemoveIgnoreDevice(string &mountInfo) -{ - if (mapIgnoreDevice.count(mountInfo)) { - mapIgnoreDevice.erase(mountInfo); - } -} - -void HdcHostUSB::ReviewUsbNodeLater(string &nodeKey) -{ - HdcServer *hdcServer = (HdcServer *)clsMainBase; - // add to ignore list - mapIgnoreDevice[nodeKey] = HOST_USB_IGNORE; - int delayRemoveFromList = intervalDevCheck * MINOR_TIMEOUT; // wait little time for daemon reinit - Base::DelayDo(&hdcServer->loopMain, delayRemoveFromList, 0, nodeKey, nullptr, - [this](const uint8_t flag, string &msg, const void *) -> void { RemoveIgnoreDevice(msg); }); -} - -void HdcHostUSB::WatchDevPlugin(uv_timer_t *handle) -{ - HdcHostUSB *thisClass = (HdcHostUSB *)handle->data; - HdcServer *ptrConnect = (HdcServer *)thisClass->clsMainBase; - libusb_device **devs = nullptr; - libusb_device *dev = nullptr; - // kick zombie - ptrConnect->EnumUSBDeviceRegister(KickoutZombie); - // find new - ssize_t cnt = libusb_get_device_list(thisClass->ctxUSB, &devs); - if (cnt < 0) { - WRITE_LOG(LOG_FATAL, "Failed to get device list"); - return; - } - int i = 0; - // linux replug devid increment,windows will be not - while ((dev = devs[i++]) != nullptr) { // must postfix++ - string szTmpKey = Base::StringFormat("%d-%d", libusb_get_bus_number(dev), libusb_get_device_address(dev)); - // check is in ignore list - UsbCheckStatus statusCheck = thisClass->mapIgnoreDevice[szTmpKey]; - if (statusCheck == HOST_USB_IGNORE || statusCheck == HOST_USB_REGISTER) { - continue; - } - string sn = szTmpKey; - if (!thisClass->DetectMyNeed(dev, sn)) { - thisClass->ReviewUsbNodeLater(szTmpKey); - } - } - libusb_free_device_list(devs, 1); -} - -int HdcHostUSB::StartupUSBWork() -{ - // Because libusb(winusb backend) does not support hotplug under win32, we use list mode for all platforms - WRITE_LOG(LOG_DEBUG, "USBHost loopfind mode"); - devListWatcher.data = this; - uv_timer_start(&devListWatcher, WatchDevPlugin, 0, intervalDevCheck); - // Running pendding in independent threads does not significantly improve the efficiency - usbWork.data = ctxUSB; - uv_idle_start(&usbWork, PenddingUSBIO); - return 0; -} - -int HdcHostUSB::CheckDescriptor(HUSB hUSB) -{ - char serialNum[BUF_SIZE_MEDIUM] = ""; - int childRet = 0; - struct libusb_device_descriptor desc; - int curBus = libusb_get_bus_number(hUSB->device); - int curDev = libusb_get_device_address(hUSB->device); - hUSB->busId = curBus; - hUSB->devId = curDev; - if (libusb_get_device_descriptor(hUSB->device, &desc)) { - WRITE_LOG(LOG_DEBUG, "CheckDescriptor libusb_get_device_descriptor failed"); - return -1; - } - // Get the serial number of the device, if there is no serial number, use the ID number to replace - // If the device is not in time, occasionally can't get it, this is determined by the external factor, cannot be - // changed. LIBUSB_SUCCESS - childRet = libusb_get_string_descriptor_ascii(hUSB->devHandle, desc.iSerialNumber, (uint8_t *)serialNum, - sizeof(serialNum)); - if (childRet < 0) { - hUSB->serialNumber = Base::StringFormat("%d-%d", curBus, curDev); - } else { - hUSB->serialNumber = serialNum; - } - return 0; -} - -// hSession can be null -void HdcHostUSB::UpdateUSBDaemonInfo(HUSB hUSB, HSession hSession, uint8_t connStatus) -{ - // add to list - HdcServer *pServer = (HdcServer *)clsMainBase; - HdcDaemonInformation di; - di.connectKey = hUSB->serialNumber; - di.connType = CONN_USB; - di.connStatus = connStatus; - di.hSession = hSession; - di.usbMountPoint = ""; - di.usbMountPoint = Base::StringFormat("%d-%d", hUSB->busId, hUSB->devId); - - HDaemonInfo pDi = nullptr; - HDaemonInfo hdiNew = &di; - pServer->AdminDaemonMap(OP_QUERY, hUSB->serialNumber, pDi); - if (!pDi) { - pServer->AdminDaemonMap(OP_ADD, hUSB->serialNumber, hdiNew); - } else { - pServer->AdminDaemonMap(OP_UPDATE, hUSB->serialNumber, hdiNew); - } -} - -bool HdcHostUSB::IsDebuggableDev(const struct libusb_interface_descriptor *ifDescriptor) -{ - constexpr uint8_t harmonyEpNum = 2; - constexpr uint8_t harmonyClass = 0xff; - constexpr uint8_t harmonySubClass = 0x50; - constexpr uint8_t harmonyProtocol = 0x01; - - if (ifDescriptor->bInterfaceClass != harmonyClass || ifDescriptor->bInterfaceSubClass != harmonySubClass - || ifDescriptor->bInterfaceProtocol != harmonyProtocol) { - return false; - } - if (ifDescriptor->bNumEndpoints != harmonyEpNum) { - return false; - } - return true; -} - -int HdcHostUSB::CheckActiveConfig(libusb_device *device, HUSB hUSB) -{ - unsigned int j = 0; - int ret = -1; - struct libusb_config_descriptor *descConfig = nullptr; - if (libusb_get_active_config_descriptor(device, &descConfig)) { - return -1; - } - for (j = 0; j < descConfig->bNumInterfaces; ++j) { - const struct libusb_interface *interface = &descConfig->interface[j]; - if (interface->num_altsetting >= 1) { - const struct libusb_interface_descriptor *ifDescriptor = &interface->altsetting[0]; - if (!IsDebuggableDev(ifDescriptor)) { - continue; - } - hUSB->interfaceNumber = ifDescriptor->bInterfaceNumber; - unsigned int k = 0; - for (k = 0; k < ifDescriptor->bNumEndpoints; ++k) { - const struct libusb_endpoint_descriptor *ep_desc = &ifDescriptor->endpoint[k]; - if ((ep_desc->bmAttributes & 0x03) == LIBUSB_TRANSFER_TYPE_BULK) { - if (ep_desc->bEndpointAddress & LIBUSB_ENDPOINT_IN) { - hUSB->epDevice = ep_desc->bEndpointAddress; - } else { - hUSB->epHost = ep_desc->bEndpointAddress; - } - hUSB->wMaxPacketSize = ep_desc->wMaxPacketSize; - } - } - if (hUSB->epDevice == 0 || hUSB->epHost == 0) { - break; - } - ret = 0; - } - } - libusb_free_config_descriptor(descConfig); - return ret; -} - -void LIBUSB_CALL HdcHostUSB::ReadUSBBulkCallback(struct libusb_transfer *transfer) -{ - HSession hSession = (HSession)transfer->user_data; - HdcHostUSB *thisClass = (HdcHostUSB *)hSession->classModule; - HUSB hUSB = hSession->hUSB; - bool bOK = false; - int childRet = 0; - constexpr int infinity = 0; // ignore timeout - while (true) { - if (!thisClass->modRunning || (hSession->isDead && 0 == hSession->sendRef)) - break; - if (LIBUSB_TRANSFER_COMPLETED != transfer->status) { - WRITE_LOG(LOG_FATAL, "Host usb not LIBUSB_TRANSFER_COMPLETED, status:%d", transfer->status); - break; - } - childRet - = thisClass->SendToHdcStream(hSession, reinterpret_cast(&hSession->dataPipe[STREAM_MAIN]), - hUSB->bufDevice, transfer->actual_length); - if (childRet != RET_SUCCESS && childRet != ERR_SESSION_NOFOUND) { - break; - } - hUSB->lockDeviceHandle.lock(); - // loop self - libusb_fill_bulk_transfer(transfer, hUSB->devHandle, hUSB->epDevice, hUSB->bufDevice, hUSB->sizeEpBuf, - ReadUSBBulkCallback, hSession, infinity); - childRet = libusb_submit_transfer(transfer); - hUSB->lockDeviceHandle.unlock(); - if (childRet < 0) { - WRITE_LOG(LOG_FATAL, "libusb_submit_transfer failed, err:%d", childRet); - break; - } - bOK = true; - break; - } - if (!bOK) { - auto server = reinterpret_cast(thisClass->clsMainBase); - server->FreeSession(hSession->sessionId); - hUSB->recvIOComplete = true; - WRITE_LOG(LOG_WARN, "ReadUSBBulkCallback failed"); - } -} - -void HdcHostUSB::RegisterReadCallback(HSession hSession) -{ - HUSB hUSB = hSession->hUSB; - if (hSession->isDead || !modRunning) { - return; - } - hSession->hUSB->transferRecv->user_data = hSession; - hUSB->lockDeviceHandle.lock(); - // first bulk-read must be Okay and no timeout, otherwise failed. - libusb_fill_bulk_transfer(hSession->hUSB->transferRecv, hUSB->devHandle, hUSB->epDevice, hUSB->bufDevice, - hUSB->sizeEpBuf, ReadUSBBulkCallback, hSession, GLOBAL_TIMEOUT * TIME_BASE); - int childRet = libusb_submit_transfer(hSession->hUSB->transferRecv); - hUSB->lockDeviceHandle.unlock(); - if (childRet == 0) { - hSession->hUSB->recvIOComplete = false; - } -} - -// ==0 Represents new equipment and is what we need,<0 my need -int HdcHostUSB::OpenDeviceMyNeed(HUSB hUSB) -{ - libusb_device *device = hUSB->device; - int ret = -1; - if (LIBUSB_SUCCESS != libusb_open(device, &hUSB->devHandle)) { - return -100; - } - while (modRunning) { - libusb_device_handle *handle = hUSB->devHandle; - if (CheckDescriptor(hUSB)) { - break; - } - if (CheckActiveConfig(device, hUSB)) { - break; - } - // USB filter rules are set according to specific device - // pedding device - libusb_claim_interface(handle, hUSB->interfaceNumber); - ret = 0; - break; - } - if (ret) { - // not my need device - libusb_close(hUSB->devHandle); - hUSB->devHandle = nullptr; - } - return ret; -} - -// at main thread -void LIBUSB_CALL HdcHostUSB::WriteUSBBulkCallback(struct libusb_transfer *transfer) -{ - USBHead *usbHead = reinterpret_cast(transfer->buffer); - HSession hSession = reinterpret_cast(transfer->user_data); - HdcSessionBase *server = reinterpret_cast(hSession->classInstance); - if (usbHead->option & USB_OPTION_TAIL) { - --hSession->sendRef; - } - if (LIBUSB_TRANSFER_COMPLETED != transfer->status || (hSession->isDead && 0 == hSession->sendRef)) { - WRITE_LOG(LOG_FATAL, "SendUSBRaw status:%d", transfer->status); - if (hSession->hUSB->transferRecv != nullptr) { - libusb_cancel_transfer(hSession->hUSB->transferRecv); - } - server->FreeSession(hSession->sessionId); - } - hSession->hUSB->sendIOComplete = true; - hSession->hUSB->cvTransferSend.notify_one(); -} - -// libusb can send directly across threads?!!! -// Just call from child work thread, it will be block when overlap full -int HdcHostUSB::SendUSBRaw(HSession hSession, uint8_t *data, const int length) -{ - int ret = ERR_GENERIC; - int childRet = -1; - HUSB hUSB = hSession->hUSB; - while (true) { - if (memcpy_s(hUSB->bufHost, length, data, length) != EOK) { - ret = ERR_BUF_COPY; - break; - } - hUSB->lockDeviceHandle.lock(); - std::unique_lock lock(hUSB->lockSend); - hUSB->sendIOComplete = false; - libusb_fill_bulk_transfer(hUSB->transferSend, hUSB->devHandle, hUSB->epHost, hUSB->bufHost, length, - WriteUSBBulkCallback, hSession, GLOBAL_TIMEOUT * TIME_BASE); - childRet = libusb_submit_transfer(hUSB->transferSend); - hUSB->lockDeviceHandle.unlock(); - if (childRet < 0) { - ret = ERR_IO_FAIL; - break; - } - ret = length; - hUSB->cvTransferSend.wait(lock, [hUSB]() { return hUSB->sendIOComplete; }); - break; - } - if (ret < 0) { - --hSession->sendRef; - if (hUSB->transferRecv != nullptr) { - libusb_cancel_transfer(hUSB->transferRecv); - } - } - return ret; -} - -bool HdcHostUSB::FindDeviceByID(HUSB hUSB, const char *usbMountPoint, libusb_context *ctxUSB) -{ - libusb_device **listDevices = nullptr; - bool ret = false; - char tmpStr[BUF_SIZE_TINY] = ""; - int busNum = 0; - int devNum = 0; - int curBus = 0; - int curDev = 0; - - int device_num = libusb_get_device_list(ctxUSB, &listDevices); - if (device_num <= 0) { - libusb_free_device_list(listDevices, 1); - return false; - } - if (strchr(usbMountPoint, '-') && EOK == strcpy_s(tmpStr, sizeof(tmpStr), usbMountPoint)) { - *strchr(tmpStr, '-') = '\0'; - busNum = atoi(tmpStr); - devNum = atoi(tmpStr + strlen(tmpStr) + 1); - } else - return false; - - int i = 0; - for (i = 0; i < device_num; ++i) { - struct libusb_device_descriptor desc; - if (LIBUSB_SUCCESS != libusb_get_device_descriptor(listDevices[i], &desc)) { - break; - } - curBus = libusb_get_bus_number(listDevices[i]); - curDev = libusb_get_device_address(listDevices[i]); - if ((curBus == busNum && curDev == devNum)) { - hUSB->device = listDevices[i]; - int childRet = OpenDeviceMyNeed(hUSB); - if (!childRet) { - ret = true; - } - break; - } - } - libusb_free_device_list(listDevices, 1); - return ret; -} - -bool HdcHostUSB::ReadyForWorkThread(HSession hSession) -{ - HdcUSBBase::ReadyForWorkThread(hSession); - return true; -}; - -// Determines that daemonInfo must have the device -HSession HdcHostUSB::ConnectDetectDaemon(const HSession hSession, const HDaemonInfo pdi) -{ - HdcServer *pServer = (HdcServer *)clsMainBase; - HUSB hUSB = hSession->hUSB; - hUSB->usbMountPoint = pdi->usbMountPoint; - hUSB->ctxUSB = ctxUSB; - if (!FindDeviceByID(hUSB, hUSB->usbMountPoint.c_str(), hUSB->ctxUSB)) { - pServer->FreeSession(hSession->sessionId); - return nullptr; - } - UpdateUSBDaemonInfo(hUSB, hSession, STATUS_CONNECTED); - RegisterReadCallback(hSession); - hUSB->usbMountPoint = pdi->usbMountPoint; - WRITE_LOG(LOG_DEBUG, "HSession HdcHostUSB::ConnectDaemon"); - - Base::StartWorkThread(&pServer->loopMain, pServer->SessionWorkThread, Base::FinishWorkThread, hSession); - // wait for thread up - while (hSession->childLoop.active_handles == 0) { - uv_sleep(1); - } - auto ctrl = pServer->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0); - Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); - return hSession; -} -} // namespace Hdc diff --git a/services/flashd/host/host_usb.h b/services/flashd/host/host_usb.h deleted file mode 100755 index edafd789..00000000 --- a/services/flashd/host/host_usb.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_HOST_USB_H -#define HDC_HOST_USB_H -#include "host_common.h" - -namespace Hdc { -class HdcHostUSB : public HdcUSBBase { -public: - HdcHostUSB(const bool serverOrDaemonIn, void *ptrMainBase, void *ctxUSBin); - virtual ~HdcHostUSB(); - int Initial(); - int SendUSBRaw(HSession hSession, uint8_t *data, const int length); - HSession ConnectDetectDaemon(const HSession hSession, const HDaemonInfo pdi); - void Stop(); - void RemoveIgnoreDevice(string &mountInfo); - -private: - enum UsbCheckStatus { - HOST_USB_IGNORE = 1, - HOST_USB_READY, - HOST_USB_REGISTER, - }; - static int LIBUSB_CALL HotplugHostUSBCallback(libusb_context *ctx, libusb_device *device, - libusb_hotplug_event event, void *userData); - static void PenddingUSBIO(uv_idle_t *handle); - static void WatchDevPlugin(uv_timer_t *handle); - static void KickoutZombie(HSession hSession); - static void LIBUSB_CALL WriteUSBBulkCallback(struct libusb_transfer *transfer); - static void LIBUSB_CALL ReadUSBBulkCallback(struct libusb_transfer *transfer); - int StartupUSBWork(); - int CheckActiveConfig(libusb_device *device, HUSB hUSB); - int OpenDeviceMyNeed(HUSB hUSB); - int CheckDescriptor(HUSB hUSB); - bool IsDebuggableDev(const struct libusb_interface_descriptor *ifDescriptor); - bool ReadyForWorkThread(HSession hSession); - bool FindDeviceByID(HUSB hUSB, const char *usbMountPoint, libusb_context *ctxUSB); - bool DetectMyNeed(libusb_device *device, string &sn); - void SendUsbSoftReset(HUSB hUSB, uint32_t sessionId); - void RestoreHdcProtocol(HUSB hUsb, const uint8_t *buf, int bufSize); - void UpdateUSBDaemonInfo(HUSB hUSB, HSession hSession, uint8_t connStatus); - void RegisterReadCallback(HSession hSession); - void ReviewUsbNodeLater(string &nodeKey); - - uv_idle_t usbWork; - libusb_context *ctxUSB; - uv_timer_t devListWatcher; - map mapIgnoreDevice; - const int intervalDevCheck = 3000; - -private: -}; -} // namespace Hdc -#endif \ No newline at end of file diff --git a/services/flashd/host/main.cpp b/services/flashd/host/main.cpp index 016e3dc2..ca934bf6 100755 --- a/services/flashd/host/main.cpp +++ b/services/flashd/host/main.cpp @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "flash_define.h" #include "server.h" #include "server_for_client.h" diff --git a/services/flashd/host/server.cpp b/services/flashd/host/server.cpp index 90a4b994..6e42d875 100755 --- a/services/flashd/host/server.cpp +++ b/services/flashd/host/server.cpp @@ -14,6 +14,9 @@ */ #include "server.h" +#include "host_updater.h" +#include "flash_define.h" + namespace Hdc { HdcServer::HdcServer(bool serverOrDaemonIn) : HdcSessionBase(serverOrDaemonIn) @@ -141,7 +144,7 @@ bool HdcServer::PullupServer(const char *listenString) // close file pipe close(i); } - execl(path, "hdc", "-m", "-s", listenString, nullptr); + execl(path, "ohflash", "-m", "-s", listenString, nullptr); exit(0); return true; } diff --git a/services/flashd/host/server.h b/services/flashd/host/server.h deleted file mode 100755 index e1e66810..00000000 --- a/services/flashd/host/server.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_SERVER_H -#define HDC_SERVER_H -#include "host_common.h" - -namespace Hdc { -class HdcServer : public HdcSessionBase { -public: - HdcServer(bool serverOrDaemonIn); - virtual ~HdcServer(); - bool FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, - const int payloadSize); - string AdminDaemonMap(uint8_t opType, const string &connectKey, HDaemonInfo &hDaemonInfoInOut); - string AdminForwardMap(uint8_t opType, const string &taskString, HForwardInfo &hForwardInfoInOut); - int CreateConnect(const string &connectKey); - bool Initial(const char *listenString); - void AttachChannel(HSession hSession, const uint32_t channelId); - void DeatchChannel(HSession hSession, const uint32_t channelId); - static bool PullupServer(const char *listenString); - static void UsbPreConnect(uv_timer_t *handle); - void NotifyInstanceSessionFree(HSession hSession, bool freeOrClear); - - HdcHostTCP *clsTCPClt; - HdcHostUSB *clsUSBClt; - void *clsServerForClient; - -private: - void ClearInstanceResource(); - void BuildDaemonVisableLine(HDaemonInfo hdi, bool fullDisplay, string &out); - void BuildForwardVisableLine(bool fullOrSimble, HForwardInfo hfi, string &echo); - void ClearMapDaemonInfo(); - bool ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, uint8_t *bufPtr, - const int size); - bool RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, const uint16_t command, - uint8_t *payload, const int payloadSize); - bool RemoveInstanceTask(const uint8_t op, HTaskInfo hTask); - void BuildForwardVisableLine(HDaemonInfo hdi, char *out, int sizeOutBuf); - bool HandServerAuth(HSession hSession, SessionHandShake &handshake); - string GetDaemonMapList(uint8_t opType); - bool ServerSessionHandshake(HSession hSession, uint8_t *payload, int payloadSize); - void GetDaemonMapOnlyOne(HDaemonInfo &hDaemonInfoInOut); - void TryStopInstance(); - static bool PullupServerWin32(const char *path, const char *listenString); - - uv_rwlock_t daemonAdmin; - map mapDaemon; - uv_rwlock_t forwardAdmin; - map mapForward; -}; -} // namespace Hdc -#endif \ No newline at end of file diff --git a/services/flashd/host/server_for_client.cpp b/services/flashd/host/server_for_client.cpp index fc6feb17..f1db8215 100755 --- a/services/flashd/host/server_for_client.cpp +++ b/services/flashd/host/server_for_client.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ #include "server_for_client.h" + +#include "flash_define.h" #include "server.h" namespace Hdc { diff --git a/services/flashd/host/server_for_client.h b/services/flashd/host/server_for_client.h deleted file mode 100755 index 22ca06e2..00000000 --- a/services/flashd/host/server_for_client.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_SERVERFORCLIENT_H -#define HDC_SERVERFORCLIENT_H -#include "host_common.h" -#include "translate.h" - -namespace Hdc { -class HdcServerForClient : public HdcChannelBase { -public: - HdcServerForClient(const bool serverOrClient, const string &addrString, void *pClsServer, uv_loop_t *loopMainIn); - virtual ~HdcServerForClient(); - int Initial(); - void EchoClient(HChannel hChannel, MessageLevel level, const char *msg, ...); - void EchoClientRaw(const uint32_t channelId, uint8_t *payload, const int payloadSize); - uint16_t GetTCPListenPort(); - void Stop(); - -protected: -private: - static void AcceptClient(uv_stream_t *server, int status); - void SetTCPListen(); - int ReadChannel(HChannel hChannel, uint8_t *bufPtr, const int bytesIO); - bool DoCommand(HChannel hChannel, void *formatCommandInput); - void OrderFindTargets(HChannel hChannel); - bool NewConnectTry(void *ptrServer, HChannel hChannel, const string &connectKey); - static void OrderConnecTargetResult(uv_timer_t *req); - bool SendToDaemon(HChannel hChannel, const uint16_t commandFlag, uint8_t *bufPtr, const int bufSize); - int BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO); - bool CheckAutoFillTarget(HChannel hChannel); - bool CommandRemoveSession(HChannel hChannel, const char *connectKey); - bool CommandRemoveForward(const string &forwardKey); - bool DoCommandLocal(HChannel hChannel, void *formatCommandInput); - bool DoCommandRemote(HChannel hChannel, void *formatCommandInput); - void GetTargetList(HChannel hChannel, void *formatCommandInput); - bool GetAnyTarget(HChannel hChannel); - bool RemoveForward(HChannel hChannel, const char *parameterString); - bool TaskCommand(HChannel hChannel, void *formatCommandInput); - int ChannelHandShake(HChannel hChannel, uint8_t *bufPtr, const int bytesIO); - bool ChannelSendSessionCtrlMsg(vector &ctrlMsg, uint32_t sessionId); - HSession FindAliveSession(uint32_t sessionId); - HSession FindAliveSessionFromDaemonMap(const HChannel hChannel); - - uv_tcp_t tcpListen; - void *clsServer; -}; -} // namespace Hdc -#endif \ No newline at end of file diff --git a/services/flashd/host/translate.cpp b/services/flashd/host/translate.cpp index 350765eb..e74dbd77 100755 --- a/services/flashd/host/translate.cpp +++ b/services/flashd/host/translate.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include "translate.h" +#include "host_updater.h" namespace Hdc { namespace TranslateCommand { diff --git a/services/flashd/host/translate.h b/services/flashd/host/translate.h deleted file mode 100755 index 96128e50..00000000 --- a/services/flashd/host/translate.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HDC_TRANSLATE_H -#define HDC_TRANSLATE_H -#include "host_common.h" - -namespace Hdc { -namespace TranslateCommand { - struct FormatCommand { - uint16_t cmdFlag; - string parameters; - bool bJumpDo; - }; - - string String2FormatCommand(const char *inputRaw, int sizeInputRaw, FormatCommand *outCmd); - string Usage(); -} -} -#endif \ No newline at end of file diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 8fd94283..5ad65418 100755 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -176,6 +176,9 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/diffpatch/bzip2", "//base/update/updater/services/ui", "//base/update/updater/test/unittest", + "//developtools/hdc_standard/src/common", + "//developtools/hdc_standard/src/host", + "//developtools/hdc_standard/src/daemon", "//third_party/zlib", "//third_party/lz4/lib", "//third_party/bounds_checking_function/include", diff --git a/test/unittest/flashd_test/flash_host_unittest.cpp b/test/unittest/flashd_test/flash_host_unittest.cpp index 36561822..00c2bf3a 100755 --- a/test/unittest/flashd_test/flash_host_unittest.cpp +++ b/test/unittest/flashd_test/flash_host_unittest.cpp @@ -18,10 +18,11 @@ #include #include -#include "common/common.h" -#include "common/transfer.h" +#include "common.h" +#include "flash_define.h" #include "host_updater.h" #include "serial_struct.h" +#include "transfer.h" #include "unittest_comm.h" using namespace std; @@ -197,11 +198,6 @@ HWTEST_F(FLashHostUnitTest, TestFlashHostMatch, TestSize.Level1) EXPECT_EQ(cmdFlag, CMD_UPDATER_FORMAT); EXPECT_EQ(bJumpDo == false, 1); - ret = HostUpdater::CheckMatchUpdate("flash", stringError, cmdFlag, bJumpDo); - EXPECT_EQ(ret == true, 1); - EXPECT_EQ(cmdFlag, CMD_KERNEL_HELP); - EXPECT_EQ(bJumpDo == true, 1); - bJumpDo = false; ret = HostUpdater::CheckMatchUpdate("install aaa.hap", stringError, cmdFlag, bJumpDo); EXPECT_EQ(ret == false, 1); diff --git a/test/unittest/flashd_test/flash_service_unittest.cpp b/test/unittest/flashd_test/flash_service_unittest.cpp index 3272f947..32b63600 100755 --- a/test/unittest/flashd_test/flash_service_unittest.cpp +++ b/test/unittest/flashd_test/flash_service_unittest.cpp @@ -18,13 +18,14 @@ #include #include -#include "common/common.h" -#include "common/transfer.h" +#include "common.h" #include "daemon_updater.h" +#include "flash_define.h" #include "flash_service.h" #include "flashd/flashd.h" #include "fs_manager/mount.h" #include "serial_struct.h" +#include "transfer.h" #include "unittest_comm.h" using namespace std; -- Gitee From 1dbacfa0fb3c618e991877c434f7e60a25f7a165 Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Wed, 17 Nov 2021 11:52:13 +0800 Subject: [PATCH 14/15] updater: fix codedex Signed-off-by: xionglei6 --- services/diffpatch/diff/blocks_diff.cpp | 4 +-- services/flashd/BUILD.gn | 2 +- services/flashd/host/client.cpp | 2 +- services/flashd/host/host_updater.cpp | 12 ++------- services/flashd/host/main.cpp | 21 ++++----------- services/flashd/host/server.cpp | 4 +-- services/flashd/host/server_for_client.cpp | 19 +++++++------- services/flashd/host/translate.cpp | 26 ++++++++++--------- .../flashd_test/flash_host_unittest.cpp | 4 --- 9 files changed, 36 insertions(+), 58 deletions(-) diff --git a/services/diffpatch/diff/blocks_diff.cpp b/services/diffpatch/diff/blocks_diff.cpp index d579dbd9..2a68f28c 100644 --- a/services/diffpatch/diff/blocks_diff.cpp +++ b/services/diffpatch/diff/blocks_diff.cpp @@ -237,7 +237,7 @@ void BlocksDiff::ComputeLength(const BlockBuffer &newInfo, int64_t i = 0; int64_t s = 0; int64_t tmp = 0; - for (; ((lastScan_ + i) < currentOffset_) && ((lastPos_ + i) < static_cast(oldInfo.length)); ) { + for (; ((lastScan_ + i) < currentOffset_) && ((lastPos_ + i) < static_cast(oldInfo.length));) { if (oldInfo.buffer[lastPos_ + i] == newInfo.buffer[lastScan_ + i]) { s++; } @@ -413,7 +413,7 @@ void SuffixArray::Init(const BlockBuffer &oldInfo) DataType len = 0; for (h = 1; suffixArray_[0] != -(static_cast(oldInfo.length) + 1); h += h) { len = 0; - for (i = 0; i < (static_cast(oldInfo.length) + 1); ) { + for (i = 0; i < (static_cast(oldInfo.length) + 1);) { if (suffixArray_[i] < 0) { len -= suffixArray_[i]; i -= suffixArray_[i]; diff --git a/services/flashd/BUILD.gn b/services/flashd/BUILD.gn index 7a30a9fb..a0f49ad4 100755 --- a/services/flashd/BUILD.gn +++ b/services/flashd/BUILD.gn @@ -17,7 +17,7 @@ FLASHD_PATH = "//base/update/updater/services/flashd" HDC_PATH = "//developtools/hdc_standard/src" common_sources = [ - "${FLASHD_PATH}/common/base.cpp", + "${HDC_PATH}/common/base.cpp", "${HDC_PATH}/common/async_cmd.cpp", "${HDC_PATH}/common/auth.cpp", "${HDC_PATH}/common/channel.cpp", diff --git a/services/flashd/host/client.cpp b/services/flashd/host/client.cpp index 9dc38afe..a1b93bcd 100755 --- a/services/flashd/host/client.cpp +++ b/services/flashd/host/client.cpp @@ -373,7 +373,7 @@ int HdcClient::ReadChannel(HChannel hChannel, uint8_t *buf, const int bytesIO) #endif WRITE_LOG(LOG_DEBUG, "Client ReadChannel :%d", bytesIO); string s(reinterpret_cast(buf), bytesIO); - fprintf(stdout, "%s", s.c_str()); + (void)fprintf(stdout, "%s", s.c_str()); fflush(stdout); return 0; } diff --git a/services/flashd/host/host_updater.cpp b/services/flashd/host/host_updater.cpp index 641bc1d9..9cd19ffb 100755 --- a/services/flashd/host/host_updater.cpp +++ b/services/flashd/host/host_updater.cpp @@ -292,7 +292,6 @@ void HostUpdater::SetInput(const std::string &input) bool HostUpdater::ConfirmCommand(const string &commandIn, bool &closeInput) { std::string tip = ""; - WRITE_LOG(LOG_DEBUG, "ConfirmCommand \"%s\" \n", commandIn.c_str()); if (!strncmp(commandIn.c_str(), updateCmd.c_str(), updateCmd.size())) { closeInput = true; } else if (!strncmp(commandIn.c_str(), flashCmd.c_str(), flashCmd.size())) { @@ -303,11 +302,7 @@ bool HostUpdater::ConfirmCommand(const string &commandIn, bool &closeInput) } else if (!strncmp(commandIn.c_str(), formatCmd.c_str(), formatCmd.size())) { tip = "Confirm format partition"; } - if (tip.empty()) { - return true; - } - // check if -f - if (strstr(commandIn.c_str(), " -f") != nullptr) { + if (tip.empty() || strstr(commandIn.c_str(), " -f") != nullptr) { // check if -f return true; } const size_t minLen = strlen("yes"); @@ -343,10 +338,7 @@ bool HostUpdater::ConfirmCommand(const string &commandIn, bool &closeInput) } retryCount++; } while (retryCount < 3); // 3 retry max count - if (retryCount >= 3) { // 3 retry max count - return false; - } - return true; + return (retryCount >= 3) ? false : true; // 3 retry max count } void HostUpdater::SendRawData(uint8_t *bufPtr, const int size) diff --git a/services/flashd/host/main.cpp b/services/flashd/host/main.cpp index ca934bf6..878428c7 100755 --- a/services/flashd/host/main.cpp +++ b/services/flashd/host/main.cpp @@ -16,13 +16,6 @@ #include "server.h" #include "server_for_client.h" -#ifndef HARMONY_PROJECT -#include "../test/ut_command.h" -using namespace HdcTest; -#endif - -#include "server.h" -#include "server_for_client.h" using namespace Hdc; static bool g_isServerMode = false; @@ -60,7 +53,7 @@ int IsRegisterCommand(string &outCommand, const char *cmd, const char *cmdnext) for (string v : registerCommand) { if (doubleCommand == v) { outCommand = doubleCommand; - return 2; + return 2; // 2 error code } if (cmd == v) { outCommand = cmd; @@ -97,7 +90,7 @@ int SplitOptionAndCommand(int argc, const char **argv, string &outOption, string resultChild = IsRegisterCommand(outCommand, argv[i], (i == argc - 1) ? nullptr : argv[i + 1]); if (resultChild > 0) { foundCommand = true; - if (resultChild == 2) { + if (resultChild == 2) { // 2 error code ++i; } AppendCwdWhenTransfer(outCommand); @@ -130,9 +123,6 @@ int RunServerMode(string &serverListenString) int RunPcDebugMode(bool isPullServer, bool isTCPorUSB, int isTestMethod) { -#ifdef HARMONY_PROJECT - Base::PrintMessage("Not support command..."); -#else pthread_t pt; if (isPullServer) { pthread_create(&pt, nullptr, TestBackgroundServerForClient, nullptr); @@ -143,7 +133,6 @@ int RunPcDebugMode(bool isPullServer, bool isTCPorUSB, int isTestMethod) pthread_join(pt, nullptr); WRITE_LOG(LOG_DEBUG, "!!!!!!!!!Server finish"); } -#endif return 0; } @@ -167,7 +156,7 @@ int RunClientMode(string &commands, string &serverListenString, string &connectK && Base::ProgramMutex(SERVER_NAME.c_str(), true) == 0) { // default pullup, just default listenstr.If want to customer listen-string, please use 'hdc -m -s lanip:port' HdcServer::PullupServer(DEFAULT_SERVER_ADDR.c_str()); - uv_sleep(300); // give time to start serverForClient,at least 200ms + uv_sleep(300); // give time to start serverForClient,at least 300ms } client.Initial(connectKey); client.ExecuteCommand(commands.c_str()); @@ -176,7 +165,7 @@ int RunClientMode(string &commands, string &serverListenString, string &connectK bool ParseServerListenString(string &serverListenString, char *optarg) { - if (strlen(optarg) > 24) { + if (strlen(optarg) > 24) { // 24 min len Base::PrintMessage("Unknow content of parament '-s'"); return false; } @@ -186,7 +175,7 @@ bool ParseServerListenString(string &serverListenString, char *optarg) } char *p = strchr(buf, ':'); if (!p) { // Only port - if (strlen(buf) > 5) { + if (strlen(buf) > 5) { // port len Base::PrintMessage("The port-string's length must < 5"); return false; } diff --git a/services/flashd/host/server.cpp b/services/flashd/host/server.cpp index 6e42d875..1d8097bc 100755 --- a/services/flashd/host/server.cpp +++ b/services/flashd/host/server.cpp @@ -490,7 +490,7 @@ bool HdcServer::FetchCommand(HSession hSession, const uint32_t channelId, const pdiNew->channelId = channelId; pdiNew->sessionId = hSession->sessionId; pdiNew->forwardDirection = ((char *)payload)[0] == '1'; - pdiNew->taskString = (char *)payload + 2; + pdiNew->taskString = (char *)payload + 2; // 2 len AdminForwardMap(OP_ADD, STRING_EMPTY, pdiNew); Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP); // detch client channel break; @@ -637,7 +637,7 @@ int HdcServer::CreateConnect(const string &connectKey) uv_timer_t *waitTimeDoCmd = new uv_timer_t; uv_timer_init(&loopMain, waitTimeDoCmd); waitTimeDoCmd->data = hSession; - uv_timer_start(waitTimeDoCmd, UsbPreConnect, 10, 100); + uv_timer_start(waitTimeDoCmd, UsbPreConnect, 10, 100); // 10 100 repeat } if (!hSession) { return ERR_BUF_ALLOC; diff --git a/services/flashd/host/server_for_client.cpp b/services/flashd/host/server_for_client.cpp index f1db8215..496b0bbf 100755 --- a/services/flashd/host/server_for_client.cpp +++ b/services/flashd/host/server_for_client.cpp @@ -81,7 +81,7 @@ void HdcServerForClient::SetTCPListen() uv_tcp_init(loopMain, &tcpListen); uv_ip4_addr(channelHost.c_str(), channelPort, &addr); uv_tcp_bind(&tcpListen, (const struct sockaddr *)&addr, 0); - uv_listen((uv_stream_t *)&tcpListen, 128, (uv_connection_cb)AcceptClient); + uv_listen((uv_stream_t *)&tcpListen, 128, (uv_connection_cb)AcceptClient); // 128 client } int HdcServerForClient::Initial() @@ -92,7 +92,7 @@ int HdcServerForClient::Initial() } if (!channelHostPort.size() || !channelHost.size() || !channelPort) { WRITE_LOG(LOG_FATAL, "Listen string initial failed"); - return -2; + return -2; // 2 error code } SetTCPListen(); return 0; @@ -206,8 +206,7 @@ void HdcServerForClient::OrderConnecTargetResult(uv_timer_t *req) } else { uint16_t *bRetryCount = (uint16_t *)hChannel->bufStd; ++(*bRetryCount); - if (*bRetryCount > 500) { - // 5s + if (*bRetryCount > 500) { // 500 ms bExitRepet = true; sRet = "Connect failed"; thisClass->EchoClient(hChannel, MSG_FAIL, (char *)sRet.c_str()); @@ -228,15 +227,15 @@ bool HdcServerForClient::NewConnectTry(void *ptrServer, HChannel hChannel, const bool ret = false; if (-1 == childRet) { EchoClient(hChannel, MSG_INFO, "Target is connected, repeat operation"); - } else if (-2 == childRet) { + } else if (-2 == childRet) { // 2 error code EchoClient(hChannel, MSG_FAIL, "CreateConnect failed"); WRITE_LOG(LOG_FATAL, "CreateConnect failed"); } else { - Base::ZeroBuf(hChannel->bufStd, 2); - childRet = snprintf_s(hChannel->bufStd + 2, sizeof(hChannel->bufStd) - 2, sizeof(hChannel->bufStd) - 3, "%s", - (char *)connectKey.c_str()); + Base::ZeroBuf(hChannel->bufStd, 2); // 2 len + childRet = snprintf_s(hChannel->bufStd + 2, sizeof(hChannel->bufStd) - 2, // 2 len + sizeof(hChannel->bufStd) - 3, "%s", (char *)connectKey.c_str()); // 3 len if (childRet > 0) { - Base::TimerUvTask(loopMain, hChannel, OrderConnecTargetResult, 10); + Base::TimerUvTask(loopMain, hChannel, OrderConnecTargetResult, 10); // 10 repeat ret = true; } } @@ -639,7 +638,7 @@ int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const in } } if (formatCommand.bJumpDo) { - ret = -10; + ret = -10; // 10 error code return ret; } } else { diff --git a/services/flashd/host/translate.cpp b/services/flashd/host/translate.cpp index e74dbd77..5b274307 100755 --- a/services/flashd/host/translate.cpp +++ b/services/flashd/host/translate.cpp @@ -57,7 +57,7 @@ namespace TranslateCommand { { string stringError; if (Base::StringEndsWith(outCmd->parameters, " -remove")) { - outCmd->parameters = outCmd->parameters.substr(0, outCmd->parameters.size() - 8); + outCmd->parameters = outCmd->parameters.substr(0, outCmd->parameters.size() - 8); // 8 leng outCmd->cmdFlag = CMD_KERNEL_TARGET_DISCONNECT; } else { outCmd->cmdFlag = CMD_KERNEL_TARGET_CONNECT; @@ -92,10 +92,14 @@ namespace TranslateCommand { outCmd->parameters = input + 9; // 9 rm extra size } } else { - const char *p = input + 6; + const char *p = input + 6; // 6 length // clang-format off - if (strncmp(p, "tcp:", 4) && strncmp(p, "localabstract:", 14) && strncmp(p, "localreserved:", 14) && - strncmp(p, "localfilesystem:", 16) && strncmp(p, "dev:", 4) && strncmp(p, "jdwp:", 5)) { + if (strncmp(p, "tcp:", 4) && // 4 legnth of tcp + strncmp(p, "localabstract:", 14) && // 14 legnth of localabstract + strncmp(p, "localreserved:", 14) && // 14 legnth of localreserved + strncmp(p, "localfilesystem:", 16) && // 14 legnth of localfilesystem + strncmp(p, "dev:", 4) && // 4 legnth of dev + strncmp(p, "jdwp:", 5)) { // 14 legnth of jdwp stringError = "Incorrect forward command"; outCmd->bJumpDo = true; } @@ -111,12 +115,12 @@ namespace TranslateCommand { string stringError; outCmd->cmdFlag = CMD_UNITY_RUNMODE; outCmd->parameters = input + CMDSTR_TARGET_MODE.size() + 1; // with ' ' - if (!strncmp(outCmd->parameters.c_str(), "port", 4) + if (!strncmp(outCmd->parameters.c_str(), "port", 4) // 4 port len && !strcmp(outCmd->parameters.c_str(), CMDSTR_TMODE_USB.c_str())) { stringError = "Error tmode command"; outCmd->bJumpDo = true; - } else if (!strncmp(outCmd->parameters.c_str(), "port ", 5)) { - int port = atoi(input + 4); + } else if (!strncmp(outCmd->parameters.c_str(), "port ", 5)) { // 5 port len + int port = atoi(input + 4); // 4 port len if (port > MAX_IP_PORT || port <= 0) { stringError = "Incorrect port range"; outCmd->bJumpDo = true; @@ -130,7 +134,7 @@ namespace TranslateCommand { string stringError; outCmd->cmdFlag = CMD_UNITY_REBOOT; if (strcmp(input, CMDSTR_TARGET_REBOOT.c_str())) { - outCmd->parameters = input + 12; + outCmd->parameters = input + 12; // 12 length of target boot if (outCmd->parameters != "-bootloader" && outCmd->parameters != "-recovery" && outCmd->parameters != "-flashd") { stringError = "Error reboot paramenter"; @@ -192,7 +196,7 @@ namespace TranslateCommand { } else if (!strncmp(input.c_str(), CMDSTR_APP_UNINSTALL.c_str(), CMDSTR_APP_UNINSTALL.size())) { outCmd->cmdFlag = CMD_APP_UNINSTALL; outCmd->parameters = input; - if (outCmd->parameters.size() > 512 || outCmd->parameters.size() < 4) { + if (outCmd->parameters.size() > 512 || outCmd->parameters.size() < 4) { // 512 4 max and min name length stringError = "Package's path incorrect"; outCmd->bJumpDo = true; } @@ -229,9 +233,7 @@ namespace TranslateCommand { if (outCmd->parameters.size() == CMDSTR_BUGREPORT.size()) { outCmd->parameters += " "; } - } - // Inner command, protocol uses only - else if (input == CMDSTR_INNER_ENABLE_KEEPALIVE) { + } else if (input == CMDSTR_INNER_ENABLE_KEEPALIVE) { // Inner command, protocol uses only outCmd->cmdFlag = CMD_KERNEL_ENABLE_KEEPALIVE; } else if (HostUpdater::CheckMatchUpdate(input, stringError, outCmd->cmdFlag, outCmd->bJumpDo)) { outCmd->parameters = input; diff --git a/test/unittest/flashd_test/flash_host_unittest.cpp b/test/unittest/flashd_test/flash_host_unittest.cpp index 00c2bf3a..d7c4e068 100755 --- a/test/unittest/flashd_test/flash_host_unittest.cpp +++ b/test/unittest/flashd_test/flash_host_unittest.cpp @@ -64,13 +64,11 @@ public: } flashHost->CommandDispatch(command, const_cast(reinterpret_cast(cmd.data())), cmd.size()); - return 0; } int TestFlashProgress(uint16_t command, const std::string &cmd, uint32_t progress) { - HTaskInfo hTaskInfo = nullptr; std::shared_ptr task = std::make_shared(); if (task == nullptr) { @@ -114,7 +112,6 @@ public: (void)memcpy_s(cmdInfo.data(), cmdInfo.size(), &percentage, sizeof(percentage)); flashHost->CommandDispatch(CMD_UPDATER_PROGRESS, const_cast(reinterpret_cast(cmdInfo.data())), cmdInfo.size()); - return 0; } }; @@ -139,7 +136,6 @@ HWTEST_F(FLashHostUnitTest, TestFlashHostFormat, TestSize.Level1) cmdParam += " -t ext4"; EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FORMAT, cmdParam)); - cmdParam = "format "; cmdParam += TEST_PARTITION_NAME; cmdParam += " -t ext4"; -- Gitee From cbb191f11102dc77716c47a74d05a86c6813e03a Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Wed, 17 Nov 2021 14:13:49 +0800 Subject: [PATCH 15/15] updater: fix bugs Signed-off-by: xionglei6 --- services/flashd/BUILD.gn | 2 +- services/flashd/common/base.cpp | 1249 ----------------------- services/flashd/daemon/daemon_unity.cpp | 2 - services/flashd/host/client.cpp | 2 +- services/flashd/host/main.cpp | 2 +- 5 files changed, 3 insertions(+), 1254 deletions(-) delete mode 100755 services/flashd/common/base.cpp diff --git a/services/flashd/BUILD.gn b/services/flashd/BUILD.gn index a0f49ad4..ab998573 100755 --- a/services/flashd/BUILD.gn +++ b/services/flashd/BUILD.gn @@ -17,9 +17,9 @@ FLASHD_PATH = "//base/update/updater/services/flashd" HDC_PATH = "//developtools/hdc_standard/src" common_sources = [ - "${HDC_PATH}/common/base.cpp", "${HDC_PATH}/common/async_cmd.cpp", "${HDC_PATH}/common/auth.cpp", + "${HDC_PATH}/common/base.cpp", "${HDC_PATH}/common/channel.cpp", "${HDC_PATH}/common/debug.cpp", "${HDC_PATH}/common/file.cpp", diff --git a/services/flashd/common/base.cpp b/services/flashd/common/base.cpp deleted file mode 100755 index b0e7f153..00000000 --- a/services/flashd/common/base.cpp +++ /dev/null @@ -1,1249 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "base.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __MUSL__ -extern "C" { -#include "parameter.h" -} -#endif -using namespace std::chrono; - -namespace Hdc { -namespace Base { - uint8_t g_logLevel = 0; - void SetLogLevel(const uint8_t logLevel) - { - g_logLevel = logLevel; - } - -// Commenting the code will optimize and tune all log codes, and the compilation volume will be greatly reduced -#define ENABLE_DEBUGLOG -#ifdef ENABLE_DEBUGLOG - void GetLogDebugFunctioname(string &debugInfo, int line, string &threadIdString) - { - string tmpString = GetFileNameAny(debugInfo); - debugInfo = StringFormat("%s:%d", tmpString.c_str(), line); - if (g_logLevel < LOG_FULL) { - debugInfo = ""; - threadIdString = ""; - } else { - debugInfo = "[" + debugInfo + "]"; - threadIdString = StringFormat("[%x]", std::hash {}(std::this_thread::get_id())); - } - } - - bool IsWindowsSupportAnsiColor() - { -#ifdef _WIN32 - // Set output mode to handle virtual terminal sequences - HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); - if (hOut == INVALID_HANDLE_VALUE) { - return false; - } - DWORD dwMode = 0; - if (!GetConsoleMode(hOut, &dwMode)) { - return false; - } - dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; - if (!SetConsoleMode(hOut, dwMode)) { - return false; - } -#endif - return true; - } - - void GetLogLevelAndTime(uint8_t logLevel, string &logLevelString, string &timeString) - { - system_clock::time_point timeNow = system_clock::now(); // now time - system_clock::duration sinceUnix0 = timeNow.time_since_epoch(); // since 1970 - time_t sSinceUnix0 = duration_cast(sinceUnix0).count(); - std::tm tim = *std::localtime(&sSinceUnix0); - bool enableAnsiColor = false; -#ifdef _WIN32 - enableAnsiColor = IsWindowsSupportAnsiColor(); -#else - enableAnsiColor = true; -#endif - if (enableAnsiColor) { - switch (logLevel) { - case LOG_FATAL: - logLevelString = "\033[1;31mF\033[0m"; - break; - case LOG_INFO: - logLevelString = "\033[1;32mI\033[0m"; - break; - case LOG_WARN: - logLevelString = "\033[1;33mW\033[0m"; - break; - case LOG_DEBUG: - logLevelString = "\033[1;36mD\033[0m"; - break; - default: - logLevelString = "\033[1;36mD\033[0m"; - break; - } - } else { - logLevelString = std::to_string(logLevel); - } - string msTimeSurplus; - if (g_logLevel > LOG_DEBUG) { - const auto sSinceUnix0Rest = duration_cast(sinceUnix0).count() % (TIME_BASE * TIME_BASE); - msTimeSurplus = StringFormat(".%06llu", sSinceUnix0Rest); - } - timeString = StringFormat("%d:%d:%d%s", tim.tm_hour, tim.tm_min, tim.tm_sec, msTimeSurplus.c_str()); - } - - void PrintLogEx(const char *functionName, int line, uint8_t logLevel, const char *msg, ...) - { - if (logLevel > g_logLevel) { - return; - } - string debugInfo; - string logBuf; - string logLevelString; - string threadIdString; - string sep = "\n"; - string timeString; - - va_list vaArgs; - va_start(vaArgs, msg); - string logDetail = Base::StringFormat(msg, vaArgs); - va_end(vaArgs); - if (logDetail.back() == '\n') { - sep = "\r\n"; - } - debugInfo = functionName; - GetLogDebugFunctioname(debugInfo, line, threadIdString); - GetLogLevelAndTime(logLevel, logLevelString, timeString); - logBuf = StringFormat("[%s][%s]%s%s %s%s", logLevelString.c_str(), timeString.c_str(), threadIdString.c_str(), - debugInfo.c_str(), logDetail.c_str(), sep.c_str()); - - printf("%s", logBuf.c_str()); - fflush(stdout); - // logfile, not thread-safe -#ifdef HDC_SUPPORT_FLASHD - FILE *fp = fopen("/tmp/flashd_hdc.log", "a"); -#else - string path = GetTmpDir() + LOG_FILE_NAME; - FILE *fp = fopen(path.c_str(), "a"); -#endif - if (fp == nullptr) { - return; - } - if (fprintf(fp, "%s", logBuf.c_str()) > 0 && fflush(fp)) { - // make ci happy - } - fclose(fp); - return; - } -#else // else ENABLE_DEBUGLOG.If disabled, the entire output code will be optimized by the compiler - void PrintLogEx(uint8_t logLevel, char *msg, ...) - { - } -#endif // ENABLE_DEBUGLOG - - void PrintMessage(const char *fmt, ...) - { - va_list ap; - va_start(ap, fmt); - if (vfprintf(stdout, fmt, ap) > 0) { - fprintf(stdout, "\n"); - } - va_end(ap); - } - - // if can linkwith -lstdc++fs, use std::filesystem::path(path).filename(); - string GetFileNameAny(string &path) - { - string tmpString = path; - size_t tmpNum = tmpString.rfind('/'); - if (tmpNum == std::string::npos) { - tmpNum = tmpString.rfind('\\'); - if (tmpNum == std::string::npos) { - return tmpString; - } - } - tmpString = tmpString.substr(tmpNum + 1, tmpString.size() - tmpNum); - return tmpString; - } - - int GetMaxBufSize() - { - return MAX_SIZE_IOBUF; - } - - void SetTcpOptions(uv_tcp_t *tcpHandle) - { - constexpr int maxBufFactor = 10; - if (!tcpHandle) { - WRITE_LOG(LOG_WARN, "SetTcpOptions nullptr Ptr"); - return; - } - uv_tcp_keepalive(tcpHandle, 1, GLOBAL_TIMEOUT); - // if MAX_SIZE_IOBUF==5k,bufMaxSize at least 40k. It must be set to io 8 times is more appropriate, - // otherwise asynchronous IO is too fast, a lot of IO is wasted on IOloop, transmission speed will decrease - int bufMaxSize = GetMaxBufSize() * maxBufFactor; - uv_recv_buffer_size((uv_handle_t *)tcpHandle, &bufMaxSize); - uv_send_buffer_size((uv_handle_t *)tcpHandle, &bufMaxSize); - } - - void ReallocBuf(uint8_t **origBuf, int *nOrigSize, const int indexUsedBuf, int sizeWanted) - { - sizeWanted = GetMaxBufSize(); - int remainLen = *nOrigSize - indexUsedBuf; - // init:0, left less than expected - if (!*nOrigSize || (remainLen < sizeWanted && (*nOrigSize + sizeWanted < sizeWanted * 2))) { - // Memory allocation size is slightly larger than the maximum - int nNewLen = *nOrigSize + sizeWanted + EXTRA_ALLOC_SIZE; - uint8_t *bufPtrOrig = *origBuf; - *origBuf = new uint8_t[nNewLen](); - if (!*origBuf) { - *origBuf = bufPtrOrig; - } else { - *nOrigSize = nNewLen; - if (bufPtrOrig) { - if (memcpy_s(*origBuf, nNewLen, bufPtrOrig, *nOrigSize)) { - WRITE_LOG(LOG_FATAL, "ReallocBuf failed"); - } - delete[] bufPtrOrig; - } - } - uint8_t *buf = static_cast(*origBuf + indexUsedBuf); - Base::ZeroBuf(buf, nNewLen - indexUsedBuf); - } - } - - // As an uv_alloc_cb it must keep the same as prototype - void AllocBufferCallback(uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf) - { - const int size = GetMaxBufSize(); - buf->base = (char *)new uint8_t[size](); - if (buf->base) { - buf->len = size - 1; - } - } - - // As an uv_write_cb it must keep the same as prototype - void SendCallback(uv_write_t *req, int status) - { - delete[]((uint8_t *)req->data); - delete req; - } - - // xxx must keep sync with uv_loop_close/uv_walk etc. - bool TryCloseLoop(uv_loop_t *ptrLoop, const char *callerName) - { - // UV_RUN_DEFAULT: Runs the event loop until the reference count drops to zero. Always returns zero. - // UV_RUN_ONCE: Poll for new events once. Note that this function blocks if there are no pending events. - // Returns zero when done (no active handles or requests left), or non-zero if more events are - // expected meaning you should run the event loop again sometime in the future). - // UV_RUN_NOWAIT: Poll for new events once but don't block if there are no pending events. - uint8_t closeRetry = 0; - bool ret = false; - constexpr int maxRetry = 3; - for (closeRetry = 0; closeRetry < maxRetry; ++closeRetry) { - if (uv_loop_close(ptrLoop) == UV_EBUSY) { - if (closeRetry > 2) { // 2 try count - WRITE_LOG(LOG_WARN, "%s close busy,try:%d", callerName, closeRetry); - } - - if (ptrLoop->active_handles >= 2) { - WRITE_LOG(LOG_DEBUG, "TryCloseLoop issue"); - } - auto clearLoopTask = [](uv_handle_t *handle, void *arg) -> void { TryCloseHandle(handle); }; - uv_walk(ptrLoop, clearLoopTask, nullptr); - // If all processing ends, Then return0,this call will block - if (!ptrLoop->active_handles) { - ret = true; - break; - } - if (!uv_run(ptrLoop, UV_RUN_ONCE)) { - ret = true; - break; - } - } else { - ret = true; - break; - } - } - return ret; - } - - // Some handles may not be initialized or activated yet or have been closed, skip the closing process - void TryCloseHandle(const uv_handle_t *handle) - { - TryCloseHandle(handle, nullptr); - } - - void TryCloseHandle(const uv_handle_t *handle, uv_close_cb closeCallBack) - { - TryCloseHandle(handle, false, closeCallBack); - } - - void TryCloseHandle(const uv_handle_t *handle, bool alwaysCallback, uv_close_cb closeCallBack) - { - bool hasCallClose = false; - if (handle->loop && !uv_is_closing(handle)) { - uv_close((uv_handle_t *)handle, closeCallBack); - hasCallClose = true; - } - if (!hasCallClose && alwaysCallback) { - closeCallBack((uv_handle_t *)handle); - } - } - - int SendToStream(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen) - { - if (bufLen > static_cast(HDC_BUF_MAX_BYTES)) { - return ERR_BUF_ALLOC; - } - uint8_t *pDynBuf = new uint8_t[bufLen]; - if (!pDynBuf) { - return ERR_BUF_ALLOC; - } - if (memcpy_s(pDynBuf, bufLen, buf, bufLen)) { - delete[] pDynBuf; - return ERR_BUF_COPY; - } - return SendToStreamEx(handleStream, pDynBuf, bufLen, nullptr, (void *)SendCallback, (void *)pDynBuf); - } - - // handleSend is used for pipe thread sending, set nullptr for tcp, and dynamically allocated by malloc when buf - // is required - int SendToStreamEx(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen, uv_stream_t *handleSend, - const void *finishCallback, const void *pWriteReqData) - { - int ret = -1; - uv_write_t *reqWrite = new uv_write_t(); - if (!reqWrite) { - return 0; - } - uv_buf_t bfr; - while (true) { - reqWrite->data = (void *)pWriteReqData; - bfr.base = (char *)buf; - bfr.len = bufLen; - if (!uv_is_writable(handleStream)) { - delete reqWrite; - break; - } - // handleSend must be a TCP socket or pipe, which is a server or a connection (listening or - // connected state). Bound sockets or pipes will be assumed to be servers. - if (handleSend) { - uv_write2(reqWrite, handleStream, &bfr, 1, handleSend, (uv_write_cb)finishCallback); - } else { - uv_write(reqWrite, handleStream, &bfr, 1, (uv_write_cb)finishCallback); - } - ret = bufLen; - break; - } - return ret; - } - - uint64_t GetRuntimeMSec() - { - struct timespec times = { 0, 0 }; - long time; - clock_gettime(CLOCK_MONOTONIC, ×); - time = times.tv_sec * TIME_BASE + times.tv_nsec / (TIME_BASE * TIME_BASE); - return time; - } - - uint64_t GetRandom(const uint64_t min, const uint64_t max) - { -#ifdef HARMONY_PROJECT - uint64_t ret; - uv_random(nullptr, nullptr, &ret, sizeof(ret), 0, nullptr); -#else - uint64_t ret; - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution dis(min, max); - ret = dis(gen); -#endif - return ret; - } - - string GetRandomString(const uint16_t expectedLen) - { - srand(static_cast(GetRandom())); - string ret = string(expectedLen, '0'); - std::stringstream val; - for (auto i = 0; i < expectedLen; ++i) { - val << std::hex << (rand() % BUF_SIZE_MICRO); - } - ret = val.str(); - return ret; - } - - int GetRandomNum(const int min, const int max) - { - return static_cast(GetRandom(min, max)); - } - - int ConnectKey2IPPort(const char *connectKey, char *outIP, uint16_t *outPort) - { - char bufString[BUF_SIZE_TINY] = ""; - if (memcpy_s(bufString, sizeof(bufString), connectKey, sizeof(bufString))) { - return ERR_BUF_COPY; - } - char *p = strchr(bufString, ':'); - if (!p) { - return ERR_PARM_FORMAT; - } - *p = '\0'; - if (!strlen(bufString) || strlen(bufString) > 16) { - return ERR_PARM_SIZE; - } - uint16_t wPort = static_cast(atoi(p + 1)); - if (EOK != strcpy_s(outIP, BUF_SIZE_TINY, bufString)) { - return ERR_BUF_COPY; - } - *outPort = wPort; - return RET_SUCCESS; - } - - // After creating the session worker thread, execute it on the main thread - void FinishWorkThread(uv_work_t *req, int status) - { - // This is operated in the main thread - delete req; - } - - // at the finsh of pFuncAfterThread must free uv_work_t* - // clang-format off - int StartWorkThread(uv_loop_t *loop, uv_work_cb pFuncWorkThread, - uv_after_work_cb pFuncAfterThread, void *pThreadData) - { - uv_work_t *workThread = new uv_work_t(); - if (!workThread) { - return -1; - } - workThread->data = pThreadData; - uv_queue_work(loop, workThread, pFuncWorkThread, pFuncAfterThread); - return 0; - } - // clang-format on - - char **SplitCommandToArgs(const char *cmdStringLine, int *slotIndex) - { - constexpr int extraBufSize = 2; - char **argv; - char *temp = nullptr; - int argc = 0; - char a = 0; - size_t i = 0; - size_t j = 0; - size_t len = 0; - bool isQuoted = false; - bool isText = false; - bool isSpace = false; - - len = strlen(cmdStringLine); - if (len < 1) { - return nullptr; - } - i = ((len + extraBufSize) / extraBufSize) * sizeof(void *) + sizeof(void *); - argv = reinterpret_cast(new char[i + (len + extraBufSize) * sizeof(char)]); - temp = reinterpret_cast((reinterpret_cast(argv)) + i); - argc = 0; - argv[argc] = temp; - isQuoted = false; - isText = false; - isSpace = true; - i = 0; - j = 0; - - while ((a = cmdStringLine[i]) != 0) { - if (isQuoted) { - if (a == '\"') { - isQuoted = false; - } else { - temp[j] = a; - ++j; - } - } else { - switch (a) { - case '\"': - isQuoted = true; - isText = true; - if (isSpace) { - argv[argc] = temp + j; - ++argc; - } - isSpace = false; - break; - case ' ': - case '\t': - case '\n': - case '\r': - if (isText) { - temp[j] = '\0'; - ++j; - } - isText = false; - isSpace = true; - break; - default: - isText = true; - if (isSpace) { - argv[argc] = temp + j; - ++argc; - } - temp[j] = a; - ++j; - isSpace = false; - break; - } - } - ++i; - } - temp[j] = '\0'; - argv[argc] = nullptr; - - (*slotIndex) = argc; - return argv; - } - - bool RunPipeComand(const char *cmdString, char *outBuf, uint16_t sizeOutBuf, bool ignoreTailLf) - { - FILE *pipeHandle = popen(cmdString, "r"); - if (pipeHandle == nullptr) { - return false; - } - int bytesRead = 0; - int bytesOnce = 0; - while (!feof(pipeHandle)) { - bytesOnce = fread(outBuf, 1, sizeOutBuf - bytesRead, pipeHandle); - if (bytesOnce <= 0) { - break; - } - bytesRead += bytesOnce; - } - if (bytesRead && ignoreTailLf) { - if (outBuf[bytesRead - 1] == '\n') { - outBuf[bytesRead - 1] = '\0'; - } - } - pclose(pipeHandle); - return bytesRead; - } - - bool SetHdcProperty(const char *key, const char *value) - { -#ifndef __MUSL__ -#ifdef HDC_PCDEBUG - WRITE_LOG(LOG_DEBUG, "Setproperty, key:%s value:%s", key, value); -#else - string sKey = key; - string sValue = value; - string sBuf = "setprop " + sKey + " " + value; - system(sBuf.c_str()); -#endif -#else - SetParameter(key, value); -#endif - return true; - } - - bool GetHdcProperty(const char *key, char *value, uint16_t sizeOutBuf) - { -#ifndef __MUSL__ -#ifdef HDC_PCDEBUG - WRITE_LOG(LOG_DEBUG, "Getproperty, key:%s value:%s", key, value); -#else - string sKey = key; - string sBuf = "getprop " + sKey; - RunPipeComand(sBuf.c_str(), value, sizeOutBuf, true); -#endif -#else - string sKey = key; - string sBuf = "param get " + sKey; - RunPipeComand(sBuf.c_str(), value, sizeOutBuf, true); -#endif - value[sizeOutBuf - 1] = '\0'; - return true; - } - - // bufLen == 0: alloc buffer in heap, need free it later - // >0: read max nBuffLen bytes to *buff - // ret value: <0 or bytes read - int ReadBinFile(const char *pathName, void **buf, const int bufLen) - { - uint8_t *pDst = nullptr; - int byteIO = 0; - struct stat statbuf; - int ret = stat(pathName, &statbuf); - if (ret < 0) { - return -1; - } - int nFileSize = statbuf.st_size; - int readMax = 0; - uint8_t dynamicBuf = 0; - ret = -3; - if (bufLen == 0) { - dynamicBuf = 1; - pDst = new uint8_t[nFileSize + 1](); // tail \0 - if (!pDst) { - return -1; - } - readMax = nFileSize; - } else { - if (nFileSize > bufLen) { - return -2; - } - readMax = nFileSize; - pDst = reinterpret_cast(buf); // The first address of the static array is the array address - } - - string srcPath(pathName); - string resolvedPath = CanonicalizeSpecPath(srcPath); - FILE *fp = fopen(resolvedPath.c_str(), "r"); - if (fp == nullptr) { - goto ReadFileFromPath_Finish; - } - byteIO = fread(pDst, 1, readMax, fp); - fclose(fp); - if (byteIO != readMax) { - goto ReadFileFromPath_Finish; - } - ret = 0; - ReadFileFromPath_Finish: - if (ret) { - if (dynamicBuf) { - delete[] pDst; - } - } else { - if (dynamicBuf) { - *buf = pDst; - } - ret = byteIO; - } - return ret; - } - - int WriteBinFile(const char *pathName, const uint8_t *buf, const int bufLen, bool newFile) - { - string mode; - string resolvedPath; - string srcPath(pathName); - if (newFile) { - mode = "wb+"; - // no std::fs supoort, else std::filesystem::canonical,-lstdc++fs - if (srcPath.find("..") != string::npos) { - return ERR_FILE_PATH_CHECK; - } - resolvedPath = srcPath.c_str(); - } else { - mode = "a+"; - resolvedPath = CanonicalizeSpecPath(srcPath); - } - FILE *fp = fopen(resolvedPath.c_str(), mode.c_str()); - if (fp == nullptr) { - WRITE_LOG(LOG_DEBUG, "Write to %s failed!", pathName); - return ERR_FILE_OPEN; - } - int bytesDone = fwrite(buf, 1, bufLen, fp); - fflush(fp); - fclose(fp); - if (bytesDone != bufLen) { - return ERR_BUF_SIZE; - } - return RET_SUCCESS; - } - - void CloseIdleCallback(uv_handle_t *handle) - { - delete (uv_idle_t *)handle; - }; - - void CloseTimerCallback(uv_handle_t *handle) - { - delete (uv_timer_t *)handle; - }; - - // return value: <0 error; 0 can start new server instance; >0 server already exists - int ProgramMutex(const char *procname, bool checkOrNew) - { - char bufPath[BUF_SIZE_DEFAULT] = ""; - char buf[BUF_SIZE_DEFAULT] = ""; - char pidBuf[BUF_SIZE_TINY] = ""; - size_t size = sizeof(buf); - if (uv_os_tmpdir(buf, &size) < 0) { - WRITE_LOG(LOG_FATAL, "Tmppath failed"); - return ERR_API_FAIL; - } - if (snprintf_s(bufPath, sizeof(bufPath), sizeof(bufPath) - 1, "%s%c.%s.pid", buf, Base::GetPathSep(), procname) - < 0) { - return ERR_BUF_OVERFLOW; - } - int pid = static_cast(getpid()); - if (snprintf_s(pidBuf, sizeof(pidBuf), sizeof(pidBuf) - 1, "%d", pid) < 0) { - return ERR_BUF_OVERFLOW; - } - // no need to CanonicalizeSpecPath, else not work - umask(0); - int fd = open(bufPath, O_RDWR | O_CREAT, 0666); // 0666:permission - if (fd < 0) { - WRITE_LOG(LOG_FATAL, "Open mutex file \"%s\" failed!!!Errno:%d\n", buf, errno); - return ERR_FILE_OPEN; - } -#ifdef _WIN32 - if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "Global\\%s", procname) < 0) { - return ERR_BUF_OVERFLOW; - } - HANDLE hMutex = CreateMutex(nullptr, FALSE, buf); - DWORD dwError = GetLastError(); - if (ERROR_ALREADY_EXISTS == dwError || ERROR_ACCESS_DENIED == dwError) { - WRITE_LOG(LOG_DEBUG, "File \"%s\" locked. proc already exit!!!\n", procname); - return 1; - } - if (checkOrNew) { - CloseHandle(hMutex); - } -#else - struct flock fl; - fl.l_type = F_WRLCK; - fl.l_start = 0; - fl.l_whence = SEEK_SET; - fl.l_len = 0; - int retChild = fcntl(fd, F_SETLK, &fl); - if (-1 == retChild) { - WRITE_LOG(LOG_DEBUG, "File \"%s\" locked. proc already exit!!!\n", bufPath); - close(fd); - return 1; - } -#endif - ftruncate(fd, 0); - write(fd, pidBuf, strlen(pidBuf) + 1); - WRITE_LOG(LOG_DEBUG, "Write mutext to %s, pid:%s", bufPath, pidBuf); - if (checkOrNew) { - // close it for check only - close(fd); - } - // Do not close the file descriptor, the process will be mutext effect under no-Win32 OS - return RET_SUCCESS; - } - - void SplitString(const string &origString, const string &seq, vector &resultStrings) - { - string::size_type p1 = 0; - string::size_type p2 = origString.find(seq); - - while (p2 != string::npos) { - if (p2 == p1) { - ++p1; - p2 = origString.find(seq, p1); - continue; - } - resultStrings.push_back(origString.substr(p1, p2 - p1)); - p1 = p2 + seq.size(); - p2 = origString.find(seq, p1); - } - - if (p1 != origString.size()) { - resultStrings.push_back(origString.substr(p1)); - } - } - - string GetShellPath() - { - struct stat filecheck; - string shellPath = "/bin/sh"; - if (stat(shellPath.c_str(), &filecheck) < 0) { - shellPath = "/system/bin/sh"; - if (stat(shellPath.c_str(), &filecheck) < 0) { - shellPath = "sh"; - } - } - return shellPath; - } - - // Not supported on some platforms, Can only be achieved manually - uint64_t HostToNet(uint64_t val) - { - if (htonl(1) == 1) - return val; - return (((uint64_t)htonl(val)) << 32) + htonl(val >> 32); - } - - uint64_t NetToHost(uint64_t val) - { - if (htonl(1) == 1) - return val; - return (((uint64_t)ntohl(val)) << 32) + ntohl(val >> 32); - } - - char GetPathSep() - { -#ifdef _WIN32 - const char sep = '\\'; -#else - const char sep = '/'; -#endif - return sep; - } - - string GetFullFilePath(const string &s) - { // cannot use s.rfind(std::filesystem::path::preferred_separator - size_t i = s.rfind(GetPathSep(), s.length()); - if (i != string::npos) { - return (s.substr(i + 1, s.length() - i)); - } - return s; - } - - int CreateSocketPair(int *fds) - { -#ifndef _WIN32 -#ifdef HOST_MAC - int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); - if (ret == 0) { - for (auto i = 0; i < 2; ++i) { - if (fcntl(fds[i], F_SETFD, FD_CLOEXEC) == -1) { - close(fds[0]); - close(fds[1]); - WRITE_LOG(LOG_WARN, "fcntl failed to set FD_CLOEXEC: %s", strerror(errno)); - return -1; - } - } - } - return ret; -#else - return socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds); -#endif -#else - struct sockaddr_in addr; - socklen_t addrlen = sizeof(addr); - int reuse = 1; - if (fds == 0) { - return -1; - } - int listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (listener == -1) { - return -2; - } - Base::ZeroStruct(addr); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = 0; - fds[0] = fds[1] = (int)-1; - do { - if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, (socklen_t)sizeof(reuse))) { - break; - } - if (::bind(listener, (struct sockaddr *)&addr, sizeof(addr))) { - break; - } - if (getsockname(listener, (struct sockaddr *)&addr, &addrlen)) { - break; - } - if (listen(listener, 1)) { - break; - } - fds[0] = socket(AF_INET, SOCK_STREAM, 0); - if (fds[0] == -1) { - break; - } - if (connect(fds[0], (struct sockaddr *)&addr, sizeof(addr)) == -1) { - break; - } - fds[1] = accept(listener, nullptr, nullptr); - if (fds[1] == -1) { - break; - } - closesocket(listener); - return 0; - } while (0); - - closesocket(listener); - closesocket(fds[0]); - closesocket(fds[1]); - return -1; -#endif - } - - void CloseSocketPair(const int *fds) - { -#ifndef _WIN32 - close(fds[0]); - close(fds[1]); -#else - closesocket(fds[0]); - closesocket(fds[1]); -#endif - } - - int StringEndsWith(string s, string sub) - { - return s.rfind(sub) == (s.length() - sub.length()) ? 1 : 0; - } - - // Both absolute and relative paths support - bool CheckDirectoryOrPath(const char *localPath, bool pathOrDir, bool readWrite) - { - if (pathOrDir) { // filepath - uv_fs_t req; - int r = uv_fs_lstat(nullptr, &req, localPath, nullptr); - uv_fs_req_cleanup(&req); - if (r == 0 && req.statbuf.st_mode & S_IFREG) { // is file - uv_fs_access(nullptr, &req, localPath, readWrite ? R_OK : W_OK, nullptr); - uv_fs_req_cleanup(&req); - if (req.result == 0) - return true; - } - } else { // dir - } - return false; - } - - // Using openssl encryption and decryption method, high efficiency; when encrypting more than 64 bytes, - // the carriage return will not be added, and the tail padding 00 is removed when decrypting - // The return value is the length of the string after Base64 - int Base64EncodeBuf(const uint8_t *input, const int length, uint8_t *bufOut) - { - return EVP_EncodeBlock(bufOut, input, length); - } - - vector Base64Encode(const uint8_t *input, const int length) - { - vector retVec; - uint8_t *pBuf = nullptr; - while (true) { - if (static_cast(length) > HDC_BUF_MAX_BYTES) { - break; - } - int base64Size = length * 1.4 + 256; - if (!(pBuf = new uint8_t[base64Size]())) { - break; - } - int childRet = Base64EncodeBuf(input, length, pBuf); - if (childRet <= 0) { - break; - } - retVec.insert(retVec.begin(), pBuf, pBuf + childRet); - break; - } - if (pBuf) { - delete[] pBuf; - } - - return retVec; - } - - inline int CalcDecodeLength(const uint8_t *b64input) - { - int len = strlen(reinterpret_cast(const_cast(b64input))); - if (!len) { - return 0; - } - int padding = 0; - if (b64input[len - 1] == '=' && b64input[len - 2] == '=') { - // last two chars are = - padding = 2; // 2 : last two chars - } else if (b64input[len - 1] == '=') { - // last char is = - padding = 1; - } - return static_cast(len * 0.75 - padding); - } - - // return -1 error; >0 decode size - int Base64DecodeBuf(const uint8_t *input, const int length, uint8_t *bufOut) - { - int nRetLen = CalcDecodeLength(input); - if (!nRetLen) { - return 0; - } - - if (EVP_DecodeBlock(bufOut, input, length) > 0) { - return nRetLen; - } - return 0; - } - - string Base64Decode(const uint8_t *input, const int length) - { - string retString; - uint8_t *pBuf = nullptr; - while (true) { - if ((uint32_t)length > HDC_BUF_MAX_BYTES) { - break; - } - // must less than length - if (!(pBuf = new uint8_t[length]())) { - break; - } - int childRet = Base64DecodeBuf(input, length, pBuf); - if (childRet <= 0) { - break; - } - retString = (reinterpret_cast(pBuf)); - break; - } - if (pBuf) { - delete[] pBuf; - } - return retString; - } - - void ReverseBytes(void *start, int size) - { - uint8_t *istart = (uint8_t *)start; - uint8_t *iend = istart + size; - std::reverse(istart, iend); - } - - // clang-format off - const string StringFormat(const char * const formater, ...) - { - va_list vaArgs; - va_start(vaArgs, formater); - string ret = StringFormat(formater, vaArgs); - va_end(vaArgs); - return ret; - } - - const string StringFormat(const char * const formater, va_list &vaArgs) - { - std::vector args(MAX_SIZE_IOBUF); - const int retSize = vsnprintf_s(args.data(), MAX_SIZE_IOBUF, args.size() - 1, formater, vaArgs); - if (retSize < 0) { - return std::string(""); - } else { - return std::string(args.data(), retSize); - } - } - // clang-format on - - string GetVersion() - { - const uint8_t a = 'a'; - uint8_t major = (HDC_VERSION_NUMBER >> 28) & 0xff; - uint8_t minor = (HDC_VERSION_NUMBER << 4 >> 24) & 0xff; - uint8_t version = (HDC_VERSION_NUMBER << 12 >> 24) & 0xff; - uint8_t fix = (HDC_VERSION_NUMBER << 20 >> 28) & 0xff; // max 16, tail is p - string ver = StringFormat("%x.%x.%x%c", major, minor, version, a + fix); - return "Ver: " + ver; - } - - bool IdleUvTask(uv_loop_t *loop, void *data, uv_idle_cb cb) - { - uv_idle_t *idle = new uv_idle_t(); - if (idle == nullptr) { - return false; - } - idle->data = data; - uv_idle_init(loop, idle); - uv_idle_start(idle, cb); - // delete by callback - return true; - } - - bool TimerUvTask(uv_loop_t *loop, void *data, uv_timer_cb cb, int repeatTimeout) - { - uv_timer_t *timer = new uv_timer_t(); - if (timer == nullptr) { - return false; - } - timer->data = data; - uv_timer_init(loop, timer); - uv_timer_start(timer, cb, 0, repeatTimeout); - // delete by callback - return true; - } - - // callback, uint8_t flag, string msg, const void * data - bool DelayDo(uv_loop_t *loop, const int delayMs, const uint8_t flag, string msg, void *data, - std::function cb) - { - struct DelayDoParam { - uv_timer_t handle; - uint8_t flag; - string msg; - void *data; - std::function cb; - }; - auto funcDelayDo = [](uv_timer_t *handle) -> void { - DelayDoParam *st = (DelayDoParam *)handle->data; - st->cb(st->flag, st->msg, st->data); - uv_close((uv_handle_t *)handle, [](uv_handle_t *handle) { - DelayDoParam *st = (DelayDoParam *)handle->data; - delete st; - }); - }; - DelayDoParam *st = new DelayDoParam(); - if (st == nullptr) { - return false; - } - st->cb = cb; - st->flag = flag; - st->msg = msg; - st->data = data; - st->handle.data = st; - uv_timer_init(loop, &st->handle); - uv_timer_start(&st->handle, funcDelayDo, delayMs, 0); - return true; - } - - string ReplaceAll(string str, const string from, const string to) - { - string::size_type startPos = 0; - while ((startPos = str.find(from, startPos)) != string::npos) { - str.replace(startPos, from.length(), to); - startPos += to.length(); // Handles case where 'to' is a substring of 'from' - } - return str; - } - - string CanonicalizeSpecPath(string &src) - { - char resolvedPath[PATH_MAX] = { 0 }; -#if defined(_WIN32) - if (!_fullpath(resolvedPath, src.c_str(), PATH_MAX)) { - WRITE_LOG(LOG_FATAL, "_fullpath %s failed", src.c_str()); - return ""; - } -#else - if (realpath(src.c_str(), resolvedPath) == nullptr) { - WRITE_LOG(LOG_FATAL, "realpath %s failed", src.c_str()); - return ""; - } -#endif - string res(resolvedPath); - return res; - } - - uint8_t CalcCheckSum(const uint8_t *data, int len) - { - uint8_t ret = 0; - for (int i = 0; i < len; ++i) { - ret += data[i]; - } - return ret; - } - - int open_osfhandle(uv_os_fd_t os_fd) - { - // equal libuv's uv_open_osfhandle, libuv 1.23 added. old libuv not impl... -#ifdef _WIN32 - return _open_osfhandle((intptr_t)os_fd, 0); -#else - return os_fd; -#endif - } - - uv_os_sock_t DuplicateUvSocket(uv_tcp_t *tcp) - { - uv_os_sock_t dupFd = -1; -#ifdef _WIN32 - WSAPROTOCOL_INFO info; - ZeroStruct(info); - if (WSADuplicateSocketA(tcp->socket, GetCurrentProcessId(), &info) < 0) { - return dupFd; - } - dupFd = WSASocketA(0, 0, 0, &info, 0, 0); -#else - uv_os_fd_t fdOs; - if (uv_fileno((const uv_handle_t *)tcp, &fdOs) < 0) { - return ERR_API_FAIL; - } - dupFd = dup(open_osfhandle(fdOs)); -#endif - return dupFd; - } - - vector Md5Sum(uint8_t *buf, int size) - { - vector ret; - uint8_t md5Hash[MD5_DIGEST_LENGTH] = { 0 }; - if (EVP_Digest(buf, size, md5Hash, NULL, EVP_md5(), NULL)) { - ret.insert(ret.begin(), md5Hash, md5Hash + sizeof(md5Hash)); - } - return ret; - } - - string GetCwd() - { - char path[PATH_MAX] = ""; - size_t size = sizeof(path); - string res; - if (uv_cwd(path, &size) < 0) { - return res; - } - if (path[strlen(path) - 1] != Base::GetPathSep()) { - path[strlen(path)] = Base::GetPathSep(); - } - res = path; - return res; - } - - string GetTmpDir() - { - string res; -#ifdef HDC_HOST - char path[PATH_MAX] = ""; - size_t size = sizeof(path); - if (uv_os_tmpdir(path, &size) < 0) { - WRITE_LOG(LOG_FATAL, "get tmppath failed!"); - return res; - } - if (path[strlen(path) - 1] != Base::GetPathSep()) { - path[strlen(path)] = Base::GetPathSep(); - } - res = path; -#else - res = "/data/local/tmp/"; -#endif - return res; - } - - bool IsRoot() - { -#ifdef _WIN32 - // reserve - return true; -#else - if (getuid() == 0) { - return true; - } -#endif - return false; - } - - bool IsAbsolutePath(string &path) - { - bool ret = false; -#ifdef _WIN32 - // shlwapi.h PathIsRelativeA not link in harmony project - // c:\ or UNC path '\\hostname\share\file' - ret = path.find(":\\") == 1 || path.find("\\\\") == 0; -#else - ret = path[0] == '/'; -#endif - return ret; - } -} -} // namespace Hdc diff --git a/services/flashd/daemon/daemon_unity.cpp b/services/flashd/daemon/daemon_unity.cpp index 5a4aa067..cbe17806 100755 --- a/services/flashd/daemon/daemon_unity.cpp +++ b/services/flashd/daemon/daemon_unity.cpp @@ -15,9 +15,7 @@ #include "daemon_unity.h" #include #ifdef __MUSL__ -extern "C" { #include "init_reboot.h" -} #endif namespace Hdc { diff --git a/services/flashd/host/client.cpp b/services/flashd/host/client.cpp index a1b93bcd..b2877c6b 100755 --- a/services/flashd/host/client.cpp +++ b/services/flashd/host/client.cpp @@ -168,7 +168,7 @@ int HdcClient::ExecuteCommand(const string &commandIn) ConnectServerForClient(ip, port); uv_timer_init(loopMain, &waitTimeDoCmd); waitTimeDoCmd.data = this; - uv_timer_start(&waitTimeDoCmd, CommandWorker, 10, 10); + uv_timer_start(&waitTimeDoCmd, CommandWorker, 10, 10); // 10 10 repeat WorkerPendding(); return 0; } diff --git a/services/flashd/host/main.cpp b/services/flashd/host/main.cpp index 878428c7..3fe5d5b8 100755 --- a/services/flashd/host/main.cpp +++ b/services/flashd/host/main.cpp @@ -175,7 +175,7 @@ bool ParseServerListenString(string &serverListenString, char *optarg) } char *p = strchr(buf, ':'); if (!p) { // Only port - if (strlen(buf) > 5) { // port len + if (strlen(buf) > 5) { // 5 port len Base::PrintMessage("The port-string's length must < 5"); return false; } -- Gitee