diff --git a/BUILD.gn b/BUILD.gn index 6b9ab874cb253d808c1fe3462acbe48d36daa866..807653d0a40607fcea3eb99d20393d75bc712ff4 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -61,7 +61,11 @@ ohos_executable("hdcd") { "//third_party/openssl:crypto_source", "//utils/native/base:utils", ] - + if (use_musl) { + deps += [ + "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", + ] + } include_dirs = [ "${HDC_PATH}/daemon", "//utils/native/base/include", @@ -69,6 +73,11 @@ ohos_executable("hdcd") { "//third_party/openssl/include", "//third_party/libuv", ] + if (use_musl) { + include_dirs += [ + "//base/startup/syspara_lite/interfaces/innerkits/native/syspara/include", + ] + } install_enable = true subsystem_name = "developtools" part_name = "hdc_standard" diff --git a/prebuilt/README_zh.md b/prebuilt/README_zh.md index 1d076c0a839fbb22fec6201a1c45d4020aa3501a..cf6a3428a6081076555934732663ccfa90090457 100644 --- a/prebuilt/README_zh.md +++ b/prebuilt/README_zh.md @@ -1,11 +1,20 @@ # 几点说明: [1.通过git clone方式下载](#section662115419449) -建议通过gitclone方式下载该仓 命令为: +建议通过gitclone方式下载该仓 +外仓命令为: **git clone git@gitee.com:openharmony/developtools_hdc_standard.git** +合作仓命令为: +**git clone git@gitee.com:OHOS_STD/developtools_hdc_standard.git** [2.通过网页形式下载](#section15908143623714) -通过网页形式下载prebuilt,请 使用类似如下URL打开网页 https://gitee.com/openharmony/developtools_hdc_standard/blob/master/prebuilt/windows/hdc-std.exe ,点击中间下载方式进行下载,windows版本文件大小在**5M左右**,linux版本在**2M左右**,不要使用右击另存为方式进行保存下载,下载后检查文件大小。 +通过网页形式下载prebuilt,请 使用类似如下URL打开网页 https://gitee.com/openharmony/developtools_hdc_standard/blob/master/prebuilt/windows/hdc-std.exe ,点击中间下载方式进行下载,windows版本文件大小在**5M左右**,linux版本在**2M左右**,不要使用右击另存为方式进行保存下载,下载后检查文件大小(说三遍)。 [3.支持环境](#section161941989596) -支持运行环境 linux版本建议ubuntu20 CentOS8 64位,其他版本相近也应该可以,libc++.so引用错误请使用ldd\readelf等命令检查库引用 windows版本建议windows10 64位,windows8也应该可以,Windows7等EOF版本尚未测试,如果低版本windows winusb库缺失,请使用zadia更新库。 \ No newline at end of file +支持运行环境 linux版本建议ubuntu20 CentOS8 64位,其他版本相近也应该可以,libc++.so引用错误请使用ldd/readelf等命令检查库引用 windows版本建议windows10 64位,windows8也应该可以,Windows7等EOF版本尚未测试,如果低版本windows winusb库缺失,请使用zadig更新库。 + +[4.关于Issue](#section161941989596) +近期hdc刚开发完成,适配和调整变动较多,如果遇到异常情况,建议按照如下步骤进行排查: +1)首先核对server与daemon版本是否匹配,hdc-std -v, hdcd -v。 +2)更新工程最新的线上代码和预编译文件,是否在后续版本中已解决问题。 +3)规范的和详细的提出issue,我们将尽快跟进。 diff --git a/prebuilt/linux/hdc_std b/prebuilt/linux/hdc_std index 745e97d5644ee0aadf0a03a663c28e6e746d8ded..2c31bd319eeaec08c8cf5aeef63d0c3c8aa95bbf 100755 Binary files a/prebuilt/linux/hdc_std and b/prebuilt/linux/hdc_std differ diff --git a/prebuilt/windows/hdc_std.exe b/prebuilt/windows/hdc_std.exe index c61be9369edb13c80d653bcbd7bc2fe15a151eee..18f49eba614fe6613d39526d5033f59c11cae992 100644 --- a/prebuilt/windows/hdc_std.exe +++ b/prebuilt/windows/hdc_std.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b668bf2366c668b6d213eeb57bad3105cb2679f96441ef7b71d4334846698f40 -size 4664727 +oid sha256:8f969acb481533102a41fc2262a18d99d2cd9f58bb7d7860519f44b225cf7918 +size 3301376 diff --git a/src/common/async_cmd.cpp b/src/common/async_cmd.cpp index edba9d14d96728487887d8a3564aff1db8a21f1a..ee541af1575be177beed3ed625c960cb12c8eb08 100644 --- a/src/common/async_cmd.cpp +++ b/src/common/async_cmd.cpp @@ -39,43 +39,57 @@ bool AsyncCmd::ReadyForRelease() const return !running; } +// manual stop will not trigger ExitCallback, we call it void AsyncCmd::DoRelease() { - if (!running) { + if (hasStop || !running) { return; } - stdinPipe.data = this; - stdoutPipe.data = this; - stderrPipe.data = this; - Base::TryCloseHandle((uv_handle_t *)&stdinPipe); - Base::TryCloseHandle((uv_handle_t *)&stdoutPipe); - Base::TryCloseHandle((uv_handle_t *)&stderrPipe); - uv_process_kill(&proc, 0); + hasStop = true; // must set here to deny repeate release + ExitCallback(&proc, 0, 0); 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) { - WRITE_LOG(LOG_DEBUG, "Read ShellChildProcess failed:%s", uv_err_name(nread)); + if (nread <= 0) { // stdout and stderr + WRITE_LOG(LOG_DEBUG, "Read ShellChildProcess failed %s", uv_err_name(nread)); } else { - thisClass->cmdResult += buf->base; + if (thisClass->options & OPTION_READBACK_OUT) { + thisClass->cmdResult = buf->base; + thisClass->resultCallback(false, 0, thisClass->cmdResult); + 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->resultCallback(exitStatus == 0, thisClass->cmdResult); - thisClass->running = false; + thisClass->hasStop = true; // callback maybe call dorelease, so deny repeate ExitCallback + + thisClass->resultCallback(true, exitStatus, thisClass->cmdResult); WRITE_LOG(LOG_DEBUG, "AsyncCmd::ExitCallback"); - Base::TryCloseHandle((uv_handle_t *)req); + 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); + uv_process_kill(req, SIGKILL); thisClass->cmdResult = STRING_EMPTY; } -bool AsyncCmd::Initial(uv_loop_t *loopIn, const CmdResultCallback callback) +bool AsyncCmd::Initial(uv_loop_t *loopIn, const CmdResultCallback callback, uint32_t optionsIn) { if (running) { return false; @@ -85,14 +99,17 @@ bool AsyncCmd::Initial(uv_loop_t *loopIn, const CmdResultCallback callback) if (StartProcess() < 0) { return false; } + options = optionsIn; return true; } -bool AsyncCmd::ExecuteCommand(const string &command, bool once) const +bool AsyncCmd::ExecuteCommand(const string &command) const { string cmd = command; - cmd += "\n"; - if (once) { + if (options & OPTION_APPEND_NEWLINE) { + cmd += "\n"; + } + if (options & OPTION_COMMAND_ONETIME) { cmd += "exit\n"; } Base::SendToStream((uv_stream_t *)&stdinPipe, (uint8_t *)cmd.c_str(), cmd.size() + 1); @@ -109,6 +126,7 @@ int AsyncCmd::StartProcess() 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; @@ -141,7 +159,7 @@ int AsyncCmd::StartProcess() } if (!running) { // failed - resultCallback(false, "Start process failed"); + resultCallback(true, -1, "Start process failed"); return -1; } else { return 0; diff --git a/src/common/async_cmd.h b/src/common/async_cmd.h index 4a2f053844828de2650ca55f477f2249be93d08d..ca063f5d704c622433983bdc6e6895e3daeac66d 100644 --- a/src/common/async_cmd.h +++ b/src/common/async_cmd.h @@ -21,22 +21,32 @@ class AsyncCmd { public: AsyncCmd(); virtual ~AsyncCmd(); - - using CmdResultCallback = std::function; + 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); + bool Initial(uv_loop_t *loopIn, const CmdResultCallback callback, uint32_t optionsIn = GetDefaultOption()); void DoRelease(); // Release process resources - bool ExecuteCommand(const string &command, bool once = true) const; + bool ExecuteCommand(const string &command) const; bool ReadyForRelease() const; private: - uv_loop_t *loop; int StartProcess(); // 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; @@ -46,6 +56,9 @@ private: CmdResultCallback resultCallback; string cmdResult; bool running; + bool hasStop = false; + uint32_t options; + uint8_t uvRef = 0; }; } // namespace Hdc #endif \ No newline at end of file diff --git a/src/common/auth.cpp b/src/common/auth.cpp index 70d3b3b6c254bbfeffb1e593bf21b4b936852c90..bc55681e04da41e35630ab1a8771951bfb5a1148 100644 --- a/src/common/auth.cpp +++ b/src/common/auth.cpp @@ -165,7 +165,7 @@ int WritePublicKeyfile(RSA *private_key, const char *private_key_path) 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 ? ret : 0; + return ret >= 0 ? 1 : 0; } bool GenerateKey(const char *file) diff --git a/src/common/base.cpp b/src/common/base.cpp index 7298624cc473011b79ce46c973e0f7c70be1afaa..47767e469a5995309ea2ece1106b4197f878c3dd 100644 --- a/src/common/base.cpp +++ b/src/common/base.cpp @@ -19,7 +19,13 @@ #include #include #include +#include #include +#ifdef __MUSL__ +extern "C" { +#include "parameter.h" +} +#endif using namespace std::chrono; namespace Hdc { @@ -40,7 +46,7 @@ namespace Base { #ifdef _WIN32 currentThreadId = GetCurrentThreadId(); #else - currentThreadId = uv_thread_self(); // 64 just use 32bit + currentThreadId = uv_thread_self(); // 64bit OS, just dispaly 32bit ptr #endif debugInfo = StringFormat("%s:%d", tmpString.c_str(), line); if (g_logLevel < LOG_FULL) { @@ -261,7 +267,7 @@ namespace Base { } if (ptrLoop->active_handles >= 2) { - WRITE_LOG(LOG_WARN, "TryCloseLoop issue"); + WRITE_LOG(LOG_DEBUG, "TryCloseLoop issue"); } auto clearLoopTask = [](uv_handle_t *handle, void *arg) -> void { TryCloseHandle(handle); }; uv_walk(ptrLoop, clearLoopTask, nullptr); @@ -285,15 +291,23 @@ namespace Base { // Some handles may not be initialized or activated yet or have been closed, skip the closing process void TryCloseHandle(const uv_handle_t *handle) { - if (handle->loop && !uv_is_closing(handle)) { - uv_close((uv_handle_t *)handle, nullptr); - } + 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); } } @@ -528,6 +542,7 @@ namespace Base { 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 @@ -535,6 +550,9 @@ namespace Base { string sValue = value; string sBuf = "setprop " + sKey + " " + value; system(sBuf.c_str()); +#endif +#else + SetParameter(key, value); #endif return true; } @@ -552,10 +570,6 @@ namespace Base { 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 - // bufLen == 0: alloc buffer in heap, need free it later // >0: read max nBuffLen bytes to *buff // ret value: <0 or bytes read @@ -574,7 +588,7 @@ namespace Base { ret = -3; if (bufLen == 0) { dynamicBuf = 1; - pDst = new uint8_t[nFileSize]; + pDst = new uint8_t[nFileSize + 1](); // tail \0 if (!pDst) { return -1; } @@ -583,7 +597,6 @@ namespace Base { if (nFileSize > bufLen) { return -2; } - readMax = nFileSize; pDst = reinterpret_cast(buf); // The first address of the static array is the array address } @@ -616,16 +629,21 @@ namespace Base { int WriteBinFile(const char *pathName, const uint8_t *buf, const int bufLen, bool newFile) { - char mode[BUF_SIZE_TINY] = ""; + string mode; + string resolvedPath; + string srcPath(pathName); if (newFile) { - strcpy_s(mode, sizeof(mode), "wb+"); + 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 { - strcpy_s(mode, sizeof(mode), "a+"); + mode = "a+"; + resolvedPath = CanonicalizeSpecPath(srcPath); } - - string srcPath(pathName); - string resolvedPath = CanonicalizeSpecPath(srcPath); - FILE *fp = fopen(resolvedPath.c_str(), mode); + 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; @@ -667,9 +685,8 @@ namespace Base { if (snprintf_s(pidBuf, sizeof(pidBuf), sizeof(pidBuf) - 1, "%d", pid) < 0) { return ERR_BUF_OVERFLOW; } - string srcPath(bufPath); - string resolvedPath = CanonicalizeSpecPath(srcPath); - int fd = open(resolvedPath.c_str(), O_RDWR | O_CREAT, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)); + // no need to CanonicalizeSpecPath, else not work + int fd = open(bufPath, O_RDWR | O_CREAT, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)); if (fd < 0) { WRITE_LOG(LOG_FATAL, "Open mutex file \"%s\" failed!!!\n", buf); return ERR_FILE_OPEN; @@ -1113,5 +1130,16 @@ namespace Base { #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; + } + } } // namespace Hdc diff --git a/src/common/base.h b/src/common/base.h index 9357650596f8944c047e94f01ebb6441a48298b7..2014bd2d10c6288610d1a284b9d6d898ed032495 100644 --- a/src/common/base.h +++ b/src/common/base.h @@ -49,6 +49,7 @@ namespace Base { 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 @@ -56,7 +57,7 @@ namespace Base { 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); + 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); @@ -105,10 +106,15 @@ namespace Base { { 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); + } string ReplaceAll(string str, const string from, const string to); uint8_t CalcCheckSum(const uint8_t *data, int len); string GetFileNameAny(string &path); uv_os_sock_t DuplicateUvSocket(uv_tcp_t *tcp); + vector Md5Sum(uint8_t *buf, int size); } // namespace base } // namespace Hdc diff --git a/src/common/define.h b/src/common/define.h index fc3a8a440b54f224c153090cd55a9710d3c30610..ee2f6ad44d75c45e29d54dc539a158087b707cfe 100644 --- a/src/common/define.h +++ b/src/common/define.h @@ -41,24 +41,27 @@ 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 uint8_t DWORD_SERIALIZE_SIZE = 4; constexpr uint32_t HDC_BUF_MAX_BYTES = 1024000000; constexpr uint16_t MAX_IP_PORT = 65535; constexpr uint8_t STREAM_MAIN = 0; // work at main thread constexpr uint8_t STREAM_WORK = 1; // work at work thread constexpr uint16_t MAX_CONNECTKEY_SIZE = 32; // usb sn/tcp ipport -constexpr uint8_t MAX_IO_OVERLAP = 16; -constexpr auto TIME_BASE = 1000; // time unit conversion base value +constexpr uint8_t MAX_IO_OVERLAP = 255; // +constexpr auto TIME_BASE = 1000; // time unit conversion base value +constexpr uint16_t AID_SHELL = 2000; // general one argument command argc constexpr int CMD_ARG1_COUNT = 2; // The first child versions must match, otherwise server and daemon must be upgraded -const string VERSION_NUMBER = "1.1.0d"; // same with openssl version, 1.1.2==VERNUMBER 0x10102000 +const string VERSION_NUMBER = "1.1.0p"; // same with openssl version, 1.1.2==VERNUMBER 0x10102000 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"; @@ -88,291 +91,5 @@ const string CMDSTR_APP_INSTALL = "install"; const string CMDSTR_APP_UNINSTALL = "uninstall"; const string CMDSTR_APP_SIDELOAD = "sideload"; const string CMDSTR_LIST_JDWP = "list jpid"; -// ############################# 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 { - ERR_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_PARM_FORMAT = -12000, - ERR_PARM_SIZE, - ERR_PARM_FAIL, - ERR_API_FAIL = -13000, - ERR_IO_FAIL = -14000, - ERR_IO_TIMEOUT, - ERR_SESSION_NOFOUND = -15000, - ERR_SESSION_OFFLINE, - ERR_SESSION_DEAD, - ERR_HANDSHAKE_NOTMATCH = -16000, - ERR_HANDSHAKE_CONNECTKEY_FAILED, - ERR_SOCKET_FAIL = -17000, - ERR_SOCKET_DUPLICATE, -}; - -// 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, - // 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, - // 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, -}; - -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 - uint16_t retryCount; - libusb_device *device; - libusb_device_handle *devHandle; - uint8_t interfaceNumber; - // 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 bufSizeDevice; // packetSizeD2H - uint8_t *bufDevice; - uint8_t *bufHost; - uint32_t bufSizeHost; - string serialNumber; - string usbMountPoint; - libusb_context *ctxUSB = nullptr; // child-use, main null - libusb_transfer *transferRecv; -#endif - // usb accessory FunctionFS - // USB main thread use, sub-thread disable, sub-thread uses the main thread USB handle - int bulkOut; // EP1 - int bulkIn; // EP2 - vector bufRecv; -}; -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 - 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; // 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 - 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 *; } // namespace Hdc #endif // HDC_DEFINE_H diff --git a/src/common/define_plus.h b/src/common/define_plus.h index d0081f9d941f9e0cdc43f1bb5f08c4728ffad111..c3de4a5b10044a4c675c1cc2738dd968776831eb 100644 --- a/src/common/define_plus.h +++ b/src/common/define_plus.h @@ -16,5 +16,297 @@ #define DEFINE_PLUS_H namespace Hdc { +// ############################# 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 { + ERR_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_SESSION_NOFOUND = -15000, + ERR_SESSION_OFFLINE, + ERR_SESSION_DEAD, + ERR_HANDSHAKE_NOTMATCH = -16000, + ERR_HANDSHAKE_CONNECTKEY_FAILED, + 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, +}; + +// 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, + // 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, + // 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, +}; + +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 + uint16_t retryCount; + libusb_device *device; + libusb_device_handle *devHandle; + uint8_t interfaceNumber; + // 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 bufSizeDevice; // packetSizeD2H + uint8_t *bufDevice; + uint8_t *bufHost; + uint32_t bufSizeHost; + string serialNumber; + string usbMountPoint; + libusb_context *ctxUSB = nullptr; // child-use, main null + libusb_transfer *transferRecv; +#endif + // usb accessory FunctionFS + // USB main thread use, sub-thread disable, sub-thread uses the main thread USB handle + int bulkOut; // EP1 + int bulkIn; // EP2 + vector bufRecv; +}; +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; // 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 + 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/src/common/file.cpp b/src/common/file.cpp index 85a994efbba364c4a5953f46198fd98c5dbac61c..834024b46031b541cc8f711b91e2c1995b579528 100644 --- a/src/common/file.cpp +++ b/src/common/file.cpp @@ -45,6 +45,7 @@ bool HdcFile::BeginTransfer(CtxFile *context, const char *command) const string CMD_OPTION_TSTMP = "-a"; const string CMD_OPTION_SYNC = "-sync"; const string CMD_OPTION_ZIP = "-z"; + char **argv = Base::SplitCommandToArgs(command, &argc); if (argc < CMD_ARG1_COUNT) { goto Finish; @@ -69,14 +70,16 @@ bool HdcFile::BeginTransfer(CtxFile *context, const char *command) } else { context->localPath = argv[0]; } + if (!Base::CheckDirectoryOrPath(context->localPath.c_str(), true, true)) { goto Finish; } context->localName = Base::GetFullFilePath(context->localPath); ++refCount; - uv_fs_open(loopTask, &context->fsOpenReq, context->localPath.c_str(), O_RDONLY, 0, OnFileOpen); + uv_fs_open(loopTask, &context->fsOpenReq, context->localPath.c_str(), O_RDONLY, S_IWUSR | S_IRUSR, OnFileOpen); context->master = true; ret = true; + Finish: if (!ret) { LogMsg(MSG_FAIL, "Transfer master path failed"); diff --git a/src/common/forward.cpp b/src/common/forward.cpp index 431887ed96c856f5f186676bce663e4cbe2921fd..91c15c54ddf36b2a1b681b3e10469e90e8f8e3d3 100644 --- a/src/common/forward.cpp +++ b/src/common/forward.cpp @@ -23,7 +23,6 @@ HdcForwardBase::HdcForwardBase(HTaskInfo hTaskInfo) HdcForwardBase::~HdcForwardBase() { - runningProtect = false; WRITE_LOG(LOG_DEBUG, "~HdcForwardBase"); }; @@ -44,7 +43,6 @@ void HdcForwardBase::StopTask() } // FREECONTEXT in the STOP is triggered by the other party sector, no longer notifying each other. mapCtxPoint.clear(); - runningProtect = false; }; void HdcForwardBase::OnAccept(uv_stream_t *server, HCtxForward ctxClient, uv_stream_t *client) @@ -94,12 +92,10 @@ void HdcForwardBase::ListenCallback(uv_stream_t *server, const int status) if (FORWARD_TCP == ctxListen->type) { uv_tcp_init(ctxClient->thisClass->loopTask, &ctxClient->tcp); client = (uv_stream_t *)&ctxClient->tcp; - ctxClient->tcp.data = ctxClient; } else { // FORWARD_ABSTRACT, FORWARD_RESERVED, FORWARD_FILESYSTEM, uv_pipe_init(ctxClient->thisClass->loopTask, &ctxClient->pipe, 0); client = (uv_stream_t *)&ctxClient->pipe; - ctxClient->pipe.data = ctxClient; } thisClass->OnAccept(server, ctxClient, client); } @@ -114,6 +110,8 @@ void *HdcForwardBase::MallocContext(bool masterSlave) 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; @@ -122,7 +120,10 @@ void *HdcForwardBase::MallocContext(bool masterSlave) void HdcForwardBase::FreeContextCallBack(HCtxForward ctx) { AdminContext(OP_REMOVE, ctx->id, nullptr); - delete ctx; + Base::DoNextLoop(loopTask, ctx, [](const uint8_t flag, string &msg, const void *data) { + HCtxForward ctx = (HCtxForward)data; + delete ctx; + }); --refCount; } @@ -176,12 +177,12 @@ void HdcForwardBase::FreeContext(HCtxForward ctxIn, const uint32_t id, bool bNot switch (ctx->type) { case FORWARD_TCP: case FORWARD_JDWP: - Base::TryCloseHandle((uv_handle_t *)&ctx->tcp, funcHandleClose); + 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, funcHandleClose); + Base::TryCloseHandle((uv_handle_t *)&ctx->pipe, true, funcHandleClose); break; case FORWARD_DEVICE: { FreeJDWP(ctx); @@ -249,6 +250,9 @@ 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); } @@ -520,11 +524,15 @@ bool HdcForwardBase::SlaveConnect(uint8_t *bufCmd, bool bCheckPoint, string &sEr if (!CheckNodeInfo(content, ctxPoint->localArgs)) { return false; } - if (!SetupPoint(ctxPoint)) { - WRITE_LOG(LOG_FATAL, "SetupPoint failed"); - goto Finish; + if ((ctxPoint->checkPoint && slaveCheckWhenBegin) || !ctxPoint->checkPoint) { + if (!SetupPoint(ctxPoint)) { + WRITE_LOG(LOG_FATAL, "SetupPoint failed"); + goto Finish; + } + sError = ctxPoint->lastError; + } else { + SetupPointContinue(ctxPoint, 0); } - sError = ctxPoint->lastError; ret = true; Finish: if (!ret) { @@ -702,7 +710,6 @@ bool HdcForwardBase::CommandDispatch(const uint16_t command, uint8_t *payload, c string sError; // prepare if (CMD_FORWARD_INIT == command) { - runningProtect = true; if (!BeginForward((char *)(payload), sError)) { ret = false; goto Finish; @@ -710,7 +717,6 @@ bool HdcForwardBase::CommandDispatch(const uint16_t command, uint8_t *payload, c return true; } else if (CMD_FORWARD_CHECK == command) { // Detect remote if it's reachable - runningProtect = true; if (!SlaveConnect(payload, true, sError)) { ret = false; goto Finish; diff --git a/src/common/forward.h b/src/common/forward.h index d528bf17f3ac8fcf0292624dba1da3ed4b09001c..5bc1cfb6ed461f1f9edc9574bd7daec89330a01f 100644 --- a/src/common/forward.h +++ b/src/common/forward.h @@ -66,9 +66,6 @@ protected: bool SetupPointContinue(HCtxForward ctx, int status); private: - const uint8_t FORWARD_PARAMENTER_BUFSIZE = 8; - const string FILESYSTEM_SOCKET_PREFIX = "/tmp/"; - const string HARMONY_RESERVED_SOCKET_PREFIX = "/dev/socket/"; 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); @@ -99,6 +96,11 @@ private: 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/src/common/serial_struct_define.h b/src/common/serial_struct_define.h old mode 100755 new mode 100644 index 7facd07854713d68bc79675163862b40db03e548..a17dfc6e6f4df76fe1a7e170dbd0b7c5836b0946 --- a/src/common/serial_struct_define.h +++ b/src/common/serial_struct_define.h @@ -24,6 +24,7 @@ #include #include +// static file define. No need not modify. by zako namespace Hdc { // clang-format off namespace SerialStruct { diff --git a/src/common/session.cpp b/src/common/session.cpp index 0f7d22d59b948e81dc779df090145a434749e8be..5ae19c9a3f93e5787c13a7d90006200d25982b15 100644 --- a/src/common/session.cpp +++ b/src/common/session.cpp @@ -20,7 +20,6 @@ HdcSessionBase::HdcSessionBase(bool serverOrDaemonIn) { 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); @@ -38,7 +37,6 @@ HdcSessionBase::HdcSessionBase(bool serverOrDaemonIn) HdcSessionBase::~HdcSessionBase() { - WRITE_LOG(LOG_DEBUG, "~HdcSessionBase"); Base::TryCloseHandle((uv_handle_t *)&asyncMainLoop); uv_loop_close(&loopMain); // clear base @@ -49,7 +47,8 @@ HdcSessionBase::~HdcSessionBase() libusb_exit((libusb_context *)ctxUSB); } #endif - WRITE_LOG(LOG_DEBUG, "~HdcSessionBase free"); + WRITE_LOG(LOG_DEBUG, "~HdcSessionBase free sessionRef:%d instance:%s", uint32_t(sessionRef), + serverOrDaemon ? "server" : "daemon"); } // remove step2 @@ -140,8 +139,7 @@ void HdcSessionBase::ClearSessions() } void HdcSessionBase::ReMainLoopForInstanceClear() -{ - // reloop +{ // reloop auto clearSessionsForFinish = [](uv_idle_t *handle) -> void { HdcSessionBase *thisClass = (HdcSessionBase *)handle->data; if (thisClass->sessionRef > 0) { @@ -152,11 +150,7 @@ void HdcSessionBase::ReMainLoopForInstanceClear() uv_stop(&thisClass->loopMain); }; Base::IdleUvTask(&loopMain, this, clearSessionsForFinish); - uv_run(&loopMain, UV_RUN_DEFAULT); - uv_rwlock_wrlock(&lockMapSession); - mapSession.clear(); - uv_rwlock_wrunlock(&lockMapSession); }; void HdcSessionBase::EnumUSBDeviceRegister(void (*pCallBack)(HSession hSession)) @@ -334,6 +328,17 @@ int HdcSessionBase::MallocSessionByConnectType(HSession hSession) 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) @@ -349,14 +354,14 @@ HSession HdcSessionBase::MallocSession(bool serverOrDaemon, const ConnType connT hSession->connType = connType; hSession->classModule = classModule; hSession->isDead = false; - hSession->sessionId = ((sessionId == 0) ? static_cast(Base::GetRuntimeMSec()) : sessionId); + 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:%d", hSession->sessionId); + WRITE_LOG(LOG_DEBUG, "HdcSessionBase NewSession, sessionId:%u", hSession->sessionId); uv_tcp_init(&loopMain, &hSession->ctrlPipe[STREAM_MAIN]); ++hSession->uvRef; @@ -434,7 +439,7 @@ void HdcSessionBase::FreeSessionFinally(uv_idle_t *handle) thisClass->NotifyInstanceSessionFree(hSession, true); // all hsession uv handle has been clear thisClass->AdminSession(OP_REMOVE, hSession->sessionId, nullptr); - WRITE_LOG(LOG_DEBUG, "!!!FreeSessionFinally sessionId:%d finish", hSession->sessionId); + 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); @@ -451,7 +456,7 @@ void HdcSessionBase::FreeSessionContinue(HSession hSession) }; if (CONN_TCP == hSession->connType) { // Turn off TCP to prevent continuing writing - Base::TryCloseHandle((uv_handle_t *)&hSession->hWorkTCP, closeSessionTCPHandle); + Base::TryCloseHandle((uv_handle_t *)&hSession->hWorkTCP, true, closeSessionTCPHandle); } hSession->availTailIndex = 0; if (hSession->ioBuf) { @@ -486,7 +491,7 @@ void HdcSessionBase::FreeSessionOpeate(uv_timer_t *handle) 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:%d", hSession->sessionId); + 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; @@ -519,7 +524,7 @@ void HdcSessionBase::FreeSession(const uint32_t sessionId) hSession->isDead = true; Base::TimerUvTask(&loopMain, hSession, FreeSessionOpeate); NotifyInstanceSessionFree(hSession, false); - WRITE_LOG(LOG_DEBUG, "FreeSession sessionid:%d sendref:%u", hSession->sessionId, uint16_t(hSession->sendRef)); + 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) @@ -617,7 +622,7 @@ int HdcSessionBase::Send(const uint32_t sessionId, const uint32_t channelId, con { HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr); if (!hSession) { - WRITE_LOG(LOG_DEBUG, "Send to offline device, drop it, sessionid:%d", sessionId); + WRITE_LOG(LOG_DEBUG, "Send to offline device, drop it, sessionId:%u", sessionId); return ERR_SESSION_NOFOUND; } PayloadProtect protectBuf; // noneed convert to big-endian @@ -811,9 +816,8 @@ bool HdcSessionBase::WorkThreadStartSession(HSession hSession) { bool regOK = false; int childRet = 0; - HdcTCPBase *pTCPBase = (HdcTCPBase *)hSession->classModule; - HdcUSBBase *pUSBBase = (HdcUSBBase *)hSession->classModule; 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"); @@ -827,6 +831,7 @@ bool HdcSessionBase::WorkThreadStartSession(HSession hSession) 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); } @@ -841,7 +846,7 @@ bool HdcSessionBase::WorkThreadStartSession(HSession hSession) string hs = SerialStruct::SerializeToString(handshake); Send(hSession->sessionId, 0, CMD_KERNEL_HANDSHAKE, (uint8_t *)hs.c_str(), hs.size()); } - return true; + return regOK; } vector HdcSessionBase::BuildCtrlString(InnerCtrlCommand command, uint32_t channelId, uint8_t *data, @@ -873,16 +878,29 @@ bool HdcSessionBase::DispatchMainThreadCommand(HSession hSession, const CtrlStru 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"); + 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"); - Base::TryCloseHandle((uv_handle_t *)&hSession->hChildWorkTCP); - Base::TryCloseHandle((uv_handle_t *)&hSession->ctrlPipe[STREAM_WORK]); - Base::TryCloseHandle((uv_handle_t *)&hSession->dataPipe[STREAM_WORK]); - uv_stop(&hSession->childLoop); + 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: { @@ -965,13 +983,14 @@ void HdcSessionBase::SessionWorkThread(uv_work_t *arg) 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:%d", hSession->sessionId); + 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:%d", hSession->sessionId); + 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:%d", hSession->sessionId); + WRITE_LOG(LOG_DEBUG, "!!!Workthread run finish, sessionId:%u workthread:%p", hSession->sessionId, uv_thread_self()); } // clang-format off @@ -1025,4 +1044,12 @@ bool HdcSessionBase::DispatchTaskData(HSession hSession, const uint32_t channelI } 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/src/common/session.h b/src/common/session.h index c91fa7573228adcaea6a63ae9c4383604f200fcd..8421515f0035bd2adc17781e5b09f1e51504e2df 100644 --- a/src/common/session.h +++ b/src/common/session.h @@ -55,6 +55,8 @@ public: 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, ...); @@ -169,6 +171,7 @@ private: int MallocSessionByConnectType(HSession hSession); void FreeSessionByConnectType(HSession hSession); bool WorkThreadStartSession(HSession hSession); + uint32_t GetSessionPseudoUid(); map mapSession; uv_rwlock_t lockMapSession; diff --git a/src/common/task.h b/src/common/task.h index 9c71930647e6878b3d421ead40fa1487589da096..23b61497ed8647ea0801af0403a8f5f9c47e0b2f 100644 --- a/src/common/task.h +++ b/src/common/task.h @@ -45,9 +45,9 @@ protected: 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 runningProtect; - bool childReady; // Subcompulents have been prepared - bool singalStop; // Request stop signal + bool runningProtect; // [deprecated]will be remove, please use refCount + bool childReady; // Subcompulents have been prepared + bool singalStop; // Request stop signal HTaskInfo taskInfo; uint32_t refCount; diff --git a/src/common/transfer.cpp b/src/common/transfer.cpp index 00f01892ced1996d4be21a57b58706bfa8ebd141..9bb86d7637f079b178a9378b0b1107dacea65244 100644 --- a/src/common/transfer.cpp +++ b/src/common/transfer.cpp @@ -232,6 +232,7 @@ 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), diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 1b146677cdff973242dd19a4657aac6724ff2732..cba5cb7676325febadcd572ec45a0e9bbf5f8529 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -24,7 +24,6 @@ HdcDaemon::HdcDaemon(bool serverOrDaemonIn) clsUSBServ = nullptr; clsJdwp = nullptr; enableSecure = false; - isStopped = false; } HdcDaemon::~HdcDaemon() @@ -34,7 +33,7 @@ HdcDaemon::~HdcDaemon() void HdcDaemon::ClearInstanceResource() { - StopInstance(); + TryStopInstance(); Base::TryCloseLoop(&loopMain, "HdcDaemon::~HdcDaemon"); if (clsTCPServ) { delete (HdcDaemonTCP *)clsTCPServ; @@ -51,11 +50,8 @@ void HdcDaemon::ClearInstanceResource() WRITE_LOG(LOG_DEBUG, "~HdcDaemon finish"); } -void HdcDaemon::StopInstance() +void HdcDaemon::TryStopInstance() { - if (isStopped) { - return; - } ClearSessions(); if (clsTCPServ) { WRITE_LOG(LOG_DEBUG, "Stop TCP"); @@ -67,7 +63,7 @@ void HdcDaemon::StopInstance() } ((HdcJdwp *)clsJdwp)->Stop(); // workaround temply remove MainLoop instance clear - isStopped = true; + ReMainLoopForInstanceClear(); WRITE_LOG(LOG_DEBUG, "Stop loopmain"); } @@ -307,13 +303,6 @@ bool HdcDaemon::RemoveInstanceTask(const uint8_t op, HTaskInfo hTask) return ret; } -void HdcDaemon::StopDaemon(bool restart) -{ - PushAsyncMessage(0, ASYNC_STOP_MAINLOOP, nullptr, 0); - WRITE_LOG(LOG_DEBUG, "StopDaemon has sended"); - wantRestart = restart; -} - bool HdcDaemon::ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, uint8_t *bufPtr, const int size) { diff --git a/src/daemon/daemon.h b/src/daemon/daemon.h index 3f1fa10f9c52ec64f451ea4a613caecb31cfc906..3e7e6f353f3b8385689d694913022e4e9db4716b 100644 --- a/src/daemon/daemon.h +++ b/src/daemon/daemon.h @@ -26,9 +26,6 @@ public: const int payloadSize); bool ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, uint8_t *bufPtr, const int size); - void StopInstance(); - void StopDaemon(bool restart); // Thread security interface for global stop programs - void *clsTCPServ; void *clsUSBServ; void *clsJdwp; @@ -42,9 +39,9 @@ private: void ClearInstanceResource(); bool DaemonSessionHandshake(HSession hSession, const uint32_t channelId, uint8_t *payload, int payloadSize); bool CheckVersionMatch(string version); + void TryStopInstance(); bool enableSecure; - bool isStopped; }; } // namespace Hdc #endif \ No newline at end of file diff --git a/src/daemon/daemon_app.cpp b/src/daemon/daemon_app.cpp index 94e680ac298dd9b25907f390283f7400c1610990..39db4cb43ef486363767c37a8988f6b328433a5d 100644 --- a/src/daemon/daemon_app.cpp +++ b/src/daemon/daemon_app.cpp @@ -87,7 +87,7 @@ bool HdcDaemonApp::CommandDispatch(const uint16_t command, uint8_t *payload, con return ret; }; -void HdcDaemonApp::AsyncInstallFinish(bool runOK, const string result) +void HdcDaemonApp::AsyncInstallFinish(bool finish, int64_t exitStatus, const string result) { if (mode == APPMOD_INSTALL) { unlink(ctxNow.localPath.c_str()); @@ -97,10 +97,14 @@ void HdcDaemonApp::AsyncInstallFinish(bool runOK, const string result) echo = Base::ReplaceAll(echo, "\n", " "); vector vecBuf; vecBuf.push_back(mode); - vecBuf.push_back(runOK); + 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 } void HdcDaemonApp::PackageShell(bool installOrUninstall, const char *options, const char *package) @@ -114,7 +118,8 @@ void HdcDaemonApp::PackageShell(bool installOrUninstall, const char *options, co } else { doBuf = Base::StringFormat("bm uninstall %s -n %s", options, package); } - funcAppModFinish = std::bind(&HdcDaemonApp::AsyncInstallFinish, this, std::placeholders::_1, std::placeholders::_2); + funcAppModFinish = std::bind(&HdcDaemonApp::AsyncInstallFinish, this, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3); if (installOrUninstall) { mode = APPMOD_INSTALL; } else { diff --git a/src/daemon/daemon_app.h b/src/daemon/daemon_app.h index 60c22afe2eec7cc1c28d61f5733d749fd1278675..a2df188cdbdd8d90d1f9941e667af3cac286c404 100644 --- a/src/daemon/daemon_app.h +++ b/src/daemon/daemon_app.h @@ -27,7 +27,7 @@ public: private: void WhenTransferFinish(CtxFile *context); void PackageShell(bool installOrUninstall, const char *options, const char *package); - void AsyncInstallFinish(bool runOK, const string result); + void AsyncInstallFinish(bool finish, int64_t exitStatus, const string result); void Sideload(const char *pathOTA); AsyncCmd asyncCommand; diff --git a/src/daemon/daemon_tcp.cpp b/src/daemon/daemon_tcp.cpp index d1031074498cc42a183124079d2b7f406c45e7d5..a757832e2ec91eb7d78e124f043a4483225a0890 100644 --- a/src/daemon/daemon_tcp.cpp +++ b/src/daemon/daemon_tcp.cpp @@ -79,8 +79,7 @@ void HdcDaemonTCP::AcceptClient(uv_stream_t *server, int status) if ((hSession->fdChildWorkTCP = Base::DuplicateUvSocket(&hSession->hWorkTCP)) < 0) { goto Finish; }; - uv_read_stop((uv_stream_t *)&hSession->hWorkTCP); - Base::SetTcpOptions(&hSession->hWorkTCP); + 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) { diff --git a/src/daemon/daemon_unity.cpp b/src/daemon/daemon_unity.cpp index d30b8ecfa665722cde8f32f6af00fe2e6f10eaf8..34b578d1d281abd3afe0a8f29f8d40c73535abe6 100644 --- a/src/daemon/daemon_unity.cpp +++ b/src/daemon/daemon_unity.cpp @@ -19,9 +19,7 @@ namespace Hdc { HdcDaemonUnity::HdcDaemonUnity(HTaskInfo hTaskInfo) : HdcTaskBase(hTaskInfo) { - Base::ZeroStruct(opContext); - opContext.thisClass = this; - opContext.dataCommand = CMD_KERNEL_ECHO_RAW; // Default output to shelldata + currentDataCommand = CMD_KERNEL_ECHO_RAW; // Default output to shelldata } HdcDaemonUnity::~HdcDaemonUnity() @@ -31,118 +29,57 @@ HdcDaemonUnity::~HdcDaemonUnity() void HdcDaemonUnity::StopTask() { - singalStop = true; - ClearContext(&opContext); + asyncCommand.DoRelease(); }; -void HdcDaemonUnity::ClearContext(ContextUnity *ctx) +bool HdcDaemonUnity::ReadyForRelease() { - if (ctx->hasCleared) { - return; - } - switch (ctx->typeUnity) { - case UNITY_SHELL_EXECUTE: { - if (ctx->fpOpen) { - pclose(ctx->fpOpen); - ctx->fpOpen = nullptr; - } - break; - } - default: - break; + if (!HdcTaskBase::ReadyForRelease() || !asyncCommand.ReadyForRelease()) { + return false; } - ctx->hasCleared = true; + return true; } -void HdcDaemonUnity::OnFdRead(uv_fs_t *req) +void HdcDaemonUnity::AsyncCmdOut(bool finish, int64_t exitStatus, const string result) { - CtxUnityIO *ctxIO = static_cast(req->data); - ContextUnity *ctx = static_cast(ctxIO->context); - HdcDaemonUnity *thisClass = ctx->thisClass; - --thisClass->refCount; - uint8_t *buf = ctxIO->bufIO; - bool readContinue = false; - while (true) { - if (thisClass->singalStop || req->result <= 0) { - break; - } - if (!thisClass->SendToAnother(thisClass->opContext.dataCommand, (uint8_t *)buf, req->result)) { +#ifdef UNIT_TEST + Base::WriteBinFile((UT_TMP_PATH + "/execute.result").c_str(), (uint8_t *)result.c_str(), result.size(), + countUt++ == 0); +#endif + bool wantFinish = false; + do { + if (finish) { + wantFinish = true; + --refCount; break; } - if (thisClass->LoopFdRead(&thisClass->opContext) < 0) { + if (!SendToAnother(currentDataCommand, (uint8_t *)result.c_str(), result.size())) { + asyncCommand.DoRelease(); // will callback self, set wantFinish =true break; } - readContinue = true; - break; - } - delete[] buf; - uv_fs_req_cleanup(req); - delete req; - delete ctxIO; - if (!readContinue) { - thisClass->ClearContext(ctx); - thisClass->TaskFinish(); - } -} - -// Consider merage file_descriptor class -int HdcDaemonUnity::LoopFdRead(ContextUnity *ctx) -{ - uv_buf_t iov; - int readMax = Base::GetMaxBufSize(); - CtxUnityIO *contextIO = new CtxUnityIO(); - uint8_t *buf = new uint8_t[readMax](); - uv_fs_t *req = new uv_fs_t(); - if (!contextIO || !buf || !req) { - if (contextIO) { - delete contextIO; - } - if (buf) { - delete[] buf; - } - if (req) { - delete req; - } - WRITE_LOG(LOG_WARN, "Memory alloc failed"); - return -1; + } while (false); + if (wantFinish) { + TaskFinish(); } - contextIO->bufIO = buf; - contextIO->context = ctx; - req->data = contextIO; - ++refCount; - - iov = uv_buf_init((char *)buf, readMax); - uv_fs_read(loopTask, req, ctx->fd, &iov, 1, -1, OnFdRead); - return 0; } int HdcDaemonUnity::ExecuteShell(const char *shellCommand) { - string sUTPath; - if ((opContext.fpOpen = popen(shellCommand, "r")) == nullptr) { - goto FAILED; - } - opContext.fd = fileno(opContext.fpOpen); - opContext.typeUnity = UNITY_SHELL_EXECUTE; - while (true) { -#ifdef UNIT_TEST // UV_FS_READ can not respond to read file content in time when the unit test - uint8_t readBuf[BUF_SIZE_DEFAULT] = ""; - int bytesIO = 0; - bytesIO = fread(readBuf, 1, BUF_SIZE_DEFAULT, opContext.fpOpen); - if (bytesIO <= 0 || !SendToAnother(opContext.dataCommand, readBuf, bytesIO)) { - break; - } - Base::WriteBinFile((UT_TMP_PATH + "/execute.result").c_str(), readBuf, bytesIO, false); -#else - if (LoopFdRead(&opContext) < 0) { + 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; } - return 0; -#endif - } -FAILED: + asyncCommand.ExecuteCommand(shellCommand); + ++refCount; + return ERR_SUCCESS; + } while (false); + TaskFinish(); - WRITE_LOG(LOG_DEBUG, "Shell finish"); + WRITE_LOG(LOG_DEBUG, "Shell failed finish"); return -1; } @@ -258,7 +195,7 @@ bool HdcDaemonUnity::SetDeviceRunMode(void *daemonIn, const char *cmd) return false; } // shutdown - daemon->StopDaemon(true); + daemon->PostStopInstanceMessage(true); LogMsg(MSG_OK, "Set device run mode successful."); return true; } @@ -317,19 +254,20 @@ bool HdcDaemonUnity::CommandDispatch(const uint16_t command, uint8_t *payload, c } case CMD_UNITY_ROOTRUN: { ret = false; - if (payload && !strcmp((char *)payload, "r")) { + if (payloadSize != 0 && !strcmp((char *)payload, "r")) { Base::SetHdcProperty("persist.hdc.root", "0"); + } else { + Base::SetHdcProperty("persist.hdc.root", "1"); } - Base::SetHdcProperty("persist.hdc.root", "1"); - daemon->StopDaemon(true); + daemon->PostStopInstanceMessage(true); break; } case CMD_UNITY_TERMINATE: { - daemon->StopDaemon(!strcmp((char *)payload, "1")); + daemon->PostStopInstanceMessage(!strcmp((char *)payload, "1")); break; } case CMD_UNITY_BUGREPORT_INIT: { - opContext.dataCommand = CMD_UNITY_BUGREPORT_DATA; + currentDataCommand = CMD_UNITY_BUGREPORT_DATA; ExecuteShell((char *)CMDSTR_BUGREPORT.c_str()); break; } diff --git a/src/daemon/daemon_unity.h b/src/daemon/daemon_unity.h index 25298bdfeefe558a7882801e214f892cd212da4e..d95ed18313ea21920b8beea55a7c85fca8be203e 100644 --- a/src/daemon/daemon_unity.h +++ b/src/daemon/daemon_unity.h @@ -23,27 +23,11 @@ public: virtual ~HdcDaemonUnity(); bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize); void StopTask(); + bool ReadyForRelease(); private: - enum UNITY_TYPE { - UNITY_SHELL_EXECUTE = 1, - }; - struct ContextUnity { - bool hasCleared; - uint16_t dataCommand; - HdcDaemonUnity *thisClass; - uint8_t typeUnity; - FILE *fpOpen; - int fd; - }; - struct CtxUnityIO { - uint8_t *bufIO; - ContextUnity *context; - }; static void OnFdRead(uv_fs_t *req); int ExecuteShell(const char *shellCommand); - int LoopFdRead(ContextUnity *ctx); - void ClearContext(ContextUnity *ctx); bool FindMountDeviceByPath(const char *toQuery, char *dev); bool RemountPartition(const char *dir); bool RemountDevice(); @@ -51,9 +35,14 @@ private: bool SetDeviceRunMode(void *daemonIn, const char *cmd); bool GetHiLog(const char *cmd); bool ListJdwpProcess(void *daemonIn); + void AsyncCmdOut(bool finish, int64_t exitStatus, const string result); - ContextUnity opContext; 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/src/daemon/daemon_usb.cpp b/src/daemon/daemon_usb.cpp index 71d0d36a53e4d1ea453d35173f06e370ea3a692a..b32a8b7207082d37121ad44e03633fb7c3719448 100644 --- a/src/daemon/daemon_usb.cpp +++ b/src/daemon/daemon_usb.cpp @@ -78,7 +78,7 @@ int HdcDaemonUSB::ConnectEPPoint(HUSB hUSB) break; } if (write(controlEp, &USB_FFS_DESC, sizeof(USB_FFS_DESC)) < 0) { - WRITE_LOG(LOG_WARN, "%s: write ffs_descriptors failed: errno=%d", USB_FFS_HDC_EP0, errno); + WRITE_LOG(LOG_WARN, "%s: write ffs configs failed: errno=%d", USB_FFS_HDC_EP0, errno); break; } if (write(controlEp, &USB_FFS_VALUE, sizeof(USB_FFS_VALUE)) < 0) { @@ -148,7 +148,7 @@ bool HdcDaemonUSB::AvailablePacket(uint8_t *ioBuf, uint32_t *sessionId) if ((usbPayloadHeader->option & USB_OPTION_RESET)) { HdcDaemon *daemon = reinterpret_cast(clsMainBase); // The Host end program is restarted, but the USB cable is still connected - WRITE_LOG(LOG_WARN, "Hostside want restart daemon, restart old sessionid:%d", usbPayloadHeader->sessionId); + WRITE_LOG(LOG_WARN, "Hostside want restart daemon, restart old sessionId:%u", usbPayloadHeader->sessionId); daemon->PushAsyncMessage(usbPayloadHeader->sessionId, ASYNC_FREE_SESSION, nullptr, 0); break; } @@ -271,7 +271,7 @@ HSession HdcDaemonUSB::PrepareNewSession(uint32_t sessionId, uint8_t *pRecvBuf, 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:%d", currentSessionId); + 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); diff --git a/src/daemon/jdwp.cpp b/src/daemon/jdwp.cpp index 35c8beec7f8463bc41a14b453f3a62724d26002b..2ea6557a373376ce747c220f3e892d99e0a05047 100644 --- a/src/daemon/jdwp.cpp +++ b/src/daemon/jdwp.cpp @@ -14,12 +14,12 @@ */ #include "jdwp.h" -// https://blog.csdn.net/cigogo/article/details/87453793 namespace Hdc { HdcJdwp::HdcJdwp(uv_loop_t *loopIn) { - loop = loopIn; + Base::ZeroStruct(listenPipe); listenPipe.data = this; + loop = loopIn; refCount = 0; uv_rwlock_init(&lockMapContext); } @@ -303,7 +303,9 @@ string HdcJdwp::GetProcessList() // jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8000 int HdcJdwp::Initial() { - JdwpListen(); - return 0; + if (!JdwpListen()) { + return ERR_MODULE_JDWP_FAILED; + } + return ERR_SUCCESS; } } \ No newline at end of file diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp index 61ee8b5269da05bb1c284ac0ff79b1460df8bdc9..2e0b5faf9711f10b6ea86b27f59b9c16ac2dc442 100644 --- a/src/daemon/main.cpp +++ b/src/daemon/main.cpp @@ -17,8 +17,8 @@ using namespace Hdc; static bool g_enableUsb = false; static bool g_enableTcp = false; +static bool g_rootRun = false; static bool g_backgroundRun = false; -static bool g_root = false; namespace Hdc { bool RestartDaemon(bool forkchild) { @@ -31,15 +31,11 @@ bool RestartDaemon(bool forkchild) bool ForkChildCheck(int argc, const char *argv[]) { - // set servicelog - Base::SetLogLevel(4); // debug log print // hdcd #service start forground // hdcd -b #service start backgroundRun // hdcd -fork #fork char modeSet[BUF_SIZE_TINY] = ""; - char droprootSet[BUF_SIZE_TINY] = ""; Base::GetHdcProperty("persist.hdc.mode", modeSet, BUF_SIZE_TINY); - Base::GetHdcProperty("persist.hdc.root", droprootSet, BUF_SIZE_TINY); Base::PrintMessage("Background mode, persist.hdc.mode:%s", modeSet); if (!strcmp(modeSet, "tcp")) { WRITE_LOG(LOG_DEBUG, "Property enable TCP"); @@ -55,15 +51,6 @@ bool ForkChildCheck(int argc, const char *argv[]) WRITE_LOG(LOG_DEBUG, "Default USB mode"); g_enableUsb = true; } - droprootSet[sizeof(droprootSet) - 1] = '\0'; - if (!strcmp(droprootSet, "1")) { - g_root = true; - WRITE_LOG(LOG_DEBUG, "Root run"); - } else if (!strcmp(droprootSet, "0")) { - // Interface for pm am, harmony system has not been implemented, not to achieve - // Running is reduced by ROOT permission to run - // setgid(USER_GID) setuid(USER_UID) - } if (argc == 2) { if (!strcmp(argv[1], "-forkchild")) { g_backgroundRun = false; // forkchild,Forced foreground @@ -143,6 +130,21 @@ bool GetDaemonCommandlineOptions(int argc, const char *argv[]) } return true; } + +void NeedDropPriv() +{ + char droprootSet[BUF_SIZE_TINY] = ""; + Base::GetHdcProperty("persist.hdc.root", droprootSet, BUF_SIZE_TINY); + droprootSet[sizeof(droprootSet) - 1] = '\0'; + if (!strcmp(droprootSet, "1")) { + setuid(0); + g_rootRun = true; + WRITE_LOG(LOG_DEBUG, "Root run"); + } else if (!strcmp(droprootSet, "0")) { + setuid(AID_SHELL); + // if need, will be more priv. operate + } +} } // namespace Hdc #ifndef UNIT_TEST @@ -172,6 +174,7 @@ int main(int argc, const char *argv[]) if (g_backgroundRun) { return BackgroundRun(); } + NeedDropPriv(); WRITE_LOG(LOG_DEBUG, "HdcDaemon main run"); HdcDaemon daemon(false); daemon.InitMod(g_enableTcp, g_enableUsb); @@ -179,8 +182,9 @@ int main(int argc, const char *argv[]) bool wantRestart = daemon.WantRestart(); WRITE_LOG(LOG_DEBUG, "Daemon finish"); // There is no daemon, we can only restart myself. - if (g_root || wantRestart) { - daemon.StopInstance(); + 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; diff --git a/src/daemon/shell.cpp b/src/daemon/shell.cpp index 6a677aa44fc1cfa2d31e1424fed647c8eec975d8..f19aa480410fc624f24ed87271dafc719a20f542 100644 --- a/src/daemon/shell.cpp +++ b/src/daemon/shell.cpp @@ -126,7 +126,6 @@ int HdcShell::CreateSubProcessPTY(const char *cmd, const char *arg0, const char close(ptm); return -3; } - *pid = fork(); if (*pid < 0) { WRITE_LOG(LOG_DEBUG, "Fork shell failed:%s", strerror(errno)); @@ -159,11 +158,6 @@ bool HdcShell::ChildReadCallback(const void *context, uint8_t *buf, const int si if (!thisClass->SendToAnother(CMD_KERNEL_ECHO_RAW, (uint8_t *)buf, size)) { thisClass->TaskFinish(); } -#ifdef UNIT_TEST - // just read little data - Base::WriteBinFile((UT_TMP_PATH + "/shell.result").c_str(), (uint8_t *)buf, size, false); - thisClass->TaskFinish(); -#endif return true; }; diff --git a/src/daemon/usb_ffs.h b/src/daemon/usb_ffs.h index 2e3a26bd8e2ae490d5cc96d4673fd5d4109ddc13..d3909cda77679fc3b6cef2a5a38d76ca12a9f0d1 100644 --- a/src/daemon/usb_ffs.h +++ b/src/daemon/usb_ffs.h @@ -28,6 +28,7 @@ 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_HDC_EP0 = "/dev/usb-ffs/hdc/ep0"; constexpr auto USB_FFS_HDC_OUT = "/dev/usb-ffs/hdc/ep1"; constexpr auto USB_FFS_HDC_IN = "/dev/usb-ffs/hdc/ep2"; @@ -99,7 +100,7 @@ static struct UsbFuncConfig config3 = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = 1 | USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = HDC_FSPKT_SIZE_MAX, + .wMaxPacketSize = HDC_SSPKT_SIZE_MAX, }, .pairFrom = { .bLength = sizeof(config3.pairFrom), @@ -111,7 +112,7 @@ static struct UsbFuncConfig config3 = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = 2 | USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = HDC_FSPKT_SIZE_MAX, + .wMaxPacketSize = HDC_SSPKT_SIZE_MAX, }, .pairTo = { .bLength = sizeof(config3.pairTo), diff --git a/src/host/host_usb.cpp b/src/host/host_usb.cpp index bb8aa7aaa7837067a8ba47cd2bace823f5faca97..7420a3dd60c5fbf5c022f8f276009073cd8295c1 100644 --- a/src/host/host_usb.cpp +++ b/src/host/host_usb.cpp @@ -406,6 +406,7 @@ void LIBUSB_CALL HdcHostUSB::WriteUSBBulkCallback(struct libusb_transfer *transf --hSession->sendRef; } uv_sem_post(&thisClass->semUsbSend); + 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) { @@ -417,7 +418,27 @@ void LIBUSB_CALL HdcHostUSB::WriteUSBBulkCallback(struct libusb_transfer *transf libusb_free_transfer(transfer); } +bool HdcHostUSB::WaitMaxOverlap(HSession hSession) +{ + int result = 0; + bool ret = false; + while (true) { + result = uv_sem_trywait(&semUsbSend); + if (result == 0) { + ret = true; + break; + } else if (result == UV_EAGAIN && !hSession->isDead) { + uv_sleep(3); // at least sleep 3ms to Hand over CPU for IO + continue; + } else { + break; + } + } + return ret; +} + // 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; @@ -437,7 +458,10 @@ int HdcHostUSB::SendUSBRaw(HSession hSession, uint8_t *data, const int length) } libusb_fill_bulk_transfer(transferUsb, hUSB->devHandle, hUSB->epHost, sendBuf, length, WriteUSBBulkCallback, hSession, retryTimeout); - uv_sem_wait(&semUsbSend); + if (!WaitMaxOverlap(hSession)) { + ret = ERR_THREAD_MUTEX_FAIL; + break; + } if (libusb_submit_transfer(transferUsb) < 0) { uv_sem_post(&semUsbSend); ret = ERR_IO_FAIL; diff --git a/src/host/host_usb.h b/src/host/host_usb.h index f564870b792016be0f65e6e6145b695cddf9029c..d2e43516b130646d6094078a6fc8cf6aa7f17850 100644 --- a/src/host/host_usb.h +++ b/src/host/host_usb.h @@ -52,6 +52,7 @@ private: bool DetectMyNeed(libusb_device *device, string &sn); void SendUsbReset(HUSB hUSB, uint32_t sessionId); void RestoreHdcProtocol(HUSB hUsb, const uint8_t *buf, int bufSize); + bool WaitMaxOverlap(HSession hSession); uv_idle_t usbWork; libusb_context *ctxUSB; diff --git a/src/host/main.cpp b/src/host/main.cpp index f9966b302d6658a51b2f480697e3b59811a36839..3720718120df8337d88dfa54d6bf3d2f54c03e36 100644 --- a/src/host/main.cpp +++ b/src/host/main.cpp @@ -16,7 +16,7 @@ #include "server_for_client.h" #ifndef HARMONY_PROJECT -#include "../test/hdc_runtime_command.h" +#include "../test/ut_command.h" using namespace HdcTest; #endif diff --git a/src/host/server.cpp b/src/host/server.cpp index e9e967a3f9f61e6dc64512389ca0f453fc347843..4795c3aaf662fa586a6dfd550d64bb92142df338 100644 --- a/src/host/server.cpp +++ b/src/host/server.cpp @@ -34,7 +34,7 @@ HdcServer::~HdcServer() void HdcServer::ClearInstanceResource() { - StopInstance(); + TryStopInstance(); Base::TryCloseLoop(&loopMain, "HdcServer::~HdcServer"); if (clsTCPClt) { delete clsTCPClt; @@ -47,7 +47,7 @@ void HdcServer::ClearInstanceResource() } } -void HdcServer::StopInstance() +void HdcServer::TryStopInstance() { ClearSessions(); if (clsTCPClt) { @@ -56,7 +56,9 @@ void HdcServer::StopInstance() if (clsUSBClt) { clsUSBClt->Stop(); } - ((HdcServerForClient *)clsServerForClient)->Stop(); + if (clsServerForClient) { + ((HdcServerForClient *)clsServerForClient)->Stop(); + } ReMainLoopForInstanceClear(); ClearMapDaemonInfo(); } diff --git a/src/host/server.h b/src/host/server.h index 47911530f0ca2811d20359e4c4026013bbcee751..7bbcd04e55fae3e23ed05af0d34c7b001a5b2b91 100644 --- a/src/host/server.h +++ b/src/host/server.h @@ -29,7 +29,6 @@ public: bool Initial(const char *listenString); void AttachChannel(HSession hSession, const uint32_t channelId); void DeatchChannel(const uint32_t channelId); - void StopInstance(); static bool CheckToPullUptrServer(const char *listenString); static void UsbPreConnect(uv_timer_t *handle); void NotifyInstanceSessionFree(HSession hSession, bool freeOrClear); @@ -53,6 +52,7 @@ private: string GetDaemonMapList(uint8_t opType); bool ServerSessionHandshake(HSession hSession, uint8_t *payload, int payloadSize); void GetDaemonMapOnlyOne(HDaemonInfo &hDaemonInfoInOut); + void TryStopInstance(); uv_rwlock_t daemonAdmin; map mapDaemon; diff --git a/src/host/server_for_client.cpp b/src/host/server_for_client.cpp index ba30b964aa21a608742046abe7e6a7b95b5e6f8f..a5185af29e63f6ac2f0eef5ffd3791dabde28b71 100644 --- a/src/host/server_for_client.cpp +++ b/src/host/server_for_client.cpp @@ -172,7 +172,8 @@ void HdcServerForClient::OrderFindTargets(HChannel hChannel) 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.result").c_str(), (uint8_t *)bufString.c_str(), bufString.size(), false); + Base::WriteBinFile((UT_TMP_PATH + "/base-discover.result").c_str(), (uint8_t *)bufString.c_str(), bufString.size(), + true); #endif } @@ -287,7 +288,8 @@ void HdcServerForClient::GetTargetList(HChannel hChannel, void *formatCommandInp } EchoClient(hChannel, MSG_OK, (char *)sRet.c_str()); #ifdef UNIT_TEST - Base::WriteBinFile((UT_TMP_PATH + "/base.result").c_str(), (uint8_t *)sRet.c_str(), sRet.size(), false); + Base::WriteBinFile((UT_TMP_PATH + "/base-list.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(), + MESSAGE_SUCCESS.size(), true); #endif } @@ -304,7 +306,8 @@ bool HdcServerForClient::GetAnyTarget(HChannel hChannel) string connectKey = hdi->connectKey; bool ret = NewConnectTry(ptrServer, hChannel, connectKey); #ifdef UNIT_TEST - Base::WriteBinFile((UT_TMP_PATH + "/base.result").c_str(), (uint8_t *)"OK", 3, false); + Base::WriteBinFile((UT_TMP_PATH + "/base-any.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(), + MESSAGE_SUCCESS.size(), true); #endif return ret; } diff --git a/src/host/translate.cpp b/src/host/translate.cpp index 343b0e7b7fc482a7884c80b55cfb798c5f842a89..195cafc7ed67089abab5a9ad42fba3431fd8e529 100644 --- a/src/host/translate.cpp +++ b/src/host/translate.cpp @@ -66,8 +66,8 @@ namespace TranslateCommand { " localabstract:\n" " dev:\n" " jdwp: (remote only)\n" - " fport|rport ls - Dispaly forward/reverse tasks\n" - " fport|rport rm taskstr - Remove forward/reverse task by taskstring\n" + " fport ls - Dispaly forward/reverse tasks\n" + " fport rm taskstr - Remove forward/reverse task by taskstring\n" "\n" "app commands:\n" " install [-rdg] src - Send package(s) to device and install them\n" @@ -209,7 +209,6 @@ namespace TranslateCommand { } else if (!strncmp(input, (CMDSTR_SHELL + " ").c_str(), CMDSTR_SHELL.size() + 1)) { outCmd->cmdFlag = CMD_UNITY_EXECUTE; outCmd->paraments = input + CMDSTR_SHELL.size() + 1; - outCmd->paraments += " 2>&1"; } else if (!strcmp(input, CMDSTR_SHELL.c_str())) { outCmd->cmdFlag = CMD_SHELL_INIT; } else if (!strncmp(input, CMDSTR_FILE_SEND.c_str(), CMDSTR_FILE_SEND.size()) diff --git a/src/test/main.cpp b/src/test/main.cpp index d23f258cd6a731bdadf83349def82448d5afecce..873fe0a83b9de72dafa23a6450b8623fe4ff2a6d 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -12,20 +12,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "hdc_runtime_command.h" -#include "hdc_runtime_frame.h" #include "ut_common.h" using namespace Hdc; namespace HdcTest { -// Base module test + TEST(HdcBaseFunction, HandleNoneZeroInput) { char bufString[256] = ""; uint16_t num; int argc = 0; - char **argv = nullptr; - GTEST_ASSERT_LE(1, Base::GetRuntimeMSec()); GTEST_ASSERT_LE(10, Base::GetRandomNum(10, 12)); GTEST_ASSERT_EQ(0, Base::ConnectKey2IPPort("127.0.0.1:8080", bufString, &num)); @@ -34,60 +30,59 @@ TEST(HdcBaseFunction, HandleNoneZeroInput) GTEST_ASSERT_EQ(4, argc); } -// Task-shell +TEST(HdcBaseCommand, HandleNoneZeroInput) +{ + Runtime *ftest = new Runtime(); + GTEST_ASSERT_EQ(true, ftest->Initial(false)); + GTEST_ASSERT_EQ(true, ftest->CheckEntry(ftest->UT_MOD_BASE)); + delete ftest; +} + TEST(HdcShellMod, HandleNoneZeroInput) { - FrameRuntime *ftest = new FrameRuntime(); + Runtime *ftest = new Runtime(); GTEST_ASSERT_EQ(true, ftest->Initial(true)); GTEST_ASSERT_EQ(true, ftest->CheckEntry(ftest->UT_MOD_SHELL)); delete ftest; - - // Add interactive shell cases if ready } -// Basic support command test -TEST(HdcBaseCommand, HandleNoneZeroInput) +TEST(HdcFileCommand, HandleNoneZeroInput) { - FrameRuntime *ftest = new FrameRuntime(); - GTEST_ASSERT_EQ(true, ftest->Initial(false)); - GTEST_ASSERT_EQ(true, ftest->CheckEntry(ftest->UT_MOD_BASE)); + Runtime *ftest = new Runtime(); + GTEST_ASSERT_EQ(true, ftest->Initial(true)); + GTEST_ASSERT_EQ(true, ftest->CheckEntry(ftest->UT_MOD_FILE)); delete ftest; } -// File Transfer Command Test -TEST(HdcFileCommand, HandleNoneZeroInput) +TEST(HdcForwardCommand, HandleNoneZeroInput) { - FrameRuntime *ftest = new FrameRuntime(); + Runtime *ftest = new Runtime(); GTEST_ASSERT_EQ(true, ftest->Initial(true)); - GTEST_ASSERT_EQ(true, ftest->CheckEntry(ftest->UT_MOD_FILE)); + GTEST_ASSERT_EQ(true, ftest->CheckEntry(ftest->UT_MOD_FORWARD)); delete ftest; } -// Task-shellFunction point test -TEST(HdcShellMod_Test, HandleNoneZeroInput) +TEST(AppCommand, HandleNoneZeroInput) { - WRITE_LOG(LOG_INFO, "Begincheck Shell execute"); - FrameRuntime *ftest = new FrameRuntime(); + Runtime *ftest = new Runtime(); GTEST_ASSERT_EQ(true, ftest->Initial(true)); - GTEST_ASSERT_EQ(true, ftest->CheckEntry(ftest->UT_MOD_SHELL)); + GTEST_ASSERT_EQ(true, ftest->CheckEntry(ftest->UT_MOD_APP)); delete ftest; } + } // namespace HdcTest int main(int argc, const char *argv[]) { -#ifdef DEBUG_PROTOCOL - HdcTest::DdmCallCommandEntry(argc, argv); - return 0; -#endif int ret = 0; // many feature under Win32 UT is not supported, so we cannot support it when unit test #ifdef _WIN32 - printf("Not support platform\r\n"); + printf("Unit test not support win32 platform\r\n"); return 0; -#endif +#else testing::InitGoogleTest(&argc, (char **)argv); ret = RUN_ALL_TESTS(); WRITE_LOG(LOG_INFO, "Test all finish"); +#endif return ret; } \ No newline at end of file diff --git a/src/test/hdc_runtime_command.cpp b/src/test/ut_command.cpp similarity index 90% rename from src/test/hdc_runtime_command.cpp rename to src/test/ut_command.cpp index f9368299c7d51176e387e32116ef2ff19dc05ad7..24b6b0ed5ba816b7459c81fc2e2bb21dad30858d 100644 --- a/src/test/hdc_runtime_command.cpp +++ b/src/test/ut_command.cpp @@ -12,9 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "hdc_runtime_command.h" +#include "ut_command.h" using namespace Hdc; -using Hdc::Base::RunPipeComand; namespace HdcTest { void *TestBackgroundServerForClient(void *param) @@ -46,7 +45,6 @@ void PreConnectDaemon(const string &debugServerPort, const string &debugConnectK int TestRuntimeCommandSimple(bool bTCPorUSB, int method, bool bNeedConnectDaemon) { - unlink("/mnt/hgfs/vtmp/my.txt"); // These two parameters are tested, not much change, manually modify by myself string debugServerPort; string debugConnectKey; @@ -67,6 +65,7 @@ int TestRuntimeCommandSimple(bool bTCPorUSB, int method, bool bNeedConnectDaemon int TestTaskCommand(int method, const string &debugServerPort, const string &debugConnectKey) { WRITE_LOG(LOG_DEBUG, "------------Operate command------------"); + string bufString; switch (method) { case UT_SHELL_BASIC: // Basic order test TestRunClient(debugServerPort, debugConnectKey, "shell id"); @@ -81,17 +80,12 @@ int TestTaskCommand(int method, const string &debugServerPort, const string &deb TestRunClient(debugServerPort, debugConnectKey, CMDSTR_SHELL.c_str()); break; case UT_FILE_SEND: { // send files -#ifdef UNIT_TEST - string bufString - = Base::StringFormat("file send %s/file.send %s/file.recv", UT_TMP_PATH.c_str(), UT_TMP_PATH.c_str()); + bufString = Base::StringFormat("file send %s/file.local %s/file.remote", UT_TMP_PATH.c_str(), + UT_TMP_PATH.c_str()); TestRunClient(debugServerPort, debugConnectKey, bufString); -#else - TestRunClient(debugServerPort, debugConnectKey, - "file send /mnt/hgfs/vtmp/f.txt /mnt/hgfs/vtmp/f2.txt -z 1"); -#endif break; } - case UT_FILE_RECV: // send files + case UT_FILE_RECV: // recv files TestRunClient(debugServerPort, debugConnectKey, "file recv /mnt/hgfs/vtmp/f.txt /mnt/hgfs/vtmp/f2.txt -z 1"); break; @@ -108,8 +102,8 @@ int TestTaskCommand(int method, const string &debugServerPort, const string &deb TestRunClient(debugServerPort, debugConnectKey, "fport tcp:8081 jdwp:1234"); break; case UT_APP_INSTALL: // Single and multiple and multiple paths support - TestRunClient(debugServerPort, debugConnectKey, - "install /d/a.hap /mnt/hgfs/vtmp/b.hap /mnt/hgfs/vtmp -lrtsdpg"); // hap + bufString = Base::StringFormat("install %s/app.hap", UT_TMP_PATH.c_str()); + TestRunClient(debugServerPort, debugConnectKey, bufString); break; case UT_TEST_TMP: TestRunClient(debugServerPort, debugConnectKey, "shell pwd"); @@ -137,7 +131,7 @@ int TestTaskCommand(int method, const string &debugServerPort, const string &deb default: break; } - WRITE_LOG(LOG_DEBUG, "!!!!!!!!!Client finish"); + WRITE_LOG(LOG_DEBUG, "!!!Client finish"); return 0; } diff --git a/src/test/hdc_runtime_command.h b/src/test/ut_command.h similarity index 95% rename from src/test/hdc_runtime_command.h rename to src/test/ut_command.h index ece9a36db0a42dbcf598701280ee9418b92e00df..d8c7aa4dcd568d772aecb32a1ccea7b25f17e110 100644 --- a/src/test/hdc_runtime_command.h +++ b/src/test/ut_command.h @@ -12,12 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef HDC_RUNTIME_COMMAND_H -#define HDC_RUNTIME_COMMAND_H +#ifndef HDC_UT_COMMAND_H +#define HDC_UT_COMMAND_H #include "ut_common.h" namespace HdcTest { -enum UTType { +enum UtType { UT_HELP, UT_DISCOVER, UT_LIST_TARGETS, @@ -35,7 +35,6 @@ enum UTType { UT_FORWARD_TCP2DEV, UT_FORWARD_TCP2JDWP, UT_APP_INSTALL, - UT_TEST_TMP, }; diff --git a/src/test/ut_common.h b/src/test/ut_common.h index 459cc2f3109ecb2e41a07e9a47c66c3ea3f73236..4195f39c49ac1842e0d4a0489300379acca2213d 100644 --- a/src/test/ut_common.h +++ b/src/test/ut_common.h @@ -24,14 +24,12 @@ using Hdc::HdcServer; #ifndef _WIN32 #include #endif +#include #include #include -namespace HdcTest { -#ifndef _WIN32 - -bool TestShellExecute(); -#endif -} // namespace HdcTest +#include "ut_command.h" +#include "ut_mod.h" +#include "ut_runtime.h" #endif // end HDC_UT_COMMON_H diff --git a/src/test/ut_mod.cpp b/src/test/ut_mod.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0da1cbfd5407590e36b6cb84e8ab75e5b0d84e6e --- /dev/null +++ b/src/test/ut_mod.cpp @@ -0,0 +1,288 @@ +/* + * 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 "ut_mod.h" +using namespace Hdc; + +namespace HdcTest { +bool TestBaseCommand(void *runtimePtr) +{ + Runtime *rt = (Runtime *)runtimePtr; + uint8_t *bufPtr = nullptr; + int bytesIO = 0; + bool ret = false; + // test 'discover' + rt->InnerCall(UT_DISCOVER); + if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/base-discover.result").c_str(), (void **)&bufPtr, 0)) < 0) { + return false; + } + if (!strcmp("0", (char *)bufPtr)) { + delete[] bufPtr; + bufPtr = nullptr; + return false; + } + delete[] bufPtr; + bufPtr = nullptr; + // test 'targets' + rt->InnerCall(UT_LIST_TARGETS); + constexpr int expert = 5; + if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/base-list.result").c_str(), (void **)&bufPtr, 0)) < expert) { + goto Finish; + } + if (strcmp(MESSAGE_SUCCESS.c_str(), (char *)bufPtr)) { + goto Finish; + } + delete[] bufPtr; + bufPtr = nullptr; + // test 'any' + rt->InnerCall(UT_CONNECT_ANY); + if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/base-any.result").c_str(), (void **)&bufPtr, 0)) < 0) { + goto Finish; + } + if (strcmp(MESSAGE_SUCCESS.c_str(), (char *)bufPtr)) { + goto Finish; + } + // all pass + ret = true; + +Finish: + if (bufPtr) { + delete[] bufPtr; + bufPtr = nullptr; + } + return ret; +} + +bool TestShellExecute(void *runtimePtr) +{ + Runtime *rt = (Runtime *)runtimePtr; + uint8_t *bufPtr = nullptr; + int bytesIO = 0; + bool ret = false; + char bufString[BUF_SIZE_DEFAULT4] = ""; + string resultFile = "execute.result"; + while (true) { + // test1 + rt->InnerCall(UT_SHELL_BASIC); + if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/" + resultFile).c_str(), (void **)&bufPtr, 0)) < 10) { + break; + } + Base::RunPipeComand((const char *)"id", bufString, sizeof(bufString), false); + if (strcmp(bufString, (char *)bufPtr)) { + break; + } + delete[] bufPtr; + bufPtr = nullptr; + + // test 2 + rt->ResetUtTmpFile(resultFile); + rt->InnerCall(UT_SHELL_LIGHT); + constexpr int expert = 10; + if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/" + resultFile).c_str(), (void **)&bufPtr, 0)) < expert) { + break; + } + Base::RunPipeComand((const char *)"cat /etc/passwd", bufString, sizeof(bufString), false); + if (strcmp(bufString, (char *)bufPtr)) { + break; + } + delete[] bufPtr; + bufPtr = nullptr; + + // all pass + ret = true; + break; + } + if (bufPtr) { + delete[] bufPtr; + } + return ret; +} + +// file send like recv in our code, so just test send is enough +bool TestFileCommand(void *runtimePtr) +{ + Runtime *rt = (Runtime *)runtimePtr; + bool ret = false; + char bufString[BUF_SIZE_DEFAULT] = ""; + uint8_t *bufLocal = nullptr; + uint8_t *bufRemote = nullptr; + int sizeLocal = 0; + int sizeRemote = 0; + string localFile = Base::StringFormat("%s/file.local", UT_TMP_PATH.c_str()); + string remoteFile = Base::StringFormat("%s/file.remote", UT_TMP_PATH.c_str()); + do { + // to be use random buf, not bash result + string cmd = Base::StringFormat("find /usr > %s", localFile.c_str()); + Base::RunPipeComand(cmd.c_str(), bufString, sizeof(bufString), false); + rt->InnerCall(UT_FILE_SEND); + if ((sizeLocal = Base::ReadBinFile(localFile.c_str(), (void **)&bufLocal, 0)) < 0) { + break; + }; + if ((sizeRemote = Base::ReadBinFile(remoteFile.c_str(), (void **)&bufRemote, 0)) < 0) { + break; + }; + auto localHash = Base::Md5Sum(bufLocal, sizeLocal); + auto remoteHash = Base::Md5Sum(bufRemote, sizeRemote); + if (memcmp(localHash.data(), remoteHash.data(), localHash.size())) { + break; + } + ret = true; + } while (false); + + if (bufLocal) { + delete[] bufLocal; + } + if (bufRemote) { + delete[] bufRemote; + } + return ret; +} + +void UtForwardWaiter(uv_loop_t *loop, uv_tcp_t *server) +{ + auto funcOnNewConn = [](uv_stream_t *server, int status) -> void { + auto funcOnRead = [](uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) -> void { + if (nread > 0 && !strcmp(buf->base, MESSAGE_SUCCESS.c_str())) { + Base::WriteBinFile((UT_TMP_PATH + "/forward.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(), + MESSAGE_SUCCESS.size(), true); + } + uv_close((uv_handle_t *)client, [](uv_handle_t *handle) { free(handle); }); + free(buf->base); + }; + if (status < 0) { + return; + } + uv_tcp_t *client = new uv_tcp_t(); + uv_tcp_init(server->loop, client); + if (uv_accept(server, (uv_stream_t *)client) == 0) { + uv_read_start((uv_stream_t *)client, + [](uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) { + buf->base = new char[suggested_size](); + buf->len = suggested_size; + }, + funcOnRead); + } else { + uv_close((uv_handle_t *)client, [](uv_handle_t *handle) { free(handle); }); + } + }; + const int utForwardTargetPort = 8082; + struct sockaddr_in addr; + if (uv_tcp_init(loop, server) || uv_ip4_addr("127.0.0.1", utForwardTargetPort, &addr)) { + return; + } + if (uv_tcp_bind(server, (const struct sockaddr *)&addr, 0) || uv_listen((uv_stream_t *)server, 5, funcOnNewConn)) { + return; + } + WRITE_LOG(LOG_DEBUG, "UtForwardWaiter listen on port:%d", utForwardTargetPort); +} + +bool UtForwardConnect(uv_loop_t *loop, uv_tcp_t *client, uv_tcp_t *server) +{ + auto funcConn = [](uv_connect_t *req, int status) -> void { + uv_tcp_t *server = (uv_tcp_t *)req->data; + delete req; + if (status < 0) { + return; + } + Base::SendToStream((uv_stream_t *)req->handle, (uint8_t *)MESSAGE_SUCCESS.c_str(), MESSAGE_SUCCESS.size()); + Base::DelayDoSimple(req->handle->loop, 3000, [=](const uint8_t flag, string &msg, const void *p) { + uv_close((uv_handle_t *)server, nullptr); // notify UtForwardWaiter stop + }); + }; + + const int utForwardListenPort = 8081; + struct sockaddr_in addr; + bool ret = false; + uv_connect_t *connReq = new uv_connect_t(); + connReq->data = server; + do { + if (uv_tcp_init(loop, client)) { + break; + } + uv_ip4_addr("127.0.0.1", utForwardListenPort, &addr); + if (uv_tcp_connect(connReq, client, (const struct sockaddr *)&addr, funcConn)) { + break; + } + + ret = true; + } while (false); + return ret; +} + +void TestForwardExternThread(void *arg) +{ + uv_loop_t loop; + uv_tcp_t server; + uv_tcp_t client; + const int clientForwardTimeout = 1000; + bool *clientOK = (bool *)arg; + auto funcDelayCallUtForwardConnect = [&](const uint8_t flag, string &msg, const void *p) -> void { + if (!*clientOK) { + // client create forward timeout + WRITE_LOG(LOG_WARN, "Client forward timeout"); + uv_stop(&loop); + } + UtForwardConnect(&loop, &client, &server); + }; + + uv_loop_init(&loop); + UtForwardWaiter(&loop, &server); + Base::DelayDoSimple(&loop, clientForwardTimeout, funcDelayCallUtForwardConnect); + uv_run(&loop, UV_RUN_DEFAULT); + uv_loop_close(&loop); +}; + +bool TestForwardCommand(void *runtimePtr) +{ + Runtime *rt = (Runtime *)runtimePtr; + uv_thread_t td; + char buf[BUF_SIZE_TINY] = ""; + bool clientOK = false; + int sizeResult = 0; + uv_thread_create(&td, TestForwardExternThread, &clientOK); + rt->InnerCall(UT_FORWARD_TCP2TCP); + clientOK = true; + uv_thread_join(&td); + // all done, we will check result ok + string localFile = Base::StringFormat("%s/forward.result", UT_TMP_PATH.c_str()); + if ((sizeResult = Base::ReadBinFile(localFile.c_str(), (void **)buf, sizeof(buf))) < 0) { + return false; + }; + if (strcmp(buf, MESSAGE_SUCCESS.c_str())) { + return false; + } + return true; +} + +bool TestAppCommand(void *runtimePtr) +{ + Runtime *rt = (Runtime *)runtimePtr; + char bufString[BUF_SIZE_DEFAULT] = ""; + string localFile = Base::StringFormat("%s/app.hap", UT_TMP_PATH.c_str()); + string cmd = Base::StringFormat("id --help > %s", localFile.c_str()); // I know it is a invalid hap file + Base::RunPipeComand(cmd.c_str(), bufString, sizeof(bufString), false); + rt->InnerCall(UT_APP_INSTALL); + + constexpr int expert = 5; + if (Base::ReadBinFile((UT_TMP_PATH + "/appinstall.result").c_str(), (void **)&bufString, sizeof(bufString)) + < expert) { + return false; + } + if (strcmp(MESSAGE_SUCCESS.c_str(), (char *)bufString)) { + return false; + } + return true; +} + +} // namespace HdcTest \ No newline at end of file diff --git a/src/test/ut_mod.h b/src/test/ut_mod.h new file mode 100644 index 0000000000000000000000000000000000000000..4681c7166e0d444c5850d1167d44ca6950cf26c5 --- /dev/null +++ b/src/test/ut_mod.h @@ -0,0 +1,27 @@ +/* + * 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_UT_MOD_H +#define HDC_UT_MOD_H +#include "ut_common.h" + +namespace HdcTest { +bool TestBaseCommand(void *runtimePtr); +bool TestShellExecute(void *runtimePtr); +bool TestFileCommand(void *runtimePtr); +bool TestForwardCommand(void *runtimePtr); +bool TestAppCommand(void *runtimePtr); + +} // namespace HdcTest +#endif // HDC_FUNC_TEST_H \ No newline at end of file diff --git a/src/test/hdc_runtime_frame.cpp b/src/test/ut_runtime.cpp similarity index 35% rename from src/test/hdc_runtime_frame.cpp rename to src/test/ut_runtime.cpp index 44220c8db6dec72712f08c87766d611597c4096e..d7fd8f65a1e7494d9a053986cbb638afa7029d37 100644 --- a/src/test/hdc_runtime_frame.cpp +++ b/src/test/ut_runtime.cpp @@ -12,32 +12,34 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "hdc_runtime_frame.h" -#include "hdc_runtime_command.h" +#include "ut_runtime.h" using namespace Hdc; namespace HdcTest { -FrameRuntime::FrameRuntime() +Runtime::Runtime() { uv_loop_init(&loopMain); - uv_thread_create(&tdServer, StartServer, this); - uv_thread_create(&tdDaemon, StartDaemon, this); - bCheckResult = false; checkFinish = false; hashInitialize = false; - // UintTest Running log level LOG_INFO/LOG_DEBUG + // UintTest Running log level LOG_INFO/LOG_FULL + // Base::SetLogLevel(Hdc::LOG_FULL); // LOG_INFO Base::SetLogLevel(Hdc::LOG_INFO); - ResetTmpFolder(); + // three nodes all run host, at least 5+(reserve:2)=7 threads for use + // client 1 + (server+daemon)= SIZE_THREAD_POOL*2+1 + string threadNum = std::to_string(SIZE_THREAD_POOL * 2); + uv_os_setenv("UV_THREADPOOL_SIZE", threadNum.c_str()); + ResetUtTmpFolder(); + serverRunning = false; daemonRunning = false; }; -FrameRuntime::~FrameRuntime() +Runtime::~Runtime() { constexpr int sleepTime = 500; if (hashInitialize) { - Base::TryCloseLoop(&loopMain, "FrameRuntime childUV"); + Base::TryCloseLoop(&loopMain, "Runtime childUV"); uv_loop_close(&loopMain); } while (serverRunning || daemonRunning) { @@ -45,52 +47,27 @@ FrameRuntime::~FrameRuntime() } }; -bool FrameRuntime::Initial(bool bConnectToDaemon) -{ - // server daemon runing check port listen - // ++todo - constexpr int loopTime = 20; - constexpr int sleepTime = 300; - bool bRunCheckOK = false; - for (size_t i = 0; i < loopTime; ++i) { - if (serverRunning && daemonRunning) { - bRunCheckOK = true; - break; - } - uv_sleep(sleepTime); - } - if (!bRunCheckOK) { - WRITE_LOG(LOG_DEBUG, "Unit server daemon not ready"); - return false; // wait server and daemon ready - } - - if (bConnectToDaemon) { - PreConnectDaemon(DEBUG_ADDRESS.c_str(), DEBUG_TCP_CONNECT_KEY.c_str()); - } - hashInitialize = true; - return true; -} - -inline int FrameRuntime::InnerCall(int method) +int Runtime::InnerCall(int method) { return TestRuntimeCommand(method, DEBUG_ADDRESS.c_str(), DEBUG_TCP_CONNECT_KEY.c_str()); } -void FrameRuntime::CheckStopServer(uv_idle_t *arg) +void Runtime::CheckStopServer(uv_idle_t *arg) { - FrameRuntime *thisClass = (FrameRuntime *)arg->data; + Runtime *thisClass = (Runtime *)arg->data; thisClass->serverRunning = true; if (!thisClass->checkFinish) { return; } - thisClass->server->StopInstance(); + WRITE_LOG(LOG_DEBUG, "Try stop test server"); + thisClass->server->PostStopInstanceMessage(); Base::TryCloseHandle((uv_handle_t *)&thisClass->checkServerStop); } -void FrameRuntime::StartServer(void *arg) +void Runtime::StartServer(uv_work_t *arg) { constexpr int sleepTime = 1000; - FrameRuntime *thisClass = static_cast(arg); + Runtime *thisClass = static_cast(arg->data); uv_sleep(sleepTime); HdcServer server(true); server.Initial(DEFAULT_SERVER_ADDR.c_str()); @@ -103,26 +80,25 @@ void FrameRuntime::StartServer(void *arg) server.WorkerPendding(); WRITE_LOG(LOG_DEBUG, "TestServerForClient free"); - thisClass->serverRunning = false; } -void FrameRuntime::CheckStopDaemon(uv_idle_t *arg) +void Runtime::CheckStopDaemon(uv_idle_t *arg) { - FrameRuntime *thisClass = (FrameRuntime *)arg->data; + Runtime *thisClass = (Runtime *)arg->data; thisClass->daemonRunning = true; if (!thisClass->checkFinish) { return; } - thisClass->daemon->StopInstance(); + WRITE_LOG(LOG_DEBUG, "Try stop test daemon"); + thisClass->daemon->PostStopInstanceMessage(); Base::TryCloseHandle((uv_handle_t *)&thisClass->checkDaemonStop); } -void FrameRuntime::StartDaemon(void *arg) +void Runtime::StartDaemon(uv_work_t *arg) { - FrameRuntime *thisClass = static_cast(arg); + Runtime *thisClass = static_cast(arg->data); HdcDaemon daemon(false); daemon.InitMod(true, false); - thisClass->daemon = &daemon; uv_idle_t *idt = &thisClass->checkDaemonStop; @@ -132,48 +108,91 @@ void FrameRuntime::StartDaemon(void *arg) daemon.WorkerPendding(); WRITE_LOG(LOG_DEBUG, "TestDaemon free"); - thisClass->daemonRunning = false; } -void FrameRuntime::DoCheck(uv_idle_t *handle) +int Runtime::CheckServerDaemonReady() { - FrameRuntime *thisClass = (FrameRuntime *)handle->data; - if (!thisClass->hashInitialize) { - WRITE_LOG(LOG_FATAL, "Need initialize first"); - return; // wait server and daemon ready + if (++waitServerDaemonReadyCount > 10) { + return ERR_UT_MODULE_WAITMAX; } - switch (thisClass->checkType) { - case UT_MOD_SHELL: - thisClass->TestShellExecute(); - break; - case UT_MOD_SHELL_INTERACTIVE: - thisClass->TestShellInterActive(); - break; - case UT_MOD_BASE: - thisClass->TestBaseCommand(); - break; - case UT_MOD_FILE: - thisClass->TestFileCommand(); - break; - default: - break; + if (!serverRunning || !daemonRunning) { + return ERR_UT_MODULE_NOTREADY; + } + if (bConnectToDaemon) { + PreConnectDaemon(DEBUG_ADDRESS.c_str(), DEBUG_TCP_CONNECT_KEY.c_str()); } - uv_close((uv_handle_t *)handle, FinishRemoveIdle); + hashInitialize = true; + return ERR_SUCCESS; +} + +void Runtime::DoCheck(uv_timer_t *handle) +{ + Runtime *thisClass = (Runtime *)handle->data; + do { + int checkRet = thisClass->CheckServerDaemonReady(); + if (checkRet == ERR_UT_MODULE_WAITMAX) { + break; + } else if (checkRet == ERR_UT_MODULE_NOTREADY) { + return; + } + // every case can be add more test... + switch (thisClass->checkType) { + case UT_MOD_SHELL: + thisClass->bCheckResult = TestShellExecute(thisClass); + break; + case UT_MOD_BASE: + thisClass->bCheckResult = TestBaseCommand(thisClass); + break; + case UT_MOD_FILE: + thisClass->bCheckResult = TestFileCommand(thisClass); + break; + case UT_MOD_FORWARD: + thisClass->bCheckResult = TestForwardCommand(thisClass); + break; + case UT_MOD_APP: + thisClass->bCheckResult = TestAppCommand(thisClass); + break; + default: + break; + } + } while (false); + uv_close((uv_handle_t *)handle, Base::CloseIdleCallback); thisClass->checkFinish = true; - uv_stop(&thisClass->loopMain); } -bool FrameRuntime::CheckEntry(UT_MOD_TYPE type) +bool Runtime::Initial(bool bConnectToDaemonIn) +{ + bConnectToDaemon = bConnectToDaemonIn; + constexpr int sleepTime = 300; + auto funcServerFinish = [](uv_work_t *req, int status) -> void { + auto thisClass = (Runtime *)req->data; + thisClass->serverRunning = false; + WRITE_LOG(LOG_DEBUG, "Ut runtime frame server thread finish"); + delete req; + }; + auto funcDaemonFinish = [](uv_work_t *req, int status) -> void { + auto thisClass = (Runtime *)req->data; + thisClass->daemonRunning = false; + WRITE_LOG(LOG_DEBUG, "Ut runtime frame daemon thread finish"); + delete req; + }; + + Base::StartWorkThread(&loopMain, StartServer, funcServerFinish, this); + Base::StartWorkThread(&loopMain, StartDaemon, funcDaemonFinish, this); + Base::TimerUvTask(&loopMain, this, DoCheck, sleepTime); + return true; +} + +bool Runtime::CheckEntry(UtModType type) { checkFinish = false; checkType = type; - Hdc::Base::IdleUvTask(&loopMain, this, DoCheck); WorkerPendding(); return bCheckResult; } -bool FrameRuntime::ResetTmpFolder() +bool Runtime::ResetUtTmpFolder() { #ifdef DEF_NULL struct stat statbuf; @@ -190,142 +209,21 @@ bool FrameRuntime::ResetTmpFolder() return true; } -void FrameRuntime::WorkerPendding() +bool Runtime::ResetUtTmpFile(string file) { - uv_run(&loopMain, UV_RUN_DEFAULT); - WRITE_LOG(LOG_DEBUG, "TesPendding free"); -} - -// ----------------------------如上都是内部辅助测试函数-------------------------------------------------------- -bool FrameRuntime::TestBaseCommand() -{ - uint8_t *bufPtr = nullptr; - int bytesIO = 0; - bool ret = false; - char bufString[256] = ""; - // test 'discover' - ResetTmpFolder(); - InnerCall(UT_DISCOVER); - if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/base.result").c_str(), (void **)&bufPtr, 0)) < 0) { - return false; - } - if (!strcmp("0", (char *)bufPtr)) { - delete[] bufPtr; - bufPtr = nullptr; - return false; - } - delete[] bufPtr; - bufPtr = nullptr; - // test 'targets' - ResetTmpFolder(); - InnerCall(UT_LIST_TARGETS); - constexpr int expert = 10; - if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/base.result").c_str(), (void **)&bufPtr, 0)) < expert) { - goto Finish; - } - if (!strcmp(EMPTY_ECHO.c_str(), (char *)bufPtr)) { - goto Finish; - } - delete[] bufPtr; - bufPtr = nullptr; - // test 'any' - ResetTmpFolder(); - InnerCall(UT_CONNECT_ANY); - if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/base.result").c_str(), (void **)&bufPtr, 0)) < 0) { - goto Finish; - } - if (strcmp("OK", (char *)bufPtr)) { - goto Finish; - } - // all pass - ret = true; - -Finish: - if (bufPtr) { - delete[] bufPtr; - bufPtr = nullptr; - } - bCheckResult = ret; - return ret; -} - -bool FrameRuntime::TestShellExecute() -{ - uint8_t *bufPtr = nullptr; - int bytesIO = 0; - bool ret = false; - char bufString[8192] = ""; - while (true) { - // test1 - ResetTmpFolder(); - InnerCall(UT_SHELL_BASIC); - if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/execute.result").c_str(), (void **)&bufPtr, 0)) < 10) { - break; - } - Base::RunPipeComand((const char *)"id", bufString, 8192, false); - if (strcmp(bufString, (char *)bufPtr)) { - break; - } - delete[] bufPtr; - bufPtr = nullptr; - // test 2 - ResetTmpFolder(); - InnerCall(UT_SHELL_LIGHT); - constexpr int expert = 10; - if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/execute.result").c_str(), (void **)&bufPtr, 0)) < expert) { - break; - } - Base::RunPipeComand((const char *)"cat /etc/passwd", bufString, 8192, false); - if (strcmp(bufString, (char *)bufPtr)) { - break; - } - delete[] bufPtr; - bufPtr = nullptr; - // all pass - ret = true; - break; - } - if (bufPtr) { - delete[] bufPtr; + string utFile = Base::StringFormat("%s/%s", UT_TMP_PATH.c_str(), file.c_str()); + string sCmd = "rm -f " + utFile; + struct stat statbuf; + if (!stat(utFile.c_str(), &statbuf)) { + system(sCmd.c_str()); } - bCheckResult = ret; - return ret; + return true; } -bool FrameRuntime::TestShellInterActive() +void Runtime::WorkerPendding() { - uint8_t *bufPtr = nullptr; - int bytesIO = 0; - bool ret = false; - - constexpr int buffSize = 256; - char bufString[buffSize] = ""; - // test - ResetTmpFolder(); - InnerCall(UT_SHELL_INTERACTIVE); - constexpr int expert = 10; - if ((bytesIO = Base::ReadBinFile((UT_TMP_PATH + "/shell.result").c_str(), (void **)&bufPtr, 0)) < expert) { - return false; - } - Base::RunPipeComand("id", bufString, 256, false); - if (strcmp(bufString, (char *)bufPtr)) { - goto Finish; - } - // all pass - ret = true; - -Finish: - if (bufPtr) { - delete[] bufPtr; - bufPtr = nullptr; - } - bCheckResult = ret; - return ret; + uv_run(&loopMain, UV_RUN_DEFAULT); + WRITE_LOG(LOG_DEBUG, "TesPendding free"); } -bool FrameRuntime::TestFileCommand() -{ - bCheckResult = true; - return true; -} } // namespace HdcTest \ No newline at end of file diff --git a/src/test/hdc_runtime_frame.h b/src/test/ut_runtime.h similarity index 65% rename from src/test/hdc_runtime_frame.h rename to src/test/ut_runtime.h index dd80d07a960399c9286a2c237c316c8b63d643f1..a8f0daff63ebd39ec8207542003278d314675f0a 100644 --- a/src/test/hdc_runtime_frame.h +++ b/src/test/ut_runtime.h @@ -12,57 +12,56 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef HDC_RUNTIME_FRAME_H -#define HDC_RUNTIME_FRAME_H +#ifndef HDC_UT_RUNTIME_H +#define HDC_UT_RUNTIME_H #include "ut_common.h" namespace HdcTest { -class FrameRuntime { +class Runtime { public: - enum UT_MOD_TYPE { + enum UtModType { UT_MOD_BASE, UT_MOD_SHELL, UT_MOD_SHELL_INTERACTIVE, UT_MOD_FILE, + UT_MOD_FORWARD, UT_MOD_APP, }; - FrameRuntime(); - ~FrameRuntime(); - bool Initial(bool bConnectToDaemon); - bool CheckEntry(UT_MOD_TYPE type); + Runtime(); + ~Runtime(); + bool Initial(bool bConnectToDaemonIn); + bool CheckEntry(UtModType type); + + bool ResetUtTmpFolder(); + bool ResetUtTmpFile(string file); + int InnerCall(int method); + uv_loop_t *GetRuntimeLoop() + { + return &loopMain; + }; private: - static void DoCheck(uv_idle_t *handle); - static void StartServer(void *arg); - static void StartDaemon(void *arg); + static void DoCheck(uv_timer_t *handle); + static void StartServer(uv_work_t *arg); + static void StartDaemon(uv_work_t *arg); static void CheckStopServer(uv_idle_t *arg); static void CheckStopDaemon(uv_idle_t *arg); - static void FinishRemoveIdle(uv_handle_t *handle) - { - delete (uv_idle_t *)handle; - } - - bool ResetTmpFolder(); void WorkerPendding(); - bool TestShellExecute(); - bool TestShellInterActive(); - bool TestBaseCommand(); - bool TestFileCommand(); - int InnerCall(int method); + int CheckServerDaemonReady(); bool serverRunning; bool daemonRunning; bool bCheckResult; bool checkFinish; bool hashInitialize; - UT_MOD_TYPE checkType; + UtModType checkType; uv_loop_t loopMain; uv_idle_t checkServerStop; uv_idle_t checkDaemonStop; Hdc::HdcServer *server; Hdc::HdcDaemon *daemon; - uv_thread_t tdServer; - uv_thread_t tdDaemon; + uint8_t waitServerDaemonReadyCount = 0; + bool bConnectToDaemon = false; }; } // namespace HdcTest #endif // HDC_FUNC_TEST_H \ No newline at end of file