diff --git a/.gitattributes b/.gitattributes index 51c63e295e0232f7095a8ee8e03713837e37f419..6e4add213eb67b38b6c95b40a551472e54c39a84 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13,3 +13,7 @@ *.so filter=lfs diff=lfs merge=lfs -text *.bin filter=lfs diff=lfs merge=lfs -text *.dll filter=lfs diff=lfs merge=lfs -text +*.dat filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.bz filter=lfs diff=lfs merge=lfs -text +*.gif filter=lfs diff=lfs merge=lfs -text diff --git a/BUILD.gn b/BUILD.gn old mode 100755 new mode 100644 index d1100a89f7a586e24049145c6bf0731fe0c9e090..6b9ab874cb253d808c1fe3462acbe48d36daa866 --- a/BUILD.gn +++ b/BUILD.gn @@ -50,7 +50,6 @@ ohos_executable("hdcd") { sources += hdc_common_sources defines = [ - "HDC_DEBUG", "HARMONY_PROJECT", ] diff --git a/README_zh.md b/README_zh.md old mode 100755 new mode 100644 index 21b5bb3da4da885d2cc818298d8add7ef61ac240..97f4b55dab28059c2e6c00d18ee459a5a22c6e71 --- a/README_zh.md +++ b/README_zh.md @@ -197,5 +197,5 @@ hdc当前支持如下命令: 研发工具链子系统 -**developtools\_hdc\_standard** +**developtools\_hdc\_standard** \ No newline at end of file diff --git a/ohos.build b/ohos.build old mode 100755 new mode 100644 diff --git a/prebuilt/linux-x86/hdc_std b/prebuilt/linux-x86/hdc_std deleted file mode 100755 index 1e714dcd9e37bd8a7f7400cd65a4ff3c81f365b5..0000000000000000000000000000000000000000 Binary files a/prebuilt/linux-x86/hdc_std and /dev/null differ diff --git a/prebuilt/linux/hdc-std b/prebuilt/linux/hdc-std new file mode 100755 index 0000000000000000000000000000000000000000..745e97d5644ee0aadf0a03a663c28e6e746d8ded Binary files /dev/null and b/prebuilt/linux/hdc-std differ diff --git a/prebuilt/windows/hdc_std.exe b/prebuilt/windows/hdc-std.exe old mode 100755 new mode 100644 similarity index 32% rename from prebuilt/windows/hdc_std.exe rename to prebuilt/windows/hdc-std.exe index 7243ddf1d74c528d756b22b320032fa01609bf57..c61be9369edb13c80d653bcbd7bc2fe15a151eee --- 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:36372d8eab32bfcd7e52975011dac360cf9e4e74e041d9caf50f7b5903646266 -size 2039296 +oid sha256:b668bf2366c668b6d213eeb57bad3105cb2679f96441ef7b71d4334846698f40 +size 4664727 diff --git a/src/common/async_cmd.cpp b/src/common/async_cmd.cpp old mode 100755 new mode 100644 index c0e3445d30ab1d266c3956009f8ed59f0f0d0bc0..edba9d14d96728487887d8a3564aff1db8a21f1a --- a/src/common/async_cmd.cpp +++ b/src/common/async_cmd.cpp @@ -72,6 +72,7 @@ void AsyncCmd::ExitCallback(uv_process_t *req, int64_t exitStatus, int tersignal thisClass->running = false; WRITE_LOG(LOG_DEBUG, "AsyncCmd::ExitCallback"); Base::TryCloseHandle((uv_handle_t *)req); + thisClass->cmdResult = STRING_EMPTY; } bool AsyncCmd::Initial(uv_loop_t *loopIn, const CmdResultCallback callback) diff --git a/src/common/async_cmd.h b/src/common/async_cmd.h old mode 100755 new mode 100644 diff --git a/src/common/auth.cpp b/src/common/auth.cpp old mode 100755 new mode 100644 index 696ace08b09fc53ca42e0346791d22e230df82fd..70d3b3b6c254bbfeffb1e593bf21b4b936852c90 --- a/src/common/auth.cpp +++ b/src/common/auth.cpp @@ -104,7 +104,7 @@ int RSA2RSAPublicKey(RSA *rsa, RSAPublicKey *publicKey) BN_mod_inverse(rsaN0inv, rsaRem, r32, ctx); publicKey->wordModulusSize = RSANUMWORDS; publicKey->rsaN0inv = 0 - BN_get_word(rsaN0inv); - for (i = 0; i < RSANUMWORDS; i++) { + for (i = 0; i < RSANUMWORDS; ++i) { BN_div(rsaRR, rsaRem, rsaRR, r32, ctx); publicKey->rr[i] = BN_get_word(rsaRem); BN_div(n, rsaRem, n, r32, ctx); @@ -431,7 +431,7 @@ void LoadDaemonKey(list *listPublicKey) int num = sizeof(keyPaths) / sizeof(keyPaths[0]); struct stat buf; - for (int i = 0; i < num; i++) { + for (int i = 0; i < num; ++i) { char *p = keyPaths[i]; if (!stat(p, &buf)) { WRITE_LOG(LOG_DEBUG, "Loading keys from '%s'", p); @@ -463,7 +463,7 @@ bool KeylistIncrement(list *listKey, uint8_t &authKeyIndex, void **out) return false; } auto listIndex = listKey->begin(); - std::advance(listIndex, authKeyIndex++); + std::advance(listIndex, ++authKeyIndex); *out = *listIndex; if (!*out) { return false; diff --git a/src/common/auth.h b/src/common/auth.h old mode 100755 new mode 100644 diff --git a/src/common/base.cpp b/src/common/base.cpp old mode 100755 new mode 100644 index 4a5ee0ab65b4545fb5d6af76c44275349ec032e5..457f62185a8bcb431ba698969d0a600e38b28ffe --- a/src/common/base.cpp +++ b/src/common/base.cpp @@ -13,12 +13,14 @@ * limitations under the License. */ #include "base.h" +#include #include #include #include #include #include #include +using namespace std::chrono; namespace Hdc { namespace Base { @@ -31,15 +33,94 @@ namespace Base { // Commenting the code will optimize and tune all log codes, and the compilation volume will be greatly reduced #define ENABLE_DEBUGLOG #ifdef ENABLE_DEBUGLOG + void GetLogDebugFunctioname(string &debugInfo, int line, string &threadIdString) + { + uint32_t currentThreadId = 0; + string tmpString = GetFileNameAny(debugInfo); +#ifdef _WIN32 + currentThreadId = GetCurrentThreadId(); +#else + currentThreadId = uv_thread_self(); // 64 just use 32bit +#endif + debugInfo = StringFormat("%s:%d", tmpString.c_str(), line); + if (g_logLevel < LOG_FULL) { + debugInfo = ""; + threadIdString = ""; + } else { + debugInfo = "[" + debugInfo + "]"; + threadIdString = StringFormat("[%x]", currentThreadId); + } + } + + bool IsWindowsSupportAnsiColor() + { +#ifdef _WIN32 + // Set output mode to handle virtual terminal sequences + HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); + if (hOut == INVALID_HANDLE_VALUE) { + return false; + } + DWORD dwMode = 0; + if (!GetConsoleMode(hOut, &dwMode)) { + return false; + } + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if (!SetConsoleMode(hOut, dwMode)) { + return false; + } +#endif + return true; + } + + void GetLogLevelAndTime(uint8_t logLevel, string &logLevelString, string &timeString) + { + system_clock::time_point timeNow = system_clock::now(); // now time + system_clock::duration sinceUnix0 = timeNow.time_since_epoch(); // since 1970 + time_t sSinceUnix0 = duration_cast(sinceUnix0).count(); + std::tm tim = *std::localtime(&sSinceUnix0); + bool enableAnsiColor = false; +#ifdef _WIN32 + enableAnsiColor = IsWindowsSupportAnsiColor(); +#else + enableAnsiColor = true; +#endif + if (enableAnsiColor) { + switch (logLevel) { + case LOG_FATAL: + logLevelString = "\033[1;31mF\033[0m"; + break; + case LOG_INFO: + logLevelString = "\033[1;32mI\033[0m"; + break; + case LOG_WARN: + logLevelString = "\033[1;33mW\033[0m"; + break; + case LOG_DEBUG: + logLevelString = "\033[1;36mD\033[0m"; + break; + default: + logLevelString = "\033[1;36mD\033[0m"; + break; + } + } else { + logLevelString = std::to_string(logLevel); + } + string msTimeSurplus; + if (g_logLevel > LOG_DEBUG) { + const auto sSinceUnix0Rest = duration_cast(sinceUnix0).count() % (TIME_BASE * TIME_BASE); + msTimeSurplus = StringFormat(".%06llu", sSinceUnix0Rest); + } + timeString = StringFormat("%d:%d:%d%s", tim.tm_hour, tim.tm_min, tim.tm_sec, msTimeSurplus.c_str()); + } + void PrintLogEx(const char *functionName, int line, uint8_t logLevel, const char *msg, ...) { string debugInfo; string logBuf; string logLevelString; string threadIdString; - string usTimeString; string sep = "\n"; - uint32_t currentThreadId = 0; + string timeString; if (logLevel > g_logLevel) { return; } @@ -50,54 +131,12 @@ namespace Base { if (logDetail.back() == '\n') { sep = "\r\n"; } - time_t timeLog; - struct tm *tim; - timeLog = time(nullptr); - tim = localtime(&timeLog); - if (tim == nullptr) { - return; - } - debugInfo = StringFormat("%s:%d", functionName, line); -#ifdef _WIN32 - currentThreadId = GetCurrentThreadId(); - logLevelString = std::to_string(logLevel); -#else - currentThreadId = uv_thread_self(); - switch (logLevel) { - case LOG_FATAL: - logLevelString = "\033[1;31mF\033[0m"; - break; - case LOG_INFO: - logLevelString = "\033[1;32mI\033[0m"; - break; - case LOG_WARN: - logLevelString = "\033[1;33mW\033[0m"; - break; - case LOG_DEBUG: - logLevelString = "\033[1;36mD\033[0m"; - break; - default: - logLevelString = "\033[1;36mD\033[0m"; - break; - } -#endif - if (g_logLevel < LOG_FULL) { - debugInfo = ""; - threadIdString = ""; - } else { - debugInfo = "[" + debugInfo + "]"; - threadIdString = StringFormat("[%x]", currentThreadId); - } -#ifdef DEF_NULL // if want detail running time info ,use [%d:%d:%d %ld] x x x timeUs - struct timespec times = { 0, 0 }; - clock_gettime(CLOCK_MONOTONIC, ×); - long timeUs = times.tv_sec * TIME_BASE * TIME_BASE + times.tv_nsec / TIME_BASE; - usTimeString = StringFormat(" %ld", timeUs); -#else - logBuf = StringFormat("[%s][%d:%d:%d%s]%s%s %s%s", logLevelString.c_str(), tim->tm_hour, tim->tm_min, - tim->tm_sec, usTimeString.c_str(), threadIdString.c_str(), debugInfo.c_str(), - logDetail.c_str(), sep.c_str()); -#endif + debugInfo = functionName; + GetLogDebugFunctioname(debugInfo, line, threadIdString); + GetLogLevelAndTime(logLevel, logLevelString, timeString); + logBuf = StringFormat("[%s][%s]%s%s %s%s", logLevelString.c_str(), timeString.c_str(), threadIdString.c_str(), + debugInfo.c_str(), logDetail.c_str(), sep.c_str()); + printf("%s", logBuf.c_str()); fflush(stdout); // logfile @@ -125,6 +164,20 @@ namespace Base { va_end(ap); } + string GetFileNameAny(string &path) + { + // if can linkwith -lstdc++fs, use std::filesystem::path(path).filename(); + string tmpString = path; + size_t tmpNum = 0; + if ((tmpNum = tmpString.rfind('/')) == std::string::npos) { + if ((tmpNum = tmpString.rfind('\\')) == std::string::npos) { + return tmpString; + } + } + tmpString = tmpString.substr(tmpNum + 1, tmpString.size() - tmpNum); + return tmpString; + } + int GetMaxBufSize() { return MAX_SIZE_IOBUF; @@ -132,19 +185,18 @@ namespace Base { void SetTcpOptions(uv_tcp_t *tcpHandle) { - constexpr int maxBufFactor = 6; + constexpr int maxBufFactor = 10; if (!tcpHandle) { WRITE_LOG(LOG_WARN, "SetTcpOptions nullptr Ptr"); return; } int timeout = GLOBAL_TIMEOUT; uv_tcp_keepalive(tcpHandle, 1, timeout / 2); - // 40k, set to io 8 times is more appropriate, otherwise asynchronous IO is too fast, a lot of IO is wasted on - // IOloop, too little transmission speed will decrease - int buffSize = 0; - buffSize = GetMaxBufSize() * maxBufFactor; - uv_recv_buffer_size((uv_handle_t *)tcpHandle, &buffSize); - uv_send_buffer_size((uv_handle_t *)tcpHandle, &buffSize); + // if MAX_SIZE_IOBUF==5k,bufMaxSize at least 40k. It must be set to io 8 times is more appropriate, + // otherwise asynchronous IO is too fast, a lot of IO is wasted on IOloop, transmission speed will decrease + int bufMaxSize = GetMaxBufSize() * maxBufFactor; + uv_recv_buffer_size((uv_handle_t *)tcpHandle, &bufMaxSize); + uv_send_buffer_size((uv_handle_t *)tcpHandle, &bufMaxSize); } void ReallocBuf(uint8_t **origBuf, int *nOrigSize, const int indexUsedBuf, int sizeWanted) @@ -194,14 +246,14 @@ namespace Base { bool TryCloseLoop(uv_loop_t *ptrLoop, const char *callerName) { // UV_RUN_DEFAULT: Runs the event loop until the reference count drops to zero. Always returns zero. - // UV_RUN_ONCE: Poll for new events once. Note that this function blocks if there are no pending events. Returns - // zero when done (no active handles or requests left), or non-zero if more events are expected - // (meaning you should run the event loop again sometime in the future). - // UV_RUN_NOWAIT: Poll for new events once but don't block if there are no pending events. + // UV_RUN_ONCE: Poll for new events once. Note that this function blocks if there are no pending events. + // Returns zero when done (no active handles or requests left), or non-zero if more events are + // expected meaning you should run the event loop again sometime in the future). + // UV_RUN_NOWAIT: Poll for new events once but don't block if there are no pending events. uint8_t closeRetry = 0; bool ret = false; constexpr int maxRetry = 3; - for (closeRetry = 0; closeRetry < maxRetry; closeRetry++) { + for (closeRetry = 0; closeRetry < maxRetry; ++closeRetry) { if (uv_loop_close(ptrLoop) == UV_EBUSY) { if (closeRetry > 2) { WRITE_LOG(LOG_WARN, "%s close busy,try:%d", callerName, closeRetry); @@ -260,8 +312,8 @@ namespace Base { return SendToStreamEx(handleStream, pDynBuf, bufLen, nullptr, (void *)SendCallback, (void *)pDynBuf); } - // handleSend is used for pipe thread sending, set nullptr for tcp, and dynamically allocated by malloc when buf is - // required + // handleSend is used for pipe thread sending, set nullptr for tcp, and dynamically allocated by malloc when buf + // is required int SendToStreamEx(uv_stream_t *handleStream, const uint8_t *buf, const int bufLen, uv_stream_t *handleSend, const void *finishCallback, const void *pWriteReqData) { @@ -404,7 +456,7 @@ namespace Base { isQuoted = false; } else { temp[j] = a; - j++; + ++j; } } else { switch (a) { @@ -413,7 +465,7 @@ namespace Base { isText = true; if (isSpace) { argv[argc] = temp + j; - argc++; + ++argc; } isSpace = false; break; @@ -423,7 +475,7 @@ namespace Base { case '\r': if (isText) { temp[j] = '\0'; - j++; + ++j; } isText = false; isSpace = true; @@ -432,15 +484,15 @@ namespace Base { isText = true; if (isSpace) { argv[argc] = temp + j; - argc++; + ++argc; } temp[j] = a; - j++; + ++j; isSpace = false; break; } } - i++; + ++i; } temp[j] = '\0'; argv[argc] = nullptr; @@ -708,7 +760,7 @@ namespace Base { } string GetFullFilePath(const string &s) - { + { // cannot use s.rfind(std::filesystem::path::preferred_separator #ifdef _WIN32 const char sep = '\\'; #else @@ -850,7 +902,6 @@ namespace Base { if (!len) { return 0; } - int padding = 0; if (b64input[len - 1] == '=' && b64input[len - 2] == '=') { // last two chars are = @@ -859,7 +910,6 @@ namespace Base { // last char is = padding = 1; } - return static_cast(len * 0.75 - padding); } @@ -949,7 +999,7 @@ namespace Base { return true; } - bool TimerUvTask(uv_loop_t *loop, void *data, uv_timer_cb cb) + bool TimerUvTask(uv_loop_t *loop, void *data, uv_timer_cb cb, int repeatTimeout) { uv_timer_t *timer = new uv_timer_t(); if (timer == nullptr) { @@ -957,12 +1007,45 @@ namespace Base { } timer->data = data; uv_timer_init(loop, timer); - constexpr int repeatTimeout = 250; // ms + // default 250ms uv_timer_start(timer, cb, 0, repeatTimeout); // delete by callback return true; } + // callback, uint8_t flag, string msg, const void * data + bool DelayDo(uv_loop_t *loop, const int delayMs, const uint8_t flag, string msg, void *data, + std::function cb) + { + struct DelayDoParam { + uv_timer_t handle; + uint8_t flag; + string msg; + void *data; + std::function cb; + }; + auto funcDelayDo = [](uv_timer_t *handle) -> void { + DelayDoParam *st = (DelayDoParam *)handle->data; + st->cb(st->flag, st->msg, st->data); + uv_close((uv_handle_t *)handle, [](uv_handle_t *handle) { + DelayDoParam *st = (DelayDoParam *)handle->data; + delete st; + }); + }; + DelayDoParam *st = new DelayDoParam(); + if (st == nullptr) { + return false; + } + st->cb = cb; + st->flag = flag; + st->msg = msg; + st->data = data; + st->handle.data = st; + uv_timer_init(loop, &st->handle); + uv_timer_start(&st->handle, funcDelayDo, delayMs, 0); + return true; + } + string ReplaceAll(string str, const string from, const string to) { string::size_type startPos = 0; @@ -990,5 +1073,44 @@ namespace Base { string res(resolvedPath); return res; } + + uint8_t CalcCheckSum(const uint8_t *data, int len) + { + uint8_t ret = 0; + for (int i = 0; i < len; ++i) { + ret += data[i]; + } + return ret; + } + + int open_osfhandle(uv_os_fd_t os_fd) + { + // equal libuv's uv_open_osfhandle, libuv 1.23 added. old libuv not impl... +#ifdef _WIN32 + return _open_osfhandle((intptr_t)os_fd, 0); +#else + return os_fd; +#endif + } + + uv_os_sock_t DuplicateUvSocket(uv_tcp_t *tcp) + { + uv_os_sock_t dupFd = -1; +#ifdef _WIN32 + WSAPROTOCOL_INFO info; + memset(&info, 0, sizeof(info)); + if (WSADuplicateSocketA(tcp->socket, GetCurrentProcessId(), &info) < 0) { + return dupFd; + } + dupFd = WSASocketA(0, 0, 0, &info, 0, 0); +#else + uv_os_fd_t fdOs; + if (uv_fileno((const uv_handle_t *)tcp, &fdOs) < 0) { + return ERR_API_FAIL; + } + dupFd = dup(open_osfhandle(fdOs)); +#endif + return dupFd; + } } } // namespace Hdc diff --git a/src/common/base.h b/src/common/base.h old mode 100755 new mode 100644 index 12e8daaaebd22b242b8e59144beb386ca8ed49cd..9357650596f8944c047e94f01ebb6441a48298b7 --- a/src/common/base.h +++ b/src/common/base.h @@ -89,11 +89,7 @@ namespace Base { // just zero memory buf, such as pointer template int ZeroBuf(T &arrayBuf, int size) { - if (arrayBuf == nullptr) { - return ERR_BUF_RESET; - } else { - return memset_s(arrayBuf, size, 0, size); - } + return memset_s(arrayBuf, size, 0, size); } // clang-format off const string StringFormat(const char * const formater, ...); @@ -101,8 +97,18 @@ namespace Base { // clang-format on string GetVersion(); bool IdleUvTask(uv_loop_t *loop, void *data, uv_idle_cb cb); - bool TimerUvTask(uv_loop_t *loop, void *data, uv_timer_cb cb); + bool TimerUvTask(uv_loop_t *loop, void *data, uv_timer_cb cb, int repeatTimeout = 250); + bool DelayDo(uv_loop_t *loop, const int delayMs, const uint8_t flag, string msg, void *data, + std::function cb); + inline bool DelayDoSimple(uv_loop_t *loop, const int delayMs, + std::function cb) + { + return DelayDo(loop, delayMs, 0, "", nullptr, cb); + } 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); } // namespace base } // namespace Hdc diff --git a/src/common/channel.cpp b/src/common/channel.cpp old mode 100755 new mode 100644 index b49eeed431cf9b248538baaa7d044d75f4edc12a..6cd141dfe14b6b5cd30bf7bd365c43906c90bcb3 --- a/src/common/channel.cpp +++ b/src/common/channel.cpp @@ -22,7 +22,6 @@ HdcChannelBase::HdcChannelBase(const bool serverOrClient, const string &addrStri uv_rwlock_init(&mainAsync); uv_async_init(loopMain, &asyncMainLoop, MainAsyncCallback); uv_rwlock_init(&lockMapChannel); - uv_mutex_init(&freeChannel); } HdcChannelBase::~HdcChannelBase() @@ -35,7 +34,6 @@ HdcChannelBase::~HdcChannelBase() uv_rwlock_destroy(&mainAsync); uv_rwlock_destroy(&lockMapChannel); - uv_mutex_destroy(&freeChannel); } vector HdcChannelBase::GetChannelHandshake(string &connectKey) const @@ -84,24 +82,12 @@ bool HdcChannelBase::SetChannelTCPString(const string &addrString) void HdcChannelBase::ClearChannels() { - map::iterator iter; - for (iter = mapChannel.begin(); iter != mapChannel.end();) { - uint32_t channelId = iter->first; - HChannel hChannel = iter->second; - if (!hChannel->mainCleared) { - FreeChannel(channelId); - while (!hChannel->mainCleared) { - usleep(1000); - } + for (auto v : mapChannel) { + HChannel hChannel = (HChannel)v.second; + if (!hChannel->isDead) { + FreeChannel(hChannel->channelId); } - uv_rwlock_wrlock(&lockMapChannel); - mapChannel.erase(iter++->first); - uv_rwlock_wrunlock(&lockMapChannel); - delete hChannel; - } - uv_rwlock_wrlock(&lockMapChannel); - mapChannel.clear(); - uv_rwlock_wrunlock(&lockMapChannel); + } } void HdcChannelBase::WorkerPendding() @@ -121,7 +107,10 @@ void HdcChannelBase::ReadStream(uv_stream_t *tcp, ssize_t nread, const uv_buf_t if (nread == UV_ENOBUFS) { WRITE_LOG(LOG_DEBUG, "HdcChannelBase::ReadStream Pipe IOBuf max"); - } else if (nread <= 0) { + } else if (nread == 0) { + // maybe just afer accept, second client req + WRITE_LOG(LOG_DEBUG, "HdcChannelBase::ReadStream idle read"); + } else if (nread < 0) { Base::TryCloseHandle((uv_handle_t *)tcp); WRITE_LOG(LOG_DEBUG, "HdcChannelBase::ReadStream failed2:%s", uv_err_name(nread)); needExit = true; @@ -147,8 +136,7 @@ void HdcChannelBase::ReadStream(uv_stream_t *tcp, ssize_t nread, const uv_buf_t indexBuf += DWORD_SERIALIZE_SIZE + size; } if (indexBuf > 0 && hChannel->availTailIndex > 0) { - if (EOK - != memmove_s(hChannel->ioBuf, hChannel->bufSize, hChannel->ioBuf + indexBuf, hChannel->availTailIndex)) { + if (memmove_s(hChannel->ioBuf, hChannel->bufSize, hChannel->ioBuf + indexBuf, hChannel->availTailIndex)) { needExit = true; goto Finish; } @@ -156,22 +144,22 @@ void HdcChannelBase::ReadStream(uv_stream_t *tcp, ssize_t nread, const uv_buf_t Finish: if (needExit) { - WRITE_LOG(LOG_DEBUG, "Read Stream needExit"); thisClass->FreeChannel(hChannel->channelId); + WRITE_LOG(LOG_DEBUG, "Read Stream needExit, FreeChannel finish"); } } void HdcChannelBase::WriteCallback(uv_write_t *req, int status) { HChannel hChannel = (HChannel)req->handle->data; - hChannel->sendRef--; + --hChannel->sendRef; HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; if (status < 0) { Base::TryCloseHandle((uv_handle_t *)req->handle); - } - if (hChannel->channelDead && !hChannel->sendRef) { - thisClass->FreeChannel(hChannel->channelId); - WRITE_LOG(LOG_DEBUG, "WriteCallback TryCloseHandle"); + if (!hChannel->isDead && !hChannel->sendRef) { + thisClass->FreeChannel(hChannel->channelId); + WRITE_LOG(LOG_DEBUG, "WriteCallback TryCloseHandle"); + } } delete[]((uint8_t *)req->data); delete req; @@ -252,7 +240,7 @@ void HdcChannelBase::Send(const uint32_t channelId, uint8_t *bufPtr, const int s uv_stream_t *sendStream = nullptr; int sizeNewBuf = size + DWORD_SERIALIZE_SIZE; HChannel hChannel = (HChannel)AdminChannel(OP_QUERY, channelId, nullptr); - if (!hChannel || hChannel->channelDead) { + if (!hChannel || hChannel->isDead) { return; } auto data = new uint8_t[sizeNewBuf](); @@ -264,8 +252,7 @@ void HdcChannelBase::Send(const uint32_t channelId, uint8_t *bufPtr, const int s delete[] data; return; } - uv_mutex_lock(&hChannel->sendMutex); - hChannel->sendRef++; + ++hChannel->sendRef; if (hChannel->hWorkThread == uv_thread_self()) { sendStream = (uv_stream_t *)&hChannel->hWorkTCP; } else { @@ -274,7 +261,6 @@ void HdcChannelBase::Send(const uint32_t channelId, uint8_t *bufPtr, const int s if (uv_is_writable(sendStream)) { Base::SendToStreamEx(sendStream, data, sizeNewBuf, nullptr, (void *)WriteCallback, data); } - uv_mutex_unlock(&hChannel->sendMutex); } void HdcChannelBase::AllocCallback(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) @@ -300,85 +286,104 @@ uint32_t HdcChannelBase::MallocChannel(HChannel *hOutChannel) uint32_t channelId = Base::GetRuntimeMSec(); if (isServerOrClient) { hChannel->serverOrClient = isServerOrClient; - channelId++; // Use different value for serverForClient&client in per process + ++channelId; // Use different value for serverForClient&client in per process } uv_tcp_init(loopMain, &hChannel->hWorkTCP); + ++hChannel->uvRef; hChannel->hWorkThread = uv_thread_self(); hChannel->hWorkTCP.data = hChannel; hChannel->clsChannel = this; hChannel->channelId = channelId; AdminChannel(OP_ADD, channelId, hChannel); *hOutChannel = hChannel; - uv_mutex_init(&hChannel->sendMutex); WRITE_LOG(LOG_DEBUG, "Mallocchannel:%d", channelId); return channelId; } -void HdcChannelBase::FreeChannelContinue(HChannel hChannel) +// work when libuv-handle at struct of HdcSession has all callback finished +void HdcChannelBase::FreeChannelFinally(uv_idle_t *handle) { - // Call from main thread only - NotifyInstanceChannelFree(hChannel); - if (hChannel->hChildWorkTCP.loop) { - auto ctrl = HdcSessionBase::BuildCtrlString(SP_DEATCH_CHANNEL, hChannel->channelId, nullptr, 0); - Base::SendToStream(reinterpret_cast(&hChannel->targetSession->ctrlPipe[STREAM_MAIN]), - ctrl.data(), ctrl.size()); - while (!hChannel->childCleared) { - usleep(1000); - } + HChannel hChannel = (HChannel)handle->data; + HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; + if (hChannel->uvRef > 0) { + return; + } + thisClass->NotifyInstanceChannelFree(hChannel); + thisClass->AdminChannel(OP_REMOVE, hChannel->channelId, nullptr); + WRITE_LOG(LOG_DEBUG, "!!!FreeChannelFinally channelId:%d finish", hChannel->channelId); + if (!hChannel->serverOrClient) { + uv_stop(thisClass->loopMain); } - uv_mutex_destroy(&hChannel->sendMutex); + delete hChannel; + Base::TryCloseHandle((const uv_handle_t *)handle, Base::CloseIdleCallback); +} + +void HdcChannelBase::FreeChannelContinue(HChannel hChannel) +{ + auto closeChannelHandle = [](uv_handle_t *handle) -> void { + HChannel hChannel = (HChannel)handle->data; + --hChannel->uvRef; + Base::TryCloseHandle((uv_handle_t *)handle); + }; + hChannel->availTailIndex = 0; if (hChannel->ioBuf) { - hChannel->availTailIndex = 0; - hChannel->bufSize = 0; delete[] hChannel->ioBuf; hChannel->ioBuf = nullptr; } - Base::TryCloseHandle((uv_handle_t *)&hChannel->hWorkTCP); - // Notify main thread exit for client instance if (!hChannel->serverOrClient) { - Base::TryCloseHandle((uv_handle_t *)&hChannel->stdinPipe); - Base::TryCloseHandle((uv_handle_t *)&hChannel->stdoutPipe); - Base::TryCloseHandle((uv_handle_t *)&hChannel->stdinTty); - Base::TryCloseHandle((uv_handle_t *)&hChannel->stdoutTty); - uv_stop(loopMain); - } - hChannel->mainCleared = true; - uv_mutex_unlock(&freeChannel); - WRITE_LOG(LOG_DEBUG, "Freechannel finish id:%d sendref:%d", hChannel->channelId, uint32_t(hChannel->sendRef)); + Base::TryCloseHandle((uv_handle_t *)&hChannel->stdinTty, closeChannelHandle); + Base::TryCloseHandle((uv_handle_t *)&hChannel->stdoutTty, closeChannelHandle); + } + if (uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP)) { + --hChannel->uvRef; + } else { + Base::TryCloseHandle((uv_handle_t *)&hChannel->hWorkTCP, closeChannelHandle); + } + Base::IdleUvTask(loopMain, hChannel, FreeChannelFinally); +} + +void HdcChannelBase::FreeChannelOpeate(uv_timer_t *handle) +{ + HChannel hChannel = (HChannel)handle->data; + HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; + if (hChannel->sendRef > 0) { + return; + } + if (hChannel->hChildWorkTCP.loop) { + auto ctrl = HdcSessionBase::BuildCtrlString(SP_DEATCH_CHANNEL, hChannel->channelId, nullptr, 0); + thisClass->ChannelSendSessionCtrlMsg(ctrl, hChannel->targetSessionId); + auto callbackCheckFreeChannelContinue = [](uv_timer_t *handle) -> void { + HChannel hChannel = (HChannel)handle->data; + HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel; + if (!hChannel->childCleared) { + return; + } + Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback); + thisClass->FreeChannelContinue(hChannel); + }; + Base::TimerUvTask(thisClass->loopMain, hChannel, callbackCheckFreeChannelContinue); + } else { + thisClass->FreeChannelContinue(hChannel); + } + Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback); } void HdcChannelBase::FreeChannel(const uint32_t channelId) { - bool bNotTodo = true; HChannel hChannel = AdminChannel(OP_QUERY, channelId, nullptr); if (!hChannel) { return; } - hChannel->channelDead = true; // Two cases: alloc in main thread, or work thread if (hChannel->hWorkThread != uv_thread_self()) { PushAsyncMessage(hChannel->channelId, ASYNC_FREE_SESSION, nullptr, 0); return; } - uv_mutex_lock(&freeChannel); - while (true) { - if (!hChannel) { - break; - } - if (hChannel->sendRef) { - break; // still sending, early exit - } - if (hChannel->mainCleared) { - break; - } - bNotTodo = false; - break; - } - if (bNotTodo) { - uv_mutex_unlock(&freeChannel); + if (hChannel->isDead) { return; } - FreeChannelContinue(hChannel); + Base::TimerUvTask(loopMain, hChannel, FreeChannelOpeate, MINOR_TIMEOUT); // do immediately + hChannel->isDead = true; } HChannel HdcChannelBase::AdminChannel(const uint8_t op, const uint32_t channelId, HChannel hInput) diff --git a/src/common/channel.h b/src/common/channel.h old mode 100755 new mode 100644 index b4fd207002754310e1f04cd5545ec564f1838e63..72b81813beb80b12e57bed6d2234f1a48009d3e3 --- a/src/common/channel.h +++ b/src/common/channel.h @@ -44,6 +44,10 @@ protected: } virtual void NotifyInstanceChannelFree(HChannel hChannel) {}; void Send(const uint32_t channelId, uint8_t *bufPtr, const int size); + virtual bool ChannelSendSessionCtrlMsg(vector &ctrlMsg, uint32_t sessionId) + { + return true; // just server use + } string channelHostPort; string channelHost; @@ -53,12 +57,13 @@ protected: uv_rwlock_t mainAsync; uv_async_t asyncMainLoop; list lstMainThreadOP; - uv_mutex_t freeChannel; private: static void MainAsyncCallback(uv_async_t *handle); static void WriteCallback(uv_write_t *req, int status); static void AsyncMainLoopTask(uv_idle_t *handle); + static void FreeChannelOpeate(uv_timer_t *handle); + static void FreeChannelFinally(uv_idle_t *handle); void ClearChannels(); void FreeChannelContinue(HChannel hChannel); bool SetChannelTCPString(const string &addrString); diff --git a/src/common/common.h b/src/common/common.h old mode 100755 new mode 100644 diff --git a/src/common/debug.cpp b/src/common/debug.cpp old mode 100755 new mode 100644 index 5a96307965d1fcc19cc2dc877a749af09d48c401..8c2524cf7c8529151a05fccbdffb4c61279e33cd --- a/src/common/debug.cpp +++ b/src/common/debug.cpp @@ -55,6 +55,9 @@ namespace Debug { if (fp == nullptr) { if (snprintf_s(pathName, sizeof(pathName), sizeof(pathName) - 1, "/tmp/%s", fileName) < 0 || (fp = fopen(pathName, "r")) == nullptr) { + if (fp != nullptr) { + fclose(fp); + } WRITE_LOG(LOG_DEBUG, "Write hex to %s failed!", pathName); return ERR_FILE_WRITE; } @@ -66,7 +69,6 @@ namespace Debug { fclose(fp); return ERR_BUF_SIZE; } - int ret = fread(buf, 1, size, fp); fflush(fp); fclose(fp); @@ -90,7 +92,7 @@ namespace Debug { int PrintfHexBuf(const uint8_t *buf, int bufLen) { int i = 0; - for (i = 0; i < bufLen; i++) { + for (i = 0; i < bufLen; ++i) { printf("0x%02x, ", buf[i]); fflush(stdout); } diff --git a/src/common/debug.h b/src/common/debug.h old mode 100755 new mode 100644 diff --git a/src/common/define.h b/src/common/define.h old mode 100755 new mode 100644 index 3b9d16f01daad36b96ceb60ab8f5fbb910f522f9..fc3a8a440b54f224c153090cd55a9710d3c30610 --- a/src/common/define.h +++ b/src/common/define.h @@ -26,6 +26,8 @@ constexpr uint8_t SIZE_THREAD_POOL = 8; constexpr uint8_t GLOBAL_TIMEOUT = 60; constexpr uint16_t DEFAULT_PORT = 8710; constexpr uint16_t EXTRA_ALLOC_SIZE = 2048; +constexpr uint8_t MINOR_TIMEOUT = 5; +constexpr bool ENABLE_IO_CHECKSUM = false; const string UT_TMP_PATH = "/tmp/hdc-ut"; const string SERVER_NAME = "HDCServer"; @@ -45,13 +47,13 @@ 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 = 128; +constexpr uint8_t MAX_IO_OVERLAP = 16; constexpr auto TIME_BASE = 1000; // time unit conversion base value // 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.0b"; // same with openssl version, 1.1.2==VERNUMBER 0x10102000 +const string VERSION_NUMBER = "1.1.0d"; // 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]"; @@ -138,9 +140,14 @@ enum RetErrCode { 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 @@ -151,7 +158,6 @@ enum AsyncEvent { enum InnerCtrlCommand { SP_START_SESSION = 0, SP_STOP_SESSION, - SP_REGISTER_CHANNEL, SP_ATTACH_CHANNEL, SP_DEATCH_CHANNEL, SP_JDWP_NEWFD, @@ -162,7 +168,6 @@ enum HdcCommand { CMD_KERNEL_HELP = 0, CMD_KERNEL_HANDSHAKE, CMD_KERNEL_CHANNEL_CLOSE, - CMD_KERNEL_CHANNEL_DETCH, CMD_KERNEL_SERVER_KILL, CMD_KERNEL_TARGET_DISCOVER, CMD_KERNEL_TARGET_LIST, @@ -273,10 +278,10 @@ struct HdcUSB { 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 control; // EP0 int bulkOut; // EP1 int bulkIn; // EP2 vector bufRecv; @@ -290,11 +295,9 @@ struct HdcSession { string connectKey; uint8_t connType; // ConnType uint32_t sessionId; - uv_mutex_t sendMutex; std::atomic sendRef; uint8_t uvRef; // libuv handle ref -- just main thread now bool childCleared; - bool mainCleared; map *mapTask; // class ptr void *classInstance; // HdcSessionBase instance, HdcServer or HdcDaemon @@ -316,7 +319,7 @@ struct HdcSession { uv_tcp_t dataPipe[2]; int dataFd[2]; // data channel socketpair uv_tcp_t hChildWorkTCP; // work channel,separate thread for server/daemon - uv_os_fd_t fdChildWorkTCP; + uv_os_sock_t fdChildWorkTCP; // usb handle HUSB hUSB; // tcp handle @@ -329,28 +332,25 @@ using HSession = struct HdcSession *; struct HdcChannel { void *clsChannel; // ptr Class of serverForClient or client uint32_t channelId; - uv_mutex_t sendMutex; // lock of send 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 channelDead; + bool isDead; bool serverOrClient; // client's channel/ server's channel bool childCleared; - bool mainCleared; bool interactiveShellMode; // Is shell interactive mode std::atomic sendRef; - HSession targetSession; + uint32_t targetSessionId; // child work uv_tcp_t hChildWorkTCP; // work channel for server, no use in client - uv_os_fd_t fdChildWorkTCP; + uv_os_sock_t fdChildWorkTCP; // read io cache int bufSize; // total buffer size int availTailIndex; // buffer available data size uint8_t *ioBuf; // std - uv_pipe_t stdinPipe; - uv_pipe_t stdoutPipe; uv_tty_t stdinTty; uv_tty_t stdoutTty; char bufStd[128]; diff --git a/src/common/define_plus.h b/src/common/define_plus.h old mode 100755 new mode 100644 diff --git a/src/common/file.cpp b/src/common/file.cpp old mode 100755 new mode 100644 index 9e90a5582d23afe605aabb52463e8f06cd4d905a..85a994efbba364c4a5953f46198fd98c5dbac61c --- a/src/common/file.cpp +++ b/src/common/file.cpp @@ -40,29 +40,40 @@ void HdcFile::StopTask() bool HdcFile::BeginTransfer(CtxFile *context, const char *command) { int argc = 0; + int srcOffset = 0; bool ret = false; + 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 < 2) { + if (argc < CMD_ARG1_COUNT) { goto Finish; } context->localPath = argv[argc - 2]; - context->remotePath = argv[argc - 1]; - if (!Base::CheckDirectoryOrPath(context->localPath.c_str(), true, true)) { - goto Finish; - } - context->localName = Base::GetFullFilePath(context->localPath); - for (int i = 0; i < argc - 2; i++) { - if (!strcmp(argv[i], "-z")) { + for (int i = 0; i < argc - CMD_ARG1_COUNT; i++) { + if (argv[i] == CMD_OPTION_ZIP) { context->transferConfig.compressType = COMPRESS_LZ4; - } - if (!strcmp(argv[i], "-sync")) { + srcOffset += strlen(argv[i]) + 1; + } else if (argv[i] == CMD_OPTION_SYNC) { context->transferConfig.updateIfNew = true; - } - if (!strcmp(argv[i], "-a")) { + srcOffset += strlen(argv[i]) + 1; + } else if (argv[i] == CMD_OPTION_TSTMP) { context->transferConfig.holdTimestamp = true; + srcOffset += strlen(argv[i]) + 1; } } - refCount++; + context->remotePath = argv[argc - 1]; + if (argc > CMD_ARG1_COUNT) { + context->localPath + = std::string(command + srcOffset, strlen(command) - srcOffset - context->remotePath.size() - 1); + } 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); context->master = true; ret = true; @@ -122,7 +133,7 @@ bool HdcFile::SlaveCheck(uint8_t *payload, const int payloadSize) } } // begin work - refCount++; + ++refCount; uv_fs_open(loopTask, &ctxNow.fsOpenReq, ctxNow.localPath.c_str(), UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, OnFileOpen); ctxNow.transferBegin = Base::GetRuntimeMSec(); @@ -145,9 +156,9 @@ bool HdcFile::CommandDispatch(const uint16_t command, uint8_t *payload, const in } case CMD_FILE_FINISH: { if (*payload) { // close-step3 - (*payload)--; + --(*payload); SendToAnother(CMD_FILE_FINISH, payload, 1); - refCount++; + ++refCount; uv_fs_close(loopTask, &ctxNow.fsCloseReq, ctxNow.fsOpenReq.result, OnFileClose); } else { // close-step3 TransferSummary(&ctxNow); diff --git a/src/common/file.h b/src/common/file.h old mode 100755 new mode 100644 diff --git a/src/common/file_descriptor.cpp b/src/common/file_descriptor.cpp old mode 100755 new mode 100644 index 440d83030a6cd6cdc72c70584d86a3ebd9f6a40f..cfc7e4d5037864d4a6694728e4220f464b25f4a1 --- a/src/common/file_descriptor.cpp +++ b/src/common/file_descriptor.cpp @@ -16,7 +16,7 @@ namespace Hdc { HdcFileDescriptor::HdcFileDescriptor(uv_loop_t *loopIn, int fdToRead, void *callerContextIn, - CallBackWhenRead callbackReadIn, CmdResultCallback callbackFinishIn) + CallBackWhenRead callbackReadIn, CmdResultCallback callbackFinishIn) { loop = loopIn; workContinue = true; @@ -75,7 +75,7 @@ void HdcFileDescriptor::OnFileIO(uv_fs_t *req) delete[] buf; delete ctxIO; - thisClass->refIO--; + --thisClass->refIO; if (bFinish) { thisClass->callbackFinish(thisClass->callerContext, fetalFinish, "OnRead finish"); thisClass->workContinue = false; @@ -104,7 +104,7 @@ int HdcFileDescriptor::LoopRead() contextIO->bufIO = buf; contextIO->thisClass = this; req->data = contextIO; - refIO++; + ++refIO; iov = uv_buf_init((char *)buf, readMax); uv_fs_read(loop, req, fdIO, &iov, 1, -1, OnFileIO); @@ -144,7 +144,7 @@ int HdcFileDescriptor::WriteWithMem(uint8_t *data, int size) contextIO->bufIO = data; contextIO->thisClass = this; req->data = contextIO; - refIO++; + ++refIO; uv_buf_t iov = uv_buf_init((char *)data, size); uv_fs_write(loop, req, fdIO, &iov, 1, -1, OnFileIO); diff --git a/src/common/file_descriptor.h b/src/common/file_descriptor.h old mode 100755 new mode 100644 diff --git a/src/common/forward.cpp b/src/common/forward.cpp old mode 100755 new mode 100644 index e4a85093726303ff9f613b10c58a48ee9eb7bfd2..431887ed96c856f5f186676bce663e4cbe2921fd --- a/src/common/forward.cpp +++ b/src/common/forward.cpp @@ -38,7 +38,7 @@ bool HdcForwardBase::ReadyForRelease() void HdcForwardBase::StopTask() { map::iterator iter; - for (iter = mapCtxPoint.begin(); iter != mapCtxPoint.end(); iter++) { + for (iter = mapCtxPoint.begin(); iter != mapCtxPoint.end(); ++iter) { HCtxForward ctx = iter->second; FreeContext(ctx, 0, false); } @@ -123,7 +123,7 @@ void HdcForwardBase::FreeContextCallBack(HCtxForward ctx) { AdminContext(OP_REMOVE, ctx->id, nullptr); delete ctx; - refCount--; + --refCount; } void HdcForwardBase::FreeJDWP(HCtxForward ctx) diff --git a/src/common/forward.h b/src/common/forward.h old mode 100755 new mode 100644 diff --git a/src/common/serial_struct.h b/src/common/serial_struct.h old mode 100755 new mode 100644 index 26a2bb338024daf8211b90143d55bb7f9e81a56a..2a9e8588ed0e45e699bd8c0ae97890f1cef3cc8e --- a/src/common/serial_struct.h +++ b/src/common/serial_struct.h @@ -1213,7 +1213,6 @@ namespace SerialStruct { const std::string &_in; size_t _pos; }; - // mytype template<> struct Serializer { static void Serialize(uint32_t tag, uint8_t value, FlagsType<>, Writer &out, bool force = false) @@ -1245,6 +1244,37 @@ namespace SerialStruct { } return false; } + }; + template<> struct Serializer { + static void Serialize(uint32_t tag, uint16_t value, FlagsType<>, Writer &out, bool force = false) + { + Serializer::Serialize(tag, value, FlagsType(), out, force); + } + + static void SerializePacked(uint16_t value, FlagsType<>, Writer &out) + { + Serializer::SerializePacked(value, FlagsType(), out); + } + + static bool Parse(WireType wire_type, uint16_t &value, FlagsType<>, reader &in) + { + uint32_t intermedaite_value; + if (Serializer::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) { + value = static_cast(intermedaite_value); + return true; + } + return false; + } + + static bool ParsePacked(uint16_t &value, FlagsType<>, reader &in) + { + uint32_t intermedaite_value; + if (Serializer::ParsePacked(intermedaite_value, FlagsType<>(), in)) { + value = static_cast(intermedaite_value); + return true; + } + return false; + } }; // mytype finish template std::string SerializeToString(const T &value) @@ -1302,6 +1332,16 @@ namespace SerialStruct { Field<5, &Hdc::HdcSessionBase::SessionHandShake::buf>("buf")); } }; + + template<> struct Descriptor { + static auto type() + { + return Message(Field<1, &Hdc::HdcSessionBase::PayloadProtect::channelId>("channelId"), + Field<2, &Hdc::HdcSessionBase::PayloadProtect::commandFlag>("commandFlag"), + Field<3, &Hdc::HdcSessionBase::PayloadProtect::checkSum>("checkSum"), + Field<4, &Hdc::HdcSessionBase::PayloadProtect::vCode>("vCode")); + } + }; } // SerialStruct } // Hdc #endif // HDC_SERIAL_STRUCT_H diff --git a/src/common/session.cpp b/src/common/session.cpp old mode 100755 new mode 100644 index d024e90b5e539bb6535b6da2ec6ee041bc95c15b..0f7d22d59b948e81dc779df090145a434749e8be --- a/src/common/session.cpp +++ b/src/common/session.cpp @@ -88,7 +88,7 @@ bool HdcSessionBase::BeginRemoveTask(HTaskInfo hTask) HSession hSession = thisClass->AdminSession(OP_QUERY, hTask->sessionId, nullptr); thisClass->AdminTask(OP_REMOVE, hSession, hTask->channelId, nullptr); WRITE_LOG(LOG_DEBUG, "TaskDelay task remove finish, channelId:%d", hTask->channelId); - delete hTask; // delete + delete hTask; uv_close((uv_handle_t *)handle, Base::CloseIdleCallback); }; Base::IdleUvTask(hTask->runLoop, hTask, taskClassDeleteRetry); @@ -113,7 +113,7 @@ void HdcSessionBase::ClearOwnTasks(HSession hSession, const uint32_t channelIDIn HTaskInfo hTask = iter->second; if (channelIDInput != 0) { // single if (channelIDInput != channelId) { - iter++; + ++iter; continue; } BeginRemoveTask(hTask); @@ -123,7 +123,7 @@ void HdcSessionBase::ClearOwnTasks(HSession hSession, const uint32_t channelIDIn } // multi BeginRemoveTask(hTask); - iter++; + ++iter; } } @@ -133,7 +133,7 @@ void HdcSessionBase::ClearSessions() // broadcast free singal for (auto v : mapSession) { HSession hSession = (HSession)v.second; - if (!hSession->mainCleared) { + if (!hSession->isDead) { FreeSession(hSession->sessionId); } } @@ -166,7 +166,7 @@ void HdcSessionBase::EnumUSBDeviceRegister(void (*pCallBack)(HSession hSession)) } uv_rwlock_rdlock(&lockMapSession); map::iterator i; - for (i = mapSession.begin(); i != mapSession.end(); i++) { + for (i = mapSession.begin(); i != mapSession.end(); ++i) { HSession hs = i->second; if (hs->connType != CONN_USB) { continue; @@ -203,7 +203,7 @@ HSession HdcSessionBase::QueryUSBDeviceRegister(void *pDev, int busIDIn, int dev } uv_rwlock_rdlock(&lockMapSession); map::iterator i; - for (i = mapSession.begin(); i != mapSession.end(); i++) { + for (i = mapSession.begin(); i != mapSession.end(); ++i) { HSession hs = i->second; if (hs->connType == CONN_USB) { continue; @@ -273,7 +273,7 @@ void HdcSessionBase::PushAsyncMessage(const uint32_t sessionId, const uint8_t me param->method = method; if (dataSize > 0) { param->dataSize = dataSize; - param->data = new uint8_t[param->dataSize]; + param->data = new uint8_t[param->dataSize](); if (!param->data) { delete param; return; @@ -304,7 +304,7 @@ int HdcSessionBase::MallocSessionByConnectType(HSession hSession) switch (hSession->connType) { case CONN_TCP: { uv_tcp_init(&loopMain, &hSession->hWorkTCP); - hSession->uvRef++; + ++hSession->uvRef; hSession->hWorkTCP.data = hSession; break; } @@ -343,7 +343,7 @@ HSession HdcSessionBase::MallocSession(bool serverOrDaemon, const ConnType connT return nullptr; } int ret = 0; - sessionRef++; + ++sessionRef; memset_s(hSession->ctrlFd, sizeof(hSession->ctrlFd), 0, sizeof(hSession->ctrlFd)); hSession->classInstance = this; hSession->connType = connType; @@ -351,7 +351,6 @@ HSession HdcSessionBase::MallocSession(bool serverOrDaemon, const ConnType connT hSession->isDead = false; hSession->sessionId = ((sessionId == 0) ? static_cast(Base::GetRuntimeMSec()) : sessionId); hSession->serverOrDaemon = serverOrDaemon; - uv_mutex_init(&hSession->sendMutex); hSession->hWorkThread = uv_thread_self(); hSession->mapTask = new map(); hSession->listKey = new list; @@ -360,7 +359,7 @@ HSession HdcSessionBase::MallocSession(bool serverOrDaemon, const ConnType connT WRITE_LOG(LOG_DEBUG, "HdcSessionBase NewSession, sessionId:%d", hSession->sessionId); uv_tcp_init(&loopMain, &hSession->ctrlPipe[STREAM_MAIN]); - hSession->uvRef++; + ++hSession->uvRef; Base::CreateSocketPair(hSession->ctrlFd); uv_tcp_open(&hSession->ctrlPipe[STREAM_MAIN], hSession->ctrlFd[STREAM_MAIN]); uv_read_start((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], Base::AllocBufferCallback, ReadCtrlFromSession); @@ -368,7 +367,7 @@ HSession HdcSessionBase::MallocSession(bool serverOrDaemon, const ConnType connT hSession->ctrlPipe[STREAM_WORK].data = hSession; // Activate USB DAEMON's data channel, may not for use uv_tcp_init(&loopMain, &hSession->dataPipe[STREAM_MAIN]); - hSession->uvRef++; + ++hSession->uvRef; Base::CreateSocketPair(hSession->dataFd); uv_tcp_open(&hSession->dataPipe[STREAM_MAIN], hSession->dataFd[STREAM_MAIN]); hSession->dataPipe[STREAM_MAIN].data = hSession; @@ -417,10 +416,6 @@ void HdcSessionBase::FreeSessionByConnectType(HSession hSession) close(hUSB->bulkOut); hUSB->bulkOut = 0; } - if (hUSB->control > 0) { - close(hUSB->control); - hUSB->control = 0; - } #endif delete hSession->hUSB; hSession->hUSB = nullptr; @@ -435,14 +430,15 @@ void HdcSessionBase::FreeSessionFinally(uv_idle_t *handle) if (hSession->uvRef > 0) { return; } + // Notify Server or Daemon, just UI or display commandline + thisClass->NotifyInstanceSessionFree(hSession, true); // all hsession uv handle has been clear thisClass->AdminSession(OP_REMOVE, hSession->sessionId, nullptr); - hSession->mainCleared = true; - WRITE_LOG(LOG_DEBUG, "FreeSessionFinally sessionId:%d finish", hSession->sessionId); + WRITE_LOG(LOG_DEBUG, "!!!FreeSessionFinally sessionId:%d finish", hSession->sessionId); delete hSession; hSession = nullptr; // fix CodeMars SetNullAfterFree issue Base::TryCloseHandle((const uv_handle_t *)handle, Base::CloseIdleCallback); - thisClass->sessionRef--; + --thisClass->sessionRef; } // work when child-work thread finish @@ -450,7 +446,7 @@ void HdcSessionBase::FreeSessionContinue(HSession hSession) { auto closeSessionTCPHandle = [](uv_handle_t *handle) -> void { HSession hSession = (HSession)handle->data; - hSession->uvRef--; + --hSession->uvRef; Base::TryCloseHandle((uv_handle_t *)handle); }; if (CONN_TCP == hSession->connType) { @@ -462,7 +458,6 @@ void HdcSessionBase::FreeSessionContinue(HSession hSession) delete[] hSession->ioBuf; hSession->ioBuf = nullptr; } - uv_mutex_destroy(&hSession->sendMutex); Base::TryCloseHandle((uv_handle_t *)&hSession->ctrlPipe[STREAM_MAIN], closeSessionTCPHandle); Base::CloseSocketPair(hSession->ctrlFd); Base::TryCloseHandle((uv_handle_t *)&hSession->dataPipe[STREAM_MAIN], closeSessionTCPHandle); @@ -475,31 +470,18 @@ void HdcSessionBase::FreeSessionContinue(HSession hSession) Base::IdleUvTask(&loopMain, hSession, FreeSessionFinally); } -void HdcSessionBase::FreeSession(const uint32_t sessionId) +void HdcSessionBase::FreeSessionOpeate(uv_timer_t *handle) { - bool bNotTodo = true; - HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr); - if (!hSession) { - return; - } - // Unified Send to the main thread - if (hSession->hWorkThread != uv_thread_self()) { - PushAsyncMessage(hSession->sessionId, ASYNC_FREE_SESSION, nullptr, 0); + HSession hSession = (HSession)handle->data; + HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance; + if (hSession->sendRef > 0) { return; } - WRITE_LOG(LOG_DEBUG, "FreeSession sessionid:%d sendref:%u", hSession->sessionId, uint16_t(hSession->sendRef)); - while (true) { - if (hSession->sendRef || hSession->isDead) { - break; - } - bNotTodo = false; - break; - } - if (bNotTodo) { +#ifdef HDC_HOST + if (hSession->hUSB != nullptr && hSession->hUSB->transferRecv != nullptr) { return; } - hSession->isDead = true; - NotifyInstanceSessionFree(hSession); // Notify Server or Daemon, just UI or display commandline +#endif // wait workthread to free if (hSession->ctrlPipe[STREAM_WORK].loop) { auto ctrl = BuildCtrlString(SP_STOP_SESSION, 0, nullptr, 0); @@ -514,13 +496,30 @@ void HdcSessionBase::FreeSession(const uint32_t sessionId) Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback); thisClass->FreeSessionContinue(hSession); }; - uv_timer_t *ut = new uv_timer_t; - ut->data = hSession; - uv_timer_init(&loopMain, ut); - uv_timer_start(ut, callbackCheckFreeSessionContinue, 500, 3000); + Base::TimerUvTask(&thisClass->loopMain, hSession, callbackCheckFreeSessionContinue); } else { - FreeSessionContinue(hSession); + thisClass->FreeSessionContinue(hSession); + } + Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseTimerCallback); +} + +void HdcSessionBase::FreeSession(const uint32_t sessionId) +{ + HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr); + if (!hSession) { + return; } + if (hSession->hWorkThread != uv_thread_self()) { + PushAsyncMessage(hSession->sessionId, ASYNC_FREE_SESSION, nullptr, 0); + return; + } + if (hSession->isDead) { + return; + } + hSession->isDead = true; + Base::TimerUvTask(&loopMain, hSession, FreeSessionOpeate); + NotifyInstanceSessionFree(hSession, false); + WRITE_LOG(LOG_DEBUG, "FreeSession sessionid:%d sendref:%u", hSession->sessionId, uint16_t(hSession->sendRef)); } HSession HdcSessionBase::AdminSession(const uint8_t op, const uint32_t sessionId, HSession hInput) @@ -586,8 +585,7 @@ int HdcSessionBase::SendByProtocol(HSession hSession, uint8_t *bufPtr, const int return ERR_SESSION_NOFOUND; } int ret = 0; - uv_mutex_lock(&hSession->sendMutex); - hSession->sendRef++; + ++hSession->sendRef; switch (hSession->connType) { case CONN_TCP: { if (hSession->hWorkThread == uv_thread_self()) { @@ -611,97 +609,102 @@ int HdcSessionBase::SendByProtocol(HSession hSession, uint8_t *bufPtr, const int default: break; } - uv_mutex_unlock(&hSession->sendMutex); return ret; } int HdcSessionBase::Send(const uint32_t sessionId, const uint32_t channelId, const uint16_t commandFlag, - uint8_t *bufPtr, int bufLen) + const uint8_t *data, const int dataSize) { HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr); if (!hSession) { - WRITE_LOG(LOG_DEBUG, "Send to offline device, drop it,:%d", sessionId); + WRITE_LOG(LOG_DEBUG, "Send to offline device, drop it, sessionid:%d", sessionId); return ERR_SESSION_NOFOUND; } - // PayloadHead+Enc(channelId(4)+flag(2)+reserve(4)+buflen(4)+buf) - int sizeSendBuf = sizeof(PayloadHead) + 14 + bufLen; - uint8_t *sendBuf = new uint8_t[sizeSendBuf](); - if (sendBuf == nullptr) { + PayloadProtect protectBuf; // noneed convert to big-endian + protectBuf.channelId = channelId; + protectBuf.commandFlag = commandFlag; + protectBuf.checkSum = (ENABLE_IO_CHECKSUM && dataSize > 0) ? Base::CalcCheckSum(data, dataSize) : 0; + protectBuf.vCode = payloadProtectStaticVcode; + string s = SerialStruct::SerializeToString(protectBuf); + // reserve for encrypt here + // xx-encrypt + + PayloadHead payloadHead; // need convert to big-endian + Base::ZeroStruct(payloadHead); + payloadHead.flag[0] = PACKET_FLAG.at(0); + payloadHead.flag[1] = PACKET_FLAG.at(1); + payloadHead.protocolVer = VER_PROTOCOL; + payloadHead.headSize = htons(s.size()); + payloadHead.dataSize = htonl(dataSize); + int finalBufSize = sizeof(PayloadHead) + s.size() + dataSize; + uint8_t *finayBuf = new uint8_t[finalBufSize](); + if (finayBuf == nullptr) { return ERR_BUF_ALLOC; } - uint8_t *dataBuf = sendBuf + sizeof(PayloadHead); - PayloadHead *payloadHead = reinterpret_cast(sendBuf); - int ret = ERR_BUF_COPY; - while (true) { - *(uint32_t *)dataBuf = htonl(channelId); - *(uint16_t *)(dataBuf + 4) = htons(commandFlag); - if (memcpy_s(dataBuf + 10, 4, &bufLen, 4)) { + bool bufRet = false; + do { + if (memcpy_s(finayBuf, sizeof(PayloadHead), reinterpret_cast(&payloadHead), sizeof(PayloadHead))) { break; } - // clang-format off - if (bufLen > 0 && bufPtr != nullptr && - memcpy_s(dataBuf + 14, sizeSendBuf - sizeof(PayloadHead) - 14, bufPtr, bufLen)) { - break; // memcpy_s failed + if (memcpy_s(finayBuf + sizeof(PayloadHead), s.size(), + reinterpret_cast(const_cast(s.c_str())), s.size())) { + break; } - // clang-format on - int rc4BufLen = bufLen + 14; - // we can encrypt here - if (memcpy_s(payloadHead->flag, sizeof(payloadHead->flag), PACKET_FLAG.c_str(), 2)) { + if (dataSize > 0 && memcpy_s(finayBuf + sizeof(PayloadHead) + s.size(), dataSize, data, dataSize)) { break; } - payloadHead->protocolVer = VER_PROTOCOL; - payloadHead->dataSize = htonl(rc4BufLen); - ret = SendByProtocol(hSession, sendBuf, sizeSendBuf); - break; + bufRet = true; + } while (false); + if (!bufRet) { + delete[] finayBuf; + return ERR_BUF_COPY; } - // sendBuf free by SendByProtocol - return ret; + return SendByProtocol(hSession, finayBuf, finalBufSize); } -int HdcSessionBase::DecryptPayload(HSession hSession, uint8_t *pEncryptBuf, const int bufLen) +int HdcSessionBase::DecryptPayload(HSession hSession, PayloadHead *payloadHeadBe, uint8_t *encBuf) { - // we can decrypt here - uint32_t channelId = ntohl(*(uint32_t *)pEncryptBuf); - uint16_t flag = ntohs(*(uint16_t *)(pEncryptBuf + 4)); - int payloadSize = *(int *)(pEncryptBuf + 10); - if (payloadSize < 0 || (uint32_t)payloadSize > HDC_BUF_MAX_BYTES) { - WRITE_LOG(LOG_WARN, "DecryptPayload failed"); - return -1; + PayloadProtect protectBuf; + Base::ZeroStruct(protectBuf); + uint16_t headSize = ntohs(payloadHeadBe->headSize); + int dataSize = ntohl(payloadHeadBe->dataSize); + string encString(reinterpret_cast(encBuf), headSize); + SerialStruct::ParseFromString(protectBuf, encString); + if (protectBuf.vCode != payloadProtectStaticVcode) { + WRITE_LOG(LOG_FATAL, "Session recv static vcode failed"); + return ERR_BUF_CHECK; } - uint8_t *payload = nullptr; - if (payloadSize) { - payload = pEncryptBuf + 14; + uint8_t *data = encBuf + headSize; + if (protectBuf.checkSum != 0 && (protectBuf.checkSum != Base::CalcCheckSum(data, dataSize))) { + WRITE_LOG(LOG_FATAL, "Session recv CalcCheckSum failed"); + return ERR_BUF_CHECK; } - if (!FetchCommand(hSession, channelId, flag, payload, payloadSize)) { + if (!FetchCommand(hSession, protectBuf.channelId, protectBuf.commandFlag, data, dataSize)) { WRITE_LOG(LOG_WARN, "FetchCommand failed"); - return -2; + return ERR_GENERIC; } - return 0; + return ERR_SUCCESS; } int HdcSessionBase::OnRead(HSession hSession, uint8_t *bufPtr, const int bufLen) { - int ret = -3; - if (bufLen == 0) { - return 0; // buf end - } + int ret = ERR_GENERIC; if (memcmp(bufPtr, PACKET_FLAG.c_str(), 2)) { - return -1; + return ERR_BUF_CHECK; } struct PayloadHead *payloadHead = (struct PayloadHead *)bufPtr; - int tobeReadLen = ntohl(payloadHead->dataSize); + int tobeReadLen = ntohl(payloadHead->dataSize) + ntohs(payloadHead->headSize); int packetHeadSize = sizeof(struct PayloadHead); if (tobeReadLen <= 0 || (uint32_t)tobeReadLen > HDC_BUF_MAX_BYTES) { // max 1G - return -2; + return ERR_BUF_CHECK; } if (bufLen - packetHeadSize < tobeReadLen) { return 0; } - if (DecryptPayload(hSession, bufPtr + packetHeadSize, tobeReadLen)) { - return -3; + if (DecryptPayload(hSession, payloadHead, bufPtr + packetHeadSize)) { + return ERR_BUF_CHECK; } - ret = packetHeadSize + tobeReadLen; return ret; } @@ -752,14 +755,14 @@ void HdcSessionBase::AllocCallback(uv_handle_t *handle, size_t sizeWanted, uv_bu void HdcSessionBase::FinishWriteSessionTCP(uv_write_t *req, int status) { HSession hSession = (HSession)req->handle->data; - hSession->sendRef--; + --hSession->sendRef; HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance; if (status < 0) { Base::TryCloseHandle((uv_handle_t *)req->handle); - } - if (hSession->isDead && !hSession->sendRef) { - WRITE_LOG(LOG_DEBUG, "FinishWriteSessionTCP willfreesn :%p", hSession); - thisClass->FreeSession(hSession->sessionId); + if (!hSession->isDead && !hSession->sendRef) { + WRITE_LOG(LOG_DEBUG, "FinishWriteSessionTCP freesession :%p", hSession); + thisClass->FreeSession(hSession->sessionId); + } } delete[]((uint8_t *)req->data); delete req; @@ -816,7 +819,7 @@ bool HdcSessionBase::WorkThreadStartSession(HSession hSession) WRITE_LOG(LOG_DEBUG, "HdcSessionBase SessionCtrl failed 1"); return false; } - if ((childRet = uv_tcp_open(&hSession->hChildWorkTCP, (uv_os_sock_t)hSession->fdChildWorkTCP)) < 0) { + if ((childRet = uv_tcp_open(&hSession->hChildWorkTCP, hSession->fdChildWorkTCP)) < 0) { WRITE_LOG(LOG_DEBUG, "SessionCtrl failed 2,fd:%d,str:%s", hSession->fdChildWorkTCP, uv_strerror(childRet)); return false; } @@ -841,8 +844,8 @@ bool HdcSessionBase::WorkThreadStartSession(HSession hSession) return true; } -vector HdcSessionBase::BuildCtrlString(InnerCtrlCommand command, uint32_t channelId, - const uint8_t *data, int dataSize) +vector HdcSessionBase::BuildCtrlString(InnerCtrlCommand command, uint32_t channelId, uint8_t *data, + int dataSize) { vector ret; while (true) { @@ -882,13 +885,6 @@ bool HdcSessionBase::DispatchMainThreadCommand(HSession hSession, const CtrlStru uv_stop(&hSession->childLoop); break; } - case SP_REGISTER_CHANNEL: { - if (!serverOrDaemon) { - break; // Only Server has this feature - } - RegisterChannel(hSession, channelId); - break; - } case SP_ATTACH_CHANNEL: { if (!serverOrDaemon) { break; // Only Server has this feature diff --git a/src/common/session.h b/src/common/session.h old mode 100755 new mode 100644 index 6279f842ee3d5da1ac944afcc1f872928e3dbbe3..c91fa7573228adcaea6a63ae9c4383604f200fcd --- a/src/common/session.h +++ b/src/common/session.h @@ -36,9 +36,15 @@ public: uint8_t dataSize; uint8_t data[BUF_SIZE_MICRO]; }; + struct PayloadProtect { // reserve for encrypt and decrypt + uint32_t channelId; + uint32_t commandFlag; + uint8_t checkSum; // enable it will be lose about 20% speed + uint8_t vCode; + }; + HdcSessionBase(bool serverOrDaemonIn); virtual ~HdcSessionBase(); - virtual void RegisterChannel(HSession hSession, const uint32_t channelId) {}; virtual void AttachChannel(HSession hSession, const uint32_t channelId) {}; virtual void DeatchChannel(const uint32_t channelId) {}; virtual bool RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, @@ -46,7 +52,7 @@ public: { return true; } - virtual void NotifyInstanceSessionFree(HSession hSession) + virtual void NotifyInstanceSessionFree(HSession hSession, bool freeOrClear) { } void ReMainLoopForInstanceClear(); @@ -63,8 +69,8 @@ public: void FreeSession(const uint32_t sessionId); void WorkerPendding(); int OnRead(HSession hSession, uint8_t *bufPtr, const int bufLen); - int Send(const uint32_t sessionId, const uint32_t channelId, const uint16_t commandFlag, uint8_t *bufPtr, - const int bufLen); + int Send(const uint32_t sessionId, const uint32_t channelId, const uint16_t commandFlag, const uint8_t *data, + const int dataSize); int SendByProtocol(HSession hSession, uint8_t *bufPtr, const int bufLen); HSession AdminSession(const uint8_t op, const uint32_t sessionId, HSession hInput); int FetchIOBuf(HSession hSession, uint8_t *ioBuf, int read); @@ -92,8 +98,7 @@ public: { return wantRestart; } - static vector BuildCtrlString(InnerCtrlCommand command, uint32_t channelId, - const uint8_t *data, int dataSize); + static vector BuildCtrlString(InnerCtrlCommand command, uint32_t channelId, uint8_t *data, int dataSize); uv_loop_t loopMain; bool serverOrDaemon; uv_async_t asyncMainLoop; @@ -104,11 +109,11 @@ public: protected: struct PayloadHead { uint8_t flag[2]; - uint8_t reserve[2]; + uint8_t reserve[2]; // encrypt'flag or others options uint8_t protocolVer; + uint16_t headSize; uint32_t dataSize; } __attribute__((packed)); - void ClearSessions(); virtual void JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO) { @@ -150,7 +155,7 @@ private: virtual void ClearInstanceResource() { } - int DecryptPayload(HSession hSession, uint8_t *pEncryptBuf, const int bufLen); + int DecryptPayload(HSession hSession, PayloadHead *payloadHeadBe, uint8_t *encBuf); bool DispatchMainThreadCommand(HSession hSession, const CtrlStruct *ctrl); bool DispatchSessionThreadCommand(uv_stream_t *uvpipe, HSession hSession, const uint8_t *baseBuf, const int bytesIO); @@ -160,6 +165,7 @@ private: void FreeSessionContinue(HSession hSession); static void FreeSessionFinally(uv_idle_t *handle); static void AsyncMainLoopTask(uv_idle_t *handle); + static void FreeSessionOpeate(uv_timer_t *handle); int MallocSessionByConnectType(HSession hSession); void FreeSessionByConnectType(HSession hSession); bool WorkThreadStartSession(HSession hSession); @@ -167,6 +173,7 @@ private: map mapSession; uv_rwlock_t lockMapSession; std::atomic sessionRef = 0; + const uint8_t payloadProtectStaticVcode = 0x09; }; } // namespace Hdc #endif \ No newline at end of file diff --git a/src/common/task.cpp b/src/common/task.cpp old mode 100755 new mode 100644 diff --git a/src/common/task.h b/src/common/task.h old mode 100755 new mode 100644 diff --git a/src/common/tcp.cpp b/src/common/tcp.cpp old mode 100755 new mode 100644 diff --git a/src/common/tcp.h b/src/common/tcp.h old mode 100755 new mode 100644 diff --git a/src/common/transfer.cpp b/src/common/transfer.cpp old mode 100755 new mode 100644 index 3b8e99e853592097a17d262b6e71849c84898cf2..00f01892ced1996d4be21a57b58706bfa8ebd141 --- a/src/common/transfer.cpp +++ b/src/common/transfer.cpp @@ -67,7 +67,7 @@ int HdcTransferBase::SimpleFileIO(CtxFile *context, uint64_t index, uint8_t *sen ioContext->bufIO = buf; ioContext->context = context; req->data = ioContext; - refCount++; + ++refCount; if (context->master) { // master just read, and slave just write.when master/read, sendBuf can be nullptr uv_buf_t iov = uv_buf_init(reinterpret_cast(buf), bytes); uv_fs_read(context->loop, req, context->fsOpenReq.result, &iov, 1, index, context->cb); @@ -110,7 +110,7 @@ void HdcTransferBase::OnFileClose(uv_fs_t *req) // close-step2 thisClass->WhenTransferFinish(context); } - thisClass->refCount--; + --thisClass->refCount; return; } @@ -173,9 +173,9 @@ bool HdcTransferBase::SendIOPayload(CtxFile *context, int index, uint8_t *data, delete[] sendBuf; return false; } - SendToAnother(commandData, sendBuf, payloadPrefixReserve + compressSize); + bool ret = SendToAnother(commandData, sendBuf, payloadPrefixReserve + compressSize) > 0; delete[] sendBuf; - return true; + return ret; } void HdcTransferBase::OnFileIO(uv_fs_t *req) @@ -186,7 +186,7 @@ void HdcTransferBase::OnFileIO(uv_fs_t *req) HdcTransferBase *thisClass = (HdcTransferBase *)context->thisClass; uint8_t *bufIO = contextIO->bufIO; uv_fs_req_cleanup(req); - thisClass->refCount--; + --thisClass->refCount; while (true) { if (req->result <= 0) { // Read error or master read completion tryFinishIO = true; @@ -222,7 +222,7 @@ void HdcTransferBase::OnFileIO(uv_fs_t *req) delete contextIO; // Req is part of the Contextio structure, no free release if (tryFinishIO) { // close-step1 - thisClass->refCount++; + ++thisClass->refCount; uv_fs_close(thisClass->loopTask, &context->fsCloseReq, context->fsOpenReq.result, OnFileClose); } } @@ -232,7 +232,7 @@ void HdcTransferBase::OnFileOpen(uv_fs_t *req) CtxFile *context = (CtxFile *)req->data; HdcTransferBase *thisClass = (HdcTransferBase *)context->thisClass; uv_fs_req_cleanup(req); - thisClass->refCount--; + --thisClass->refCount; if (req->result < 0) { thisClass->LogMsg(MSG_FAIL, "Error opening file: %s, path:%s", uv_strerror((int)req->result), context->localPath.c_str()); @@ -304,7 +304,7 @@ int HdcTransferBase::GetSubFiles(const char *path, string filter, vector string fullPath = string(path) + "/"; fullPath += fileName; out->push_back(fullPath); - retNum++; + ++retNum; } } uv_fs_req_cleanup(&req); @@ -323,7 +323,6 @@ bool HdcTransferBase::SmartSlavePath(string &localPath, const char *optName) uv_fs_req_cleanup(&req); if (r == 0 && req.statbuf.st_mode & S_IFDIR) { // is dir localPath = Base::StringFormat("%s%c%s", localPath.c_str(), fs::path::preferred_separator, optName); - return false; } return false; } diff --git a/src/common/transfer.h b/src/common/transfer.h old mode 100755 new mode 100644 diff --git a/src/common/usb.cpp b/src/common/usb.cpp old mode 100755 new mode 100644 index 9bf5bdf58bd8ff7806b472d9df81a4783c8abb95..3cc4a6052ee95da06676b1713d5c50e956b3b843 --- a/src/common/usb.cpp +++ b/src/common/usb.cpp @@ -72,7 +72,7 @@ int HdcUSBBase::SendUSBBlock(HSession hSession, uint8_t *data, const int length) if (!ioBuf) { return ERR_BUF_ALLOC; } - for (i = 0; i < iCount; i++) { + for (i = 0; i < iCount; ++i) { USBHead *pUSBHead = (USBHead *)ioBuf; int errCode = memcpy_s(pUSBHead->flag, sizeof(pUSBHead->flag), PACKET_FLAG.c_str(), 2); if (errCode != EOK) { diff --git a/src/common/usb.h b/src/common/usb.h old mode 100755 new mode 100644 diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp old mode 100755 new mode 100644 index 1a48f0fa6288408c98183fe522932dccca720458..1b146677cdff973242dd19a4657aac6724ff2732 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -268,7 +268,7 @@ bool HdcDaemon::FetchCommand(HSession hSession, const uint32_t channelId, const case CMD_KERNEL_CHANNEL_CLOSE: { // Daemon is only cleaning up the Channel task ClearOwnTasks(hSession, channelId); if (*payload) { - (*payload)--; + --(*payload); Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1); } ret = true; diff --git a/src/daemon/daemon.h b/src/daemon/daemon.h old mode 100755 new mode 100644 diff --git a/src/daemon/daemon_app.cpp b/src/daemon/daemon_app.cpp old mode 100755 new mode 100644 index b6c83439726c509bde23988ecf4b32bb81d048fa..94e680ac298dd9b25907f390283f7400c1610990 --- a/src/daemon/daemon_app.cpp +++ b/src/daemon/daemon_app.cpp @@ -71,7 +71,7 @@ bool HdcDaemonApp::CommandDispatch(const uint16_t command, uint8_t *payload, con ctxNow.localPath = dstPath; ctxNow.transferBegin = Base::GetRuntimeMSec(); ctxNow.fileSize = ctxNow.transferConfig.fileSize; - refCount++; + ++refCount; uv_fs_open(loopTask, &ctxNow.fsOpenReq, ctxNow.localPath.c_str(), UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IRUSR, OnFileOpen); break; @@ -100,12 +100,12 @@ void HdcDaemonApp::AsyncInstallFinish(bool runOK, const string result) vecBuf.push_back(runOK); 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--; + --refCount; } void HdcDaemonApp::PackageShell(bool installOrUninstall, const char *options, const char *package) { - refCount++; + ++refCount; // asynccmd Other processes, no RunningProtect protection chmod(package, 0644); string doBuf; diff --git a/src/daemon/daemon_app.h b/src/daemon/daemon_app.h old mode 100755 new mode 100644 diff --git a/src/daemon/daemon_common.h b/src/daemon/daemon_common.h old mode 100755 new mode 100644 diff --git a/src/daemon/daemon_forward.cpp b/src/daemon/daemon_forward.cpp old mode 100755 new mode 100644 index 39d5bd7d553fc03ab5aec1f47fef5c5ac4d32d41..cf00aa3df2bea793120be897dab17169a57a41dc --- a/src/daemon/daemon_forward.cpp +++ b/src/daemon/daemon_forward.cpp @@ -31,7 +31,7 @@ void HdcDaemonForward::SetupJdwpPointCallBack(uv_idle_t *handle) thisClass->SetupPointContinue(ctxPoint, 1); // It usually works Base::TryCloseHandle((const uv_handle_t *)handle, Base::CloseIdleCallback); WRITE_LOG(LOG_DEBUG, "Setup JdwpPointCallBack finish"); - thisClass->refCount--; + --thisClass->refCount; return; } @@ -49,7 +49,7 @@ bool HdcDaemonForward::SetupJdwpPoint(HCtxForward ctxPoint) // do slave connect // fd[0] for forward, fd[1] for jdwp // forward to close fd[0], fd[1] for jdwp close - int fds[2] = {0}; + int fds[2] = { 0 }; bool ret = false; Base::CreateSocketPair(fds); if (uv_tcp_init(loopTask, &ctxPoint->tcp)) { @@ -73,7 +73,7 @@ bool HdcDaemonForward::SetupJdwpPoint(HCtxForward ctxPoint) return ret; } - refCount++; + ++refCount; Base::IdleUvTask(loopTask, ctxPoint, SetupJdwpPointCallBack); return ret; } diff --git a/src/daemon/daemon_forward.h b/src/daemon/daemon_forward.h old mode 100755 new mode 100644 diff --git a/src/daemon/daemon_tcp.cpp b/src/daemon/daemon_tcp.cpp old mode 100755 new mode 100644 index 8b3de8e3993abb5fc351903bc48f72fc69c2d291..d1031074498cc42a183124079d2b7f406c45e7d5 --- a/src/daemon/daemon_tcp.cpp +++ b/src/daemon/daemon_tcp.cpp @@ -67,6 +67,7 @@ void HdcDaemonTCP::AcceptClient(uv_stream_t *server, int status) HdcDaemonTCP *thisClass = (HdcDaemonTCP *)pServTCP->data; HdcSessionBase *ptrConnect = (HdcSessionBase *)thisClass->clsMainBase; HdcSessionBase *daemon = reinterpret_cast(thisClass->clsMainBase); + const uint16_t maxWaitTime = 250; auto ctrl = daemon->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0); HSession hSession = ptrConnect->MallocSession(false, CONN_TCP, thisClass); if (!hSession) { @@ -75,19 +76,16 @@ void HdcDaemonTCP::AcceptClient(uv_stream_t *server, int status) if (uv_accept(server, (uv_stream_t *)&hSession->hWorkTCP) < 0) { goto Finish; } + if ((hSession->fdChildWorkTCP = Base::DuplicateUvSocket(&hSession->hWorkTCP)) < 0) { + goto Finish; + }; + uv_read_stop((uv_stream_t *)&hSession->hWorkTCP); Base::SetTcpOptions(&hSession->hWorkTCP); Base::StartWorkThread(ptrLoop, ptrConnect->SessionWorkThread, Base::FinishWorkThread, hSession); // wait for thread up while (hSession->childLoop.active_handles == 0) { - usleep(1000); - } - if (uv_fileno((const uv_handle_t *)&hSession->hWorkTCP, &hSession->fdChildWorkTCP) < 0) { - goto Finish; + usleep(maxWaitTime); } -#ifdef UNIT_TEST - hSession->fdChildWorkTCP = dup(hSession->fdChildWorkTCP); -#endif - uv_read_stop((uv_stream_t *)&hSession->hWorkTCP); Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); return; Finish: diff --git a/src/daemon/daemon_tcp.h b/src/daemon/daemon_tcp.h old mode 100755 new mode 100644 diff --git a/src/daemon/daemon_unity.cpp b/src/daemon/daemon_unity.cpp old mode 100755 new mode 100644 index 434a6d1bf48a48a296dafd1694cbce4b7274146d..d30b8ecfa665722cde8f32f6af00fe2e6f10eaf8 --- a/src/daemon/daemon_unity.cpp +++ b/src/daemon/daemon_unity.cpp @@ -59,7 +59,7 @@ void HdcDaemonUnity::OnFdRead(uv_fs_t *req) CtxUnityIO *ctxIO = static_cast(req->data); ContextUnity *ctx = static_cast(ctxIO->context); HdcDaemonUnity *thisClass = ctx->thisClass; - thisClass->refCount--; + --thisClass->refCount; uint8_t *buf = ctxIO->bufIO; bool readContinue = false; while (true) { @@ -109,7 +109,7 @@ int HdcDaemonUnity::LoopFdRead(ContextUnity *ctx) contextIO->bufIO = buf; contextIO->context = ctx; req->data = contextIO; - refCount++; + ++refCount; iov = uv_buf_init((char *)buf, readMax); uv_fs_read(loopTask, req, ctx->fd, &iov, 1, -1, OnFdRead); diff --git a/src/daemon/daemon_unity.h b/src/daemon/daemon_unity.h old mode 100755 new mode 100644 diff --git a/src/daemon/daemon_usb.cpp b/src/daemon/daemon_usb.cpp old mode 100755 new mode 100644 index 21ab130a6f33e3e248190bb00a51b733d48f29eb..71d0d36a53e4d1ea453d35173f06e370ea3a692a --- a/src/daemon/daemon_usb.cpp +++ b/src/daemon/daemon_usb.cpp @@ -19,15 +19,17 @@ namespace Hdc { HdcDaemonUSB::HdcDaemonUSB(const bool serverOrDaemonIn, void *ptrMainBase) : HdcUSBBase(serverOrDaemonIn, ptrMainBase) { - usbMain = nullptr; Base::ZeroStruct(sendEP); uv_mutex_init(&sendEP); } HdcDaemonUSB::~HdcDaemonUSB() { - // Closed in the IO loop, no longer closing CLOSEENDPOINT + // Closed in the IO loop, no longer closing CLOSE ENDPOINT uv_mutex_destroy(&sendEP); + if (controlEp > 0) { + close(controlEp); + } } void HdcDaemonUSB::Stop() @@ -36,19 +38,10 @@ void HdcDaemonUSB::Stop() // Here only clean up the IO-related resources, session related resources clear reason to clean up the session // module modRunning = false; - if (!usbMain) { - return; - } WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB Stop free main session"); - HdcDaemon *daemon = (HdcDaemon *)clsMainBase; Base::TryCloseHandle((uv_handle_t *)&checkEP); - daemon->FreeSession(usbMain->sessionId); - if (usbMain->hUSB != nullptr) { - CloseEndpoint(usbMain->hUSB); - } + CloseEndpoint(&usbHandle); WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB Stop free main session finish"); - usbMain = nullptr; - // workaround for sendEP mutex only } int HdcDaemonUSB::Initial() @@ -61,13 +54,8 @@ int HdcDaemonUSB::Initial() WRITE_LOG(LOG_DEBUG, "Just support usb-ffs, must kernel3.8+ and enable usb-ffs, usbmod disable"); return -1; } - const uint16_t usbFfsScanInterval = 3000; + const uint16_t usbFfsScanInterval = 1500; HdcDaemon *daemon = (HdcDaemon *)clsMainBase; - usbMain = daemon->MallocSession(false, CONN_USB, this); - if (!usbMain) { - WRITE_LOG(LOG_DEBUG, "CheckNewUSBDeviceThread malloc failed"); - return -1; - } WRITE_LOG(LOG_DEBUG, "HdcDaemonUSB::Initiall"); uv_timer_init(&daemon->loopMain, &checkEP); checkEP.data = this; @@ -78,23 +66,22 @@ int HdcDaemonUSB::Initial() // DAEMON end USB module USB-FFS EP port connection int HdcDaemonUSB::ConnectEPPoint(HUSB hUSB) { - int ret = -1; + int ret = ERR_GENERIC; while (true) { - if (!hUSB->control) { + if (controlEp <= 0) { // After the control port sends the instruction, the device is initialized by the device to the HOST host, // which can be found for USB devices. Do not send initialization to the EP0 control port, the USB // device will not be initialized by Host - WRITE_LOG(LOG_DEBUG, "enter ConnectEPPoint"); WRITE_LOG(LOG_DEBUG, "Begin send to control(EP0) for usb descriptor init"); - if ((hUSB->control = open(USB_FFS_HDC_EP0, O_RDWR)) < 0) { + if ((controlEp = open(USB_FFS_HDC_EP0, O_RDWR)) < 0) { WRITE_LOG(LOG_WARN, "%s: cannot open control endpoint: errno=%d", USB_FFS_HDC_EP0, errno); break; } - if (write(hUSB->control, &USB_FFS_DESC, sizeof(USB_FFS_DESC)) < 0) { + 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); break; } - if (write(hUSB->control, &USB_FFS_VALUE, sizeof(USB_FFS_VALUE)) < 0) { + if (write(controlEp, &USB_FFS_VALUE, sizeof(USB_FFS_VALUE)) < 0) { WRITE_LOG(LOG_WARN, "%s: write USB_FFS_VALUE failed: errno=%d", USB_FFS_HDC_EP0, errno); break; } @@ -102,6 +89,7 @@ int HdcDaemonUSB::ConnectEPPoint(HUSB hUSB) Base::SetHdcProperty("sys.usb.ffs.ready", "1"); WRITE_LOG(LOG_DEBUG, "ConnectEPPoint ctrl init finish, set usb-ffs ready"); } + if ((hUSB->bulkOut = open(USB_FFS_HDC_OUT, O_RDWR)) < 0) { WRITE_LOG(LOG_WARN, "%s: cannot open bulk-out ep: errno=%d", USB_FFS_HDC_OUT, errno); break; @@ -110,22 +98,24 @@ int HdcDaemonUSB::ConnectEPPoint(HUSB hUSB) WRITE_LOG(LOG_WARN, "%s: cannot open bulk-in ep: errno=%d", USB_FFS_HDC_IN, errno); break; } - int flags = fcntl(hUSB->bulkIn, F_GETFL, 0); - fcntl(hUSB->bulkIn, flags | O_NONBLOCK); - ret = 0; + // cannot open with O_CLOEXEC, must fcntl + fcntl(controlEp, F_SETFD, FD_CLOEXEC); + fcntl(hUSB->bulkOut, F_SETFD, FD_CLOEXEC); + fcntl(hUSB->bulkIn, F_SETFD, FD_CLOEXEC); + + WRITE_LOG(LOG_DEBUG, "New bulk in\\out open bulkout:%d bulkin:%d", hUSB->bulkOut, hUSB->bulkIn); + hUSB->bufRecv.clear(); + ret = ERR_SUCCESS; break; } - if (ret < 0) { - CloseEndpoint(hUSB); + if (ret != ERR_SUCCESS) { + CloseEndpoint(hUSB, true); } return ret; } -void HdcDaemonUSB::CloseEndpoint(HUSB hUSB) +void HdcDaemonUSB::CloseEndpoint(HUSB hUSB, bool closeCtrlEp) { - if (!isAlive) { - return; - } if (hUSB->bulkIn > 0) { close(hUSB->bulkIn); hUSB->bulkIn = 0; @@ -134,12 +124,12 @@ void HdcDaemonUSB::CloseEndpoint(HUSB hUSB) close(hUSB->bulkOut); hUSB->bulkOut = 0; } - if (hUSB->control > 0) { - close(hUSB->control); - hUSB->control = 0; + if (controlEp > 0 && closeCtrlEp) { + close(controlEp); + controlEp = 0; } isAlive = false; - WRITE_LOG(LOG_FATAL, "DaemonUSB CloseEndpoint"); + WRITE_LOG(LOG_FATAL, "DaemonUSB close endpoint"); } // Prevent other USB data misfortunes to send the program crash @@ -176,18 +166,40 @@ bool HdcDaemonUSB::ReadyForWorkThread(HSession hSession) return true; }; -// daemon, usb-ffs data sends a critical function -// The speed of sending is too fast, IO will cause memory stacking, temporarily do not use asynchronous +int HdcDaemonUSB::CloseBulkEp(bool bulkInOut, int bulkFd, uv_loop_t *loop) +{ + struct CtxCloseBulkEp { + uv_fs_t req; + HdcDaemonUSB *thisClass; + bool bulkInOut; + }; + CtxCloseBulkEp *ctx = new CtxCloseBulkEp(); + uv_fs_t *req = &ctx->req; + req->data = ctx; + ctx->bulkInOut = bulkInOut; + ctx->thisClass = this; + isAlive = false; + uv_fs_close(loop, req, bulkFd, [](uv_fs_t *req) { + auto ctx = (CtxCloseBulkEp *)req->data; + if (ctx->bulkInOut) { + ctx->thisClass->usbHandle.bulkIn = 0; + } else { + ctx->thisClass->usbHandle.bulkOut = 0; + } + WRITE_LOG(LOG_DEBUG, "Try to abort blukin write callback %s", ctx->bulkInOut ? "bulkin" : "bulkout"); + uv_fs_req_cleanup(req); + delete ctx; + }); + return 0; +} + int HdcDaemonUSB::SendUSBIOSync(HSession hSession, HUSB hMainUSB, uint8_t *data, const int length) { int bulkIn = hMainUSB->bulkIn; int childRet = 0; int ret = -1; int offset = 0; - if (!isAlive) { - goto Finish; - } - if (!modRunning) { + if (!isAlive || !modRunning) { goto Finish; } while (modRunning && !hSession->isDead) { @@ -217,10 +229,9 @@ Finish: if (pUSBHead->option & USB_OPTION_TAIL) { hSession->sendRef--; } - if (ret < 0 && isAlive) { + if (ret < 0) { WRITE_LOG(LOG_FATAL, "BulkinWrite CloseEndpoint"); - // It actually closed the subsession, the EP port is also closed - CloseEndpoint(hMainUSB); + isAlive = false; } return ret; } @@ -235,7 +246,7 @@ int HdcDaemonUSB::SendUSBRaw(HSession hSession, uint8_t *data, const int length) // it can be used exclusive File-DESC transmission mode in each thread. The late stage can be used as asynchronous + // SendPipe to the main thread transmission. uv_mutex_lock(&sendEP); - int ret = SendUSBIOSync(hSession, usbMain->hUSB, data, length); + int ret = SendUSBIOSync(hSession, &usbHandle, data, length); if (ret < 0) { daemon->FreeSession(hSession->sessionId); WRITE_LOG(LOG_DEBUG, "SendUSBRaw try to freesession"); @@ -253,7 +264,6 @@ void HdcDaemonUSB::OnNewHandshakeOK(const uint32_t sessionId) HSession HdcDaemonUSB::PrepareNewSession(uint32_t sessionId, uint8_t *pRecvBuf, int recvBytesIO) { HdcDaemon *daemon = reinterpret_cast(clsMainBase); - // new session HSession hChildSession = daemon->MallocSession(false, CONN_USB, this, sessionId); if (!hChildSession) { return nullptr; @@ -282,12 +292,12 @@ HSession HdcDaemonUSB::PrepareNewSession(uint32_t sessionId, uint8_t *pRecvBuf, return hChildSession; } -int HdcDaemonUSB::DispatchToWorkThread(HSession hSession, const uint32_t sessionId, uint8_t *readBuf, int readBytes) +int HdcDaemonUSB::DispatchToWorkThread(const uint32_t sessionId, uint8_t *readBuf, int readBytes) { // Format:USBPacket1 payload1...USBPacketn // payloadn-[USBHead1(PayloadHead1+Payload1)]+[USBHead2(Payload2)]+...+[USBHeadN(PayloadN)] HSession hChildSession = nullptr; - HdcDaemon *daemon = reinterpret_cast(hSession->classInstance); + HdcDaemon *daemon = reinterpret_cast(clsMainBase); hChildSession = daemon->AdminSession(OP_QUERY, sessionId, nullptr); if (!hChildSession) { hChildSession = PrepareNewSession(sessionId, readBuf, readBytes); @@ -295,8 +305,8 @@ int HdcDaemonUSB::DispatchToWorkThread(HSession hSession, const uint32_t session return ERR_SESSION_NOFOUND; } } - if (!SendToHdcStream(hChildSession, reinterpret_cast(&hChildSession->dataPipe[STREAM_MAIN]), - readBuf, readBytes)) { + if (!SendToHdcStream(hChildSession, reinterpret_cast(&hChildSession->dataPipe[STREAM_MAIN]), readBuf, + readBytes)) { return ERR_IO_FAIL; } return readBytes; @@ -318,13 +328,13 @@ bool HdcDaemonUSB::JumpAntiquePacket(const uint8_t &buf, ssize_t bytes) const void HdcDaemonUSB::OnUSBRead(uv_fs_t *req) { // Only read at the main thread auto ctxIo = reinterpret_cast(req->data); - auto hSession = reinterpret_cast(ctxIo->data); + auto hUSB = reinterpret_cast(ctxIo->data); auto thisClass = reinterpret_cast(ctxIo->thisClass); uint8_t *bufPtr = ctxIo->buf; ssize_t bytesIOBytes = req->result; uint32_t sessionId = 0; bool ret = false; - while (true) { + while (thisClass->isAlive) { // Don't care is module running, first deal with this if (bytesIOBytes < 0) { WRITE_LOG(LOG_WARN, "USBIO failed1 %s", uv_strerror(bytesIOBytes)); @@ -340,29 +350,29 @@ void HdcDaemonUSB::OnUSBRead(uv_fs_t *req) WRITE_LOG(LOG_WARN, "AvailablePacket check failed, ret:%d buf:%-50s", bytesIOBytes, bufPtr); break; } - if (thisClass->DispatchToWorkThread(hSession, sessionId, bufPtr, bytesIOBytes) < 0) { + // can debug payload here + if (thisClass->DispatchToWorkThread(sessionId, bufPtr, bytesIOBytes) < 0) { WRITE_LOG(LOG_FATAL, "DispatchToWorkThread failed"); break; } - if (thisClass->LoopUSBRead(hSession) < 0) { + if (thisClass->LoopUSBRead(hUSB) < 0) { WRITE_LOG(LOG_FATAL, "LoopUSBRead failed"); break; } ret = true; break; } + if (!ret) { + thisClass->isAlive = false; + } delete[] ctxIo->buf; uv_fs_req_cleanup(req); delete ctxIo; - if (!ret || !thisClass->modRunning) { - thisClass->CloseEndpoint(hSession->hUSB); - } } -int HdcDaemonUSB::LoopUSBRead(HSession hSession) +int HdcDaemonUSB::LoopUSBRead(HUSB hUSB) { int ret = -1; - HUSB hUSB = hSession->hUSB; HdcDaemon *daemon = reinterpret_cast(clsMainBase); // must > available size, or it will be incorrect int readMax = Base::GetMaxBufSize() + sizeof(USBHead) + EXTRA_ALLOC_SIZE; @@ -375,7 +385,7 @@ int HdcDaemonUSB::LoopUSBRead(HSession hSession) } ctxIo->buf = buf; ctxIo->bufSize = readMax; - ctxIo->data = hSession; + ctxIo->data = hUSB; ctxIo->thisClass = this; req = &ctxIo->req; req->data = ctxIo; @@ -400,15 +410,35 @@ FAILED: void HdcDaemonUSB::WatchEPTimer(uv_timer_t *handle) { HdcDaemonUSB *thisClass = (HdcDaemonUSB *)handle->data; - HUSB hUSB = thisClass->usbMain->hUSB; - if (thisClass->isAlive) { - return; // ok not todo... + HUSB hUSB = &thisClass->usbHandle; + HdcDaemon *daemon = reinterpret_cast(thisClass->clsMainBase); + if (thisClass->isAlive || thisClass->ref > 0) { + return; + } + bool resetEp = false; + do { + if (hUSB->bulkIn > 0) { + thisClass->CloseBulkEp(true, thisClass->usbHandle.bulkIn, &daemon->loopMain); + resetEp = true; + } + if (hUSB->bulkOut > 0) { + thisClass->CloseBulkEp(false, thisClass->usbHandle.bulkOut, &daemon->loopMain); + resetEp = true; + } + if (thisClass->controlEp > 0) { + close(thisClass->controlEp); + thisClass->controlEp = 0; + resetEp = true; + } + } while (false); + if (resetEp) { + return; } - if (thisClass->ConnectEPPoint(hUSB)) { + if (thisClass->ConnectEPPoint(hUSB) != ERR_SUCCESS) { return; } // connect OK thisClass->isAlive = true; - thisClass->LoopUSBRead(thisClass->usbMain); + thisClass->LoopUSBRead(hUSB); } } // namespace Hdc \ No newline at end of file diff --git a/src/daemon/daemon_usb.h b/src/daemon/daemon_usb.h old mode 100755 new mode 100644 index e249b23985bf26b1da8ce2f11e19249b7a55486c..a79c04b1c02506a38f969eca081bb516c63c843d --- a/src/daemon/daemon_usb.h +++ b/src/daemon/daemon_usb.h @@ -37,21 +37,23 @@ private: static void OnUSBRead(uv_fs_t *req); static void WatchEPTimer(uv_timer_t *handle); int ConnectEPPoint(HUSB hUSB); - int DispatchToWorkThread(HSession hSession, const uint32_t sessionId, uint8_t *readBuf, int readBytes); + int DispatchToWorkThread(const uint32_t sessionId, uint8_t *readBuf, int readBytes); bool AvailablePacket(uint8_t *ioBuf, uint32_t *sessionId); - void CloseEndpoint(HUSB hUSB); + void CloseEndpoint(HUSB hUSB, bool closeCtrlEp = false); bool ReadyForWorkThread(HSession hSession); - int LoopUSBRead(HSession hSession); + int LoopUSBRead(HUSB hUSB); HSession PrepareNewSession(uint32_t sessionId, uint8_t *pRecvBuf, int recvBytesIO); bool JumpAntiquePacket(const uint8_t &buf, ssize_t bytes) const; int SendUSBIOSync(HSession hSession, HUSB hMainUSB, uint8_t *data, const int length); + int CloseBulkEp(bool bulkInOut, int bulkFd, uv_loop_t *loop); - HSession usbMain; + HdcUSB usbHandle; uint32_t currentSessionId = 0; // USB mode,limit only one session std::atomic ref = 0; uv_timer_t checkEP; // server-use uv_mutex_t sendEP; bool isAlive = false; + int controlEp = 0; // EP0 }; } // namespace Hdc #endif \ No newline at end of file diff --git a/src/daemon/jdwp.cpp b/src/daemon/jdwp.cpp old mode 100755 new mode 100644 index 5725ecc57a74d593a260b40baf26bc022b42cfb5..35c8beec7f8463bc41a14b453f3a62724d26002b --- a/src/daemon/jdwp.cpp +++ b/src/daemon/jdwp.cpp @@ -38,7 +38,7 @@ void HdcJdwp::Stop() { auto funcListenPipeClose = [](uv_handle_t *handle) -> void { HdcJdwp *thisClass = (HdcJdwp *)handle->data; - thisClass->refCount--; + --thisClass->refCount; }; Base::TryCloseHandle((const uv_handle_t *)&listenPipe, funcListenPipeClose); for (auto &&obj : mapCtxJdwp) { @@ -56,7 +56,7 @@ void *HdcJdwp::MallocContext() } ctx->thisClass = this; ctx->pipe.data = ctx; - refCount++; + ++refCount; return ctx; } @@ -71,7 +71,7 @@ void HdcJdwp::FreeContext(HCtxJdwp ctx) AdminContext(OP_REMOVE, ctx->pid, nullptr); auto funcReqClose = [](uv_idle_t *handle) -> void { HCtxJdwp ctx = (HCtxJdwp)handle->data; - ctx->thisClass->refCount--; + --ctx->thisClass->refCount; Base::TryCloseHandle((uv_handle_t *)handle, Base::CloseIdleCallback); delete ctx; }; @@ -171,6 +171,7 @@ bool HdcJdwp::JdwpListen() WRITE_LOG(LOG_WARN, "could not create vm debug control socket. %d: %s", errno, strerror(errno)); return false; } + fcntl(s, F_SETFD, FD_CLOEXEC); while (true) { addrlen = (pathlen + sizeof(addr.sun_family)); if (bind(s, (struct sockaddr *)&addr, addrlen) < 0) { @@ -185,7 +186,7 @@ bool HdcJdwp::JdwpListen() if (uv_listen((uv_stream_t *)&listenPipe, DEFAULT_BACKLOG, AcceptClient)) { break; } - refCount++; + ++refCount; ret = true; break; } @@ -244,7 +245,7 @@ void HdcJdwp::SendCallbackJdwpNewFD(uv_write_t *req, int status) // close my process's fd Base::TryCloseHandle((const uv_handle_t *)&ctx->jvmTCP); delete req; - ctx->thisClass->refCount--; + --ctx->thisClass->refCount; } // Each session calls the interface through the main thread message queue, which cannot be called directly across @@ -272,7 +273,7 @@ bool HdcJdwp::SendJdwpNewFD(uint32_t targetPID, int fd) break; } // clang-format on - refCount++; + ++refCount; ret = true; WRITE_LOG(LOG_DEBUG, "SendJdwpNewFD successful targetPID:%d fd%d", targetPID, fd); break; diff --git a/src/daemon/jdwp.h b/src/daemon/jdwp.h old mode 100755 new mode 100644 diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp old mode 100755 new mode 100644 index 00535f8350067e7d95c88a75cc098a88ba3af77e..61ee8b5269da05bb1c284ac0ff79b1460df8bdc9 --- a/src/daemon/main.cpp +++ b/src/daemon/main.cpp @@ -82,7 +82,7 @@ int BackgroundRun() } else if (!pc) { int i; const int MAX_NUM = 64; - for (i = 0; i < MAX_NUM; i++) { + for (i = 0; i < MAX_NUM; ++i) { close(i); } RestartDaemon(true); diff --git a/src/daemon/shell.cpp b/src/daemon/shell.cpp old mode 100755 new mode 100644 index 789f0b81b4d0b3fc71078cac0679e0a1b0656608..6a677aa44fc1cfa2d31e1424fed647c8eec975d8 --- a/src/daemon/shell.cpp +++ b/src/daemon/shell.cpp @@ -83,6 +83,7 @@ bool HdcShell::CommandDispatch(const uint16_t command, uint8_t *payload, const i int HdcShell::ChildForkDo(const char *devname, int ptm, const char *cmd, const char *arg0, const char *arg1) { + setsid(); int pts = open(devname, O_RDWR | O_CLOEXEC); if (pts < 0) { return -1; @@ -99,7 +100,6 @@ int HdcShell::ChildForkDo(const char *devname, int ptm, const char *cmd, const c write(fd, "0", 1); close(fd); } - setsid(); char *env = nullptr; if ((env = getenv("HOME")) && chdir(env) < 0) { } diff --git a/src/daemon/shell.h b/src/daemon/shell.h old mode 100755 new mode 100644 diff --git a/src/daemon/usb_ffs.h b/src/daemon/usb_ffs.h old mode 100755 new mode 100644 diff --git a/src/host/client.cpp b/src/host/client.cpp old mode 100755 new mode 100644 index 1060de263983de72f91c6f30bebf9a0bbce074c8..5648286f0642de414d565188e13c67b15bd06f52 --- a/src/host/client.cpp +++ b/src/host/client.cpp @@ -19,18 +19,21 @@ namespace Hdc { HdcClient::HdcClient(const bool serverOrClient, const string &addrString, uv_loop_t *loopMainIn) : HdcChannelBase(serverOrClient, addrString, loopMainIn) { - MallocChannel(&channel); + MallocChannel(&channel); // free by logic debugRetryCount = 0; } HdcClient::~HdcClient() +{ + Base::TryCloseLoop(loopMain, "ExecuteCommand finish"); +} + +void HdcClient::NotifyInstanceChannelFree(HChannel hChannel) { if (bShellInteractive) { WRITE_LOG(LOG_DEBUG, "Restore tty"); - ModifyTty(false, &channel->stdinTty); + ModifyTty(false, &hChannel->stdinTty); } - FreeChannel(channel->channelId); - Base::TryCloseLoop(loopMain, "ExecuteCommand finish"); } uint32_t HdcClient::GetLastPID() @@ -138,7 +141,7 @@ string HdcClient::AutoConnectKey(string &doCommand, const string &preConnectKey) if (isNoTargetCommand) { key = ""; } else { - if (!key.size()) { + if (!preConnectKey.size()) { key = CMDSTR_CONNECT_ANY; } } @@ -167,7 +170,7 @@ int HdcClient::Initial(const string &connectKeyIn) connectKey = connectKeyIn; if (!channelHostPort.size() || !channelHost.size() || !channelPort) { WRITE_LOG(LOG_FATAL, "Listen string initial failed"); - return -2; + return ERR_PARM_FAIL; } return 0; } @@ -185,10 +188,9 @@ int HdcClient::ConnectServerForClient(const char *ip, uint16_t port) void HdcClient::CommandWorker(uv_timer_t *handle) { - const uint16_t maxWaitRetry = 300; + const uint16_t maxWaitRetry = 500; HdcClient *thisClass = (HdcClient *)handle->data; - if (thisClass->debugRetryCount++ > maxWaitRetry) { - // 8s + if (++thisClass->debugRetryCount > maxWaitRetry) { uv_timer_stop(handle); uv_stop(thisClass->loopMain); WRITE_LOG(LOG_DEBUG, "Connect server failed"); @@ -255,33 +257,25 @@ void HdcClient::BindLocalStd(HChannel hChannel) if (command == CMDSTR_SHELL) { bShellInteractive = true; } - if (UV_TTY == uv_guess_handle(STDIN_FILENO)) { - WRITE_LOG(LOG_DEBUG, "Tty std mode"); - if (uv_tty_init(loopMain, &hChannel->stdoutTty, STDOUT_FILENO, 0) - || uv_tty_init(loopMain, &hChannel->stdinTty, STDIN_FILENO, 1)) { - WRITE_LOG(LOG_DEBUG, "uv_tty_init failed"); - return; - } - hChannel->stdoutTty.data = hChannel; - hChannel->stdinTty.data = hChannel; - if (bShellInteractive) { - WRITE_LOG(LOG_DEBUG, "uv_tty_init uv_tty_set_mode"); - ModifyTty(true, &hChannel->stdinTty); - uv_read_start((uv_stream_t *)&hChannel->stdinTty, AllocStdbuf, ReadStd); - } - } else { // not use, to remove - WRITE_LOG(LOG_WARN, "Pipe std mode"); - if (uv_pipe_init(loopMain, &hChannel->stdinPipe, 0) || uv_pipe_open(&hChannel->stdinPipe, STDIN_FILENO)) { - return; - } - if (uv_pipe_init(loopMain, &hChannel->stdoutPipe, 0) || uv_pipe_open(&hChannel->stdoutPipe, STDOUT_FILENO)) { - return; - } - hChannel->stdoutPipe.data = hChannel; - hChannel->stdinPipe.data = hChannel; - if (bShellInteractive) { // Only the shell interactive mode is enabled - uv_read_start((uv_stream_t *)&hChannel->stdinPipe, AllocStdbuf, ReadStd); - } + if (uv_guess_handle(STDIN_FILENO) != UV_TTY) { + WRITE_LOG(LOG_FATAL, "Not support std mode"); + return; + } + + WRITE_LOG(LOG_DEBUG, "Tty std mode"); + if (uv_tty_init(loopMain, &hChannel->stdoutTty, STDOUT_FILENO, 0) + || uv_tty_init(loopMain, &hChannel->stdinTty, STDIN_FILENO, 1)) { + WRITE_LOG(LOG_DEBUG, "uv_tty_init failed"); + return; + } + hChannel->stdoutTty.data = hChannel; + ++hChannel->uvRef; + hChannel->stdinTty.data = hChannel; + ++hChannel->uvRef; + if (bShellInteractive) { + WRITE_LOG(LOG_DEBUG, "uv_tty_init uv_tty_set_mode"); + ModifyTty(true, &hChannel->stdinTty); + uv_read_start((uv_stream_t *)&hChannel->stdinTty, AllocStdbuf, ReadStd); } } @@ -302,29 +296,26 @@ void HdcClient::Connect(uv_connect_t *connection, int status) int HdcClient::PreHandshake(HChannel hChannel, const uint8_t *buf) { - ChannelHandShake *handShakePacket = (ChannelHandShake *)buf; - if (strncmp(handShakePacket->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) { + ChannelHandShake *hShake = (ChannelHandShake *)buf; + if (strncmp(hShake->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) { hChannel->availTailIndex = 0; WRITE_LOG(LOG_DEBUG, "Channel Hello failed"); return ERR_BUF_CHECK; } // sync remote session id to local uint32_t unOld = hChannel->channelId; - hChannel->channelId = ntohl(handShakePacket->channelId); + hChannel->channelId = ntohl(hShake->channelId); AdminChannel(OP_UPDATE, unOld, hChannel); WRITE_LOG(LOG_DEBUG, "Client channel handshake finished, use connectkey:%s", connectKey.c_str()); // send config // channel handshake step2 - Base::ZeroBuf(handShakePacket->connectKey, sizeof(handShakePacket->connectKey)); - // clang-format off - if (memcpy_s(handShakePacket->connectKey, sizeof(handShakePacket->connectKey), connectKey.c_str(), - connectKey.size())) { - // clang-format on + if (memset_s(hShake->connectKey, sizeof(hShake->connectKey), 0, sizeof(hShake->connectKey)) != EOK + || memcpy_s(hShake->connectKey, sizeof(hShake->connectKey), connectKey.c_str(), connectKey.size()) != EOK) { hChannel->availTailIndex = 0; WRITE_LOG(LOG_DEBUG, "Channel Hello failed"); return ERR_BUF_COPY; } - Send(hChannel->channelId, reinterpret_cast(handShakePacket), sizeof(ChannelHandShake)); + Send(hChannel->channelId, reinterpret_cast(hShake), sizeof(ChannelHandShake)); hChannel->handshakeOK = true; return ERR_SUCCESS; } diff --git a/src/host/client.h b/src/host/client.h old mode 100755 new mode 100644 index 4f5cd1bd3af98b27a4840811203a2bcd0eedc735..ea112ba8f7d8e83a721137f4183ad3828a2c4909 --- a/src/host/client.h +++ b/src/host/client.h @@ -41,6 +41,7 @@ private: bool StartKillServer(const char *cmd, bool startOrKill); void ModifyTty(bool setOrRestore, uv_tty_t *tty); int PreHandshake(HChannel hChannel, const uint8_t *buf); + void NotifyInstanceChannelFree(HChannel hChannel); #ifndef _WIN32 termios terminalState; diff --git a/src/host/host_app.cpp b/src/host/host_app.cpp old mode 100755 new mode 100644 index 6b7af6c9cebf7806f9374e4ca9083096bb8c4b8b..7d88c5d51f8fa2f6acb1e398f7bf45e0e0e3872f --- a/src/host/host_app.cpp +++ b/src/host/host_app.cpp @@ -36,7 +36,7 @@ bool HdcHostApp::BeginInstall(CtxFile *context, const char *command) goto Finish; } - for (int i = 0; i < argc; i++) { + for (int i = 0; i < argc; ++i) { if (!strncmp(argv[i], "-", 1)) { if (options.size()) { options += " "; @@ -82,7 +82,7 @@ bool HdcHostApp::BeginSideload(CtxFile *context, const char *localPath) void HdcHostApp::RunQueue(CtxFile *context) { - refCount++; + ++refCount; context->localPath = context->taskQueue.back(); uv_fs_open(loopTask, &context->fsOpenReq, context->localPath.c_str(), O_RDONLY, 0, OnFileOpen); context->master = true; diff --git a/src/host/host_app.h b/src/host/host_app.h old mode 100755 new mode 100644 diff --git a/src/host/host_common.h b/src/host/host_common.h old mode 100755 new mode 100644 diff --git a/src/host/host_forward.cpp b/src/host/host_forward.cpp old mode 100755 new mode 100644 diff --git a/src/host/host_forward.h b/src/host/host_forward.h old mode 100755 new mode 100644 diff --git a/src/host/host_tcp.cpp b/src/host/host_tcp.cpp old mode 100755 new mode 100644 index cef01f37487e1a031c81940f460ade0e1e218685..c699e64f46eaef07deb6459d0082d1d487ef9d91 --- a/src/host/host_tcp.cpp +++ b/src/host/host_tcp.cpp @@ -102,22 +102,17 @@ void HdcHostTCP::Connect(uv_connect_t *connection, int status) if (status < 0) { goto Finish; } + if ((hSession->fdChildWorkTCP = Base::DuplicateUvSocket(&hSession->hWorkTCP)) < 0) { + goto Finish; + } + uv_read_stop((uv_stream_t *)&hSession->hWorkTCP); Base::SetTcpOptions((uv_tcp_t *)&hSession->hWorkTCP); WRITE_LOG(LOG_DEBUG, "HdcHostTCP::Connect"); Base::StartWorkThread(&ptrConnect->loopMain, ptrConnect->SessionWorkThread, Base::FinishWorkThread, hSession); // wait for thread up while (hSession->childLoop.active_handles == 0) { - uv_sleep(1); + uv_sleep(MINOR_TIMEOUT); } - // junk data to pullup acceptchild - if (uv_fileno((const uv_handle_t *)&hSession->hWorkTCP, &hSession->fdChildWorkTCP)) { - goto Finish; - } -#ifdef UNIT_TEST - hSession->fdChildWorkTCP = dup(hSession->fdChildWorkTCP); -#endif - // The main thread is no longer read, handed over to the Child thread - uv_read_stop((uv_stream_t *)&hSession->hWorkTCP); Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); return; Finish: @@ -158,7 +153,7 @@ void HdcHostTCP::FindLanDaemon() lstDaemonResult.clear(); uv_interface_addresses(&info, &count); i = count; - while (i--) { + while (--i) { uv_interface_address_t interface = info[i]; if (interface.address.address4.sin_family == AF_INET6) { continue; diff --git a/src/host/host_tcp.h b/src/host/host_tcp.h old mode 100755 new mode 100644 diff --git a/src/host/host_unity.cpp b/src/host/host_unity.cpp old mode 100755 new mode 100644 index f25823c92f1c0f86558975ba0a53763964da53a2..ed5d0532d4c33632cde03b5355b8a3bdee3ae5cd --- a/src/host/host_unity.cpp +++ b/src/host/host_unity.cpp @@ -80,7 +80,7 @@ void HdcHostUnity::OnFileIO(uv_fs_t *req) HdcHostUnity *thisClass = (HdcHostUnity *)context->thisClass; uint8_t *bufIO = contextIO->bufIO; uv_fs_req_cleanup(req); - context->ref--; + --context->ref; if (!context->ref) { thisClass->runningProtect = false; } @@ -115,7 +115,7 @@ bool HdcHostUnity::AppendLocalLog(const char *bufLog, const int sizeLog) contextIO->bufIO = buf; contextIO->context = &opContext; req->data = contextIO; - opContext.ref++; + ++opContext.ref; runningProtect = true; if (memcpy_s(buf, sizeLog, bufLog, sizeLog)) { diff --git a/src/host/host_unity.h b/src/host/host_unity.h old mode 100755 new mode 100644 diff --git a/src/host/host_usb.cpp b/src/host/host_usb.cpp old mode 100755 new mode 100644 index 995c2d2797fc11c571c472f641c1451984debbef..bb8aa7aaa7837067a8ba47cd2bace823f5faca97 --- a/src/host/host_usb.cpp +++ b/src/host/host_usb.cpp @@ -13,7 +13,6 @@ * limitations under the License. */ #include "host_usb.h" - #include "server.h" namespace Hdc { @@ -66,10 +65,9 @@ int HdcHostUSB::Initial() void HdcHostUSB::SendUsbReset(HUSB hUSB, uint32_t sessionId) { USBHead *usbPayloadHeader = new USBHead(); - usbPayloadHeader->option |= USB_OPTION_RESET; + usbPayloadHeader->option = USB_OPTION_RESET; usbPayloadHeader->sessionId = sessionId; - if (memcpy_s(usbPayloadHeader->flag, sizeof(usbPayloadHeader->flag), - PACKET_FLAG.c_str(), PACKET_FLAG.size()) != EOK) { + if (memcpy_s(usbPayloadHeader->flag, sizeof(usbPayloadHeader->flag), PACKET_FLAG.c_str(), 2) != EOK) { delete usbPayloadHeader; return; } @@ -79,9 +77,9 @@ void HdcHostUSB::SendUsbReset(HUSB hUSB, uint32_t sessionId) WRITE_LOG(LOG_FATAL, "SendUSBRaw status:%d", transfer->status); } delete usbHead; + libusb_reset_device(transfer->dev_handle); libusb_free_transfer(transfer); // has send soft reset, next reset daemon's send - libusb_reset_device(transfer->dev_handle); WRITE_LOG(LOG_DEBUG, "Device reset singal send"); }; libusb_transfer *transferUsb = libusb_alloc_transfer(0); @@ -152,6 +150,14 @@ void HdcHostUSB::KickoutZombie(HSession hSession) ptrConnect->FreeSession(hSession->sessionId); } +void HdcHostUSB::RemoveIgnoreDevice(string &mountInfo) +{ + if (mapIgnoreDevice.count(mountInfo)) { + mapIgnoreDevice.erase(mountInfo); + WRITE_LOG(LOG_DEBUG, "Remove %s from mapIgnoreDevice", mountInfo.c_str()); + } +} + void HdcHostUSB::WatchDevPlugin(uv_timer_t *handle) { HdcHostUSB *thisClass = (HdcHostUSB *)handle->data; @@ -168,7 +174,7 @@ void HdcHostUSB::WatchDevPlugin(uv_timer_t *handle) } int i = 0; // linux replug devid increment,windows will be not - while ((dev = devs[i++]) != nullptr) { + while ((dev = devs[i++]) != nullptr) { // must postfix++ string szTmpKey = Base::StringFormat("%d-%d", libusb_get_bus_number(dev), libusb_get_device_address(dev)); // check is in ignore list UsbCheckStatus statusCheck = thisClass->mapIgnoreDevice[szTmpKey]; @@ -278,7 +284,7 @@ int HdcHostUSB::CheckActiveConfig(libusb_device *device, HUSB hUSB) if (libusb_get_active_config_descriptor(device, &descConfig)) { return -1; } - for (j = 0; j < descConfig->bNumInterfaces; j++) { + for (j = 0; j < descConfig->bNumInterfaces; ++j) { const struct libusb_interface *interface = &descConfig->interface[j]; if (interface->num_altsetting >= 1) { const struct libusb_interface_descriptor *ifDescriptor = &interface->altsetting[0]; @@ -287,7 +293,7 @@ int HdcHostUSB::CheckActiveConfig(libusb_device *device, HUSB hUSB) } hUSB->interfaceNumber = ifDescriptor->bInterfaceNumber; unsigned int k = 0; - for (k = 0; k < ifDescriptor->bNumEndpoints; k++) { + for (k = 0; k < ifDescriptor->bNumEndpoints; ++k) { const struct libusb_endpoint_descriptor *ep_desc = &ifDescriptor->endpoint[k]; if ((ep_desc->bmAttributes & 0x03) == LIBUSB_TRANSFER_TYPE_BULK) { if (ep_desc->bEndpointAddress & LIBUSB_ENDPOINT_IN) { @@ -341,21 +347,22 @@ void LIBUSB_CALL HdcHostUSB::ReadUSBBulkCallback(struct libusb_transfer *transfe server->FreeSession(hSession->sessionId); WRITE_LOG(LOG_WARN, "ReadUSBBulkCallback failed"); libusb_free_transfer(transfer); + hUSB->transferRecv = nullptr; } } void HdcHostUSB::RegisterReadCallback(HSession hSession) { HUSB hUSB = hSession->hUSB; - if (hSession->isDead || !modRunning) { + if (hSession->isDead || !modRunning || hSession->hUSB->transferRecv) { return; } - libusb_transfer *transferUsb = libusb_alloc_transfer(0); - libusb_fill_bulk_transfer(transferUsb, hUSB->devHandle, hUSB->epDevice, hUSB->bufDevice, + hSession->hUSB->transferRecv = libusb_alloc_transfer(0); + libusb_fill_bulk_transfer(hSession->hUSB->transferRecv, hUSB->devHandle, hUSB->epDevice, hUSB->bufDevice, hUSB->bufSizeDevice, // Note: in_buffer is where input data ReadUSBBulkCallback, hSession, 0); // no user data - transferUsb->user_data = hSession; - libusb_submit_transfer(transferUsb); + hSession->hUSB->transferRecv->user_data = hSession; + libusb_submit_transfer(hSession->hUSB->transferRecv); } // ==0 Represents new equipment and is what we need,<0 my need @@ -396,11 +403,14 @@ void LIBUSB_CALL HdcHostUSB::WriteUSBBulkCallback(struct libusb_transfer *transf HdcSessionBase *server = reinterpret_cast(hSession->classInstance); HdcHostUSB *thisClass = reinterpret_cast(hSession->classModule); if (usbHead->option & USB_OPTION_TAIL) { - hSession->sendRef--; + --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) { + libusb_cancel_transfer(hSession->hUSB->transferRecv); + } server->FreeSession(hSession->sessionId); } delete[] transfer->buffer; @@ -437,10 +447,13 @@ int HdcHostUSB::SendUSBRaw(HSession hSession, uint8_t *data, const int length) break; } if (ret < 0) { - hSession->sendRef--; + --hSession->sendRef; if (sendBuf != nullptr) { delete[] sendBuf; } + if (hUSB->transferRecv != nullptr) { + libusb_cancel_transfer(hUSB->transferRecv); + } libusb_free_transfer(transferUsb); } return ret; @@ -469,7 +482,7 @@ bool HdcHostUSB::FindDeviceByID(HUSB hUSB, const char *usbMountPoint, libusb_con return false; int i = 0; - for (i = 0; i < device_num; i++) { + for (i = 0; i < device_num; ++i) { struct libusb_device_descriptor desc; if (LIBUSB_SUCCESS != libusb_get_device_descriptor(listDevices[i], &desc)) { break; diff --git a/src/host/host_usb.h b/src/host/host_usb.h old mode 100755 new mode 100644 index feef4a69e40503e9122f4467d1f3b8d92f977a66..f564870b792016be0f65e6e6145b695cddf9029c --- a/src/host/host_usb.h +++ b/src/host/host_usb.h @@ -25,6 +25,7 @@ public: int SendUSBRaw(HSession hSession, uint8_t *data, const int length); HSession ConnectDetectDaemon(const HSession hSession, const HDaemonInfo pdi); void Stop(); + void RemoveIgnoreDevice(string &mountInfo); private: enum UsbCheckStatus { @@ -49,7 +50,7 @@ private: bool FindDeviceByID(HUSB hUSB, const char *usbMountPoint, libusb_context *ctxUSB); void UpdateUSBDaemonInfo(HUSB hUSB, HSession hSession, uint8_t connStatus); bool DetectMyNeed(libusb_device *device, string &sn); - void SendUsbReset(HUSB usb, uint32_t sessionId); + void SendUsbReset(HUSB hUSB, uint32_t sessionId); void RestoreHdcProtocol(HUSB hUsb, const uint8_t *buf, int bufSize); uv_idle_t usbWork; diff --git a/src/host/main.cpp b/src/host/main.cpp old mode 100755 new mode 100644 index 8f287f48c1226d227fcc40959731f9e30e1775d4..f9966b302d6658a51b2f480697e3b59811a36839 --- a/src/host/main.cpp +++ b/src/host/main.cpp @@ -83,13 +83,13 @@ int SplitOptionAndCommand(int argc, const char **argv, string &outOption, string { bool foundCommand = false; int resultChild = 0; - for (int i = 0; i < argc; i++) { + for (int i = 0; i < argc; ++i) { if (!foundCommand) { resultChild = IsRegisterCommand(outCommand, argv[i], (i == argc - 1) ? nullptr : argv[i + 1]); if (resultChild > 0) { foundCommand = true; if (resultChild == 2) { - i++; + ++i; } continue; } diff --git a/src/host/server.cpp b/src/host/server.cpp old mode 100755 new mode 100644 index 36d04d4afc30d64191e9b998cfe7c0b291611d02..a276e0157b7a817ade341f02af8bf96588658865 --- a/src/host/server.cpp +++ b/src/host/server.cpp @@ -116,7 +116,7 @@ bool HdcServer::CheckToPullUptrServer(const char *listenString) } else if (!pc) { int i; const int maxFD = 1024; - for (i = 0; i < maxFD; i++) { + for (i = 0; i < maxFD; ++i) { // close file pipe close(i); } @@ -137,7 +137,7 @@ void HdcServer::ClearMapDaemonInfo() string sKey = iter->first; HDaemonInfo hDi = iter->second; delete hDi; - iter++; + ++iter; } uv_rwlock_rdunlock(&daemonAdmin); uv_rwlock_wrlock(&daemonAdmin); @@ -198,7 +198,7 @@ string HdcServer::GetDaemonMapList(uint8_t opType) uv_rwlock_rdlock(&daemonAdmin); map::iterator iter; string echoLine; - for (iter = mapDaemon.begin(); iter != mapDaemon.end(); iter++) { + for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) { HDaemonInfo di = iter->second; if (!di) { continue; @@ -240,8 +240,7 @@ string HdcServer::AdminDaemonMap(uint8_t opType, const string &connectKey, HDaem } case OP_REMOVE: { uv_rwlock_wrlock(&daemonAdmin); - HDaemonInfo hdi = mapDaemon[connectKey]; - if (hdi) { + if (mapDaemon.count(connectKey)) { mapDaemon.erase(connectKey); } uv_rwlock_wrunlock(&daemonAdmin); @@ -250,7 +249,7 @@ string HdcServer::AdminDaemonMap(uint8_t opType, const string &connectKey, HDaem case OP_GET_ANY: { uv_rwlock_rdlock(&daemonAdmin); map::iterator iter; - for (iter = mapDaemon.begin(); iter != mapDaemon.end(); iter++) { + for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) { HDaemonInfo di = iter->second; // usb will be auto connected if (di->connStatus == STATUS_READY || di->connStatus == STATUS_CONNECTED) { @@ -263,8 +262,19 @@ string HdcServer::AdminDaemonMap(uint8_t opType, const string &connectKey, HDaem } case OP_GET_ONLY: { uv_rwlock_rdlock(&daemonAdmin); - if (mapDaemon.size() == 1) { - hDaemonInfoInOut = mapDaemon.begin()->second; + string key; + for (auto &i : mapDaemon) { + if (i.second->connStatus == STATUS_CONNECTED) { + if (key == STRING_EMPTY) { + key = i.first; + } else { + key = STRING_EMPTY; + break; + } + } + } + if (key.size() > 0) { + hDaemonInfoInOut = mapDaemon[key]; } uv_rwlock_rdunlock(&daemonAdmin); break; @@ -284,17 +294,31 @@ string HdcServer::AdminDaemonMap(uint8_t opType, const string &connectKey, HDaem return sRet; } -void HdcServer::NotifyInstanceSessionFree(HSession hSession) +void HdcServer::NotifyInstanceSessionFree(HSession hSession, bool freeOrClear) { HDaemonInfo hdiOld = nullptr; AdminDaemonMap(OP_QUERY, hSession->connectKey, hdiOld); - if (hdiOld) { - HdcDaemonInformation diNew; - diNew = *hdiOld; + if (hdiOld == nullptr) { + return; + } + if (!freeOrClear) { // step1 // update + HdcDaemonInformation diNew = *hdiOld; diNew.connStatus = STATUS_OFFLINE; HDaemonInfo hdiNew = &diNew; AdminDaemonMap(OP_UPDATE, hSession->connectKey, hdiNew); + } else { // step2 + string usbMountPoint = hdiOld->usbMountPoint; + constexpr int waitDaemonReconnect = 250; // can be call directory, not delay? + auto funcDelayUsbNotify = [this, usbMountPoint](const uint8_t flag, string &msg, const void *) -> void { + string s = usbMountPoint; + clsUSBClt->RemoveIgnoreDevice(s); + }; + if (usbMountPoint.size() > 0) { + // wait time for daemon reconnect + // If removed from maplist, the USB module will be reconnected, so it needs to wait for a while + Base::DelayDoSimple(&loopMain, waitDaemonReconnect, funcDelayUsbNotify); + } } } @@ -395,6 +419,11 @@ bool HdcServer::FetchCommand(HSession hSession, const uint32_t channelId, const return ret; } if (!hChannel) { + if (command == CMD_KERNEL_CHANNEL_CLOSE) { + // Saturated release. Daemon close channel and want to notify server close channel also, but it may has been + // closed by herself + return true; + } return false; } switch (command) { @@ -412,17 +441,18 @@ bool HdcServer::FetchCommand(HSession hSession, const uint32_t channelId, const case CMD_KERNEL_CHANNEL_CLOSE: { WRITE_LOG(LOG_DEBUG, "CMD_KERNEL_CHANNEL_CLOSE channelid:%d", channelId); ClearOwnTasks(hSession, channelId); - pSfc->FreeChannel(channelId); + auto funcChannleClose = [](uv_handle_t *handle) -> void { + HChannel hChannel = (HChannel)handle->data; + HdcServerForClient *sfc = static_cast(hChannel->clsChannel); + sfc->FreeChannel(hChannel->channelId); + }; + Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP, funcChannleClose); if (*payload) { - (*payload)--; + --(*payload); Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1); } break; } - case CMD_KERNEL_CHANNEL_DETCH: { - Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP); - break; - } case CMD_FORWARD_SUCCESS: { // add to local HdcForwardInformation di; @@ -436,7 +466,11 @@ bool HdcServer::FetchCommand(HSession hSession, const uint32_t channelId, const break; } default: { - ret = DispatchTaskData(hChannel->targetSession, hChannel->channelId, command, payload, payloadSize); + HSession hSession = AdminSession(OP_QUERY, hChannel->targetSessionId, nullptr); + if (!hSession) { + return false; + } + ret = DispatchTaskData(hSession, hChannel->channelId, command, payload, payloadSize); break; } } @@ -473,7 +507,7 @@ string HdcServer::AdminForwardMap(uint8_t opType, const string &taskString, HFor case OP_GET_STRLIST_FULL: { uv_rwlock_rdlock(&forwardAdmin); map::iterator iter; - for (iter = mapForward.begin(); iter != mapForward.end(); iter++) { + for (iter = mapForward.begin(); iter != mapForward.end(); ++iter) { HForwardInfo di = iter->second; if (!di) { continue; @@ -493,8 +527,7 @@ string HdcServer::AdminForwardMap(uint8_t opType, const string &taskString, HFor } case OP_REMOVE: { uv_rwlock_wrlock(&forwardAdmin); - HForwardInfo hdi = mapForward[taskString]; - if (hdi) { + if (mapForward.count(taskString)) { mapForward.erase(taskString); } uv_rwlock_wrunlock(&forwardAdmin); @@ -511,9 +544,10 @@ void HdcServer::UsbPreConnect(uv_timer_t *handle) HSession hSession = (HSession)handle->data; bool stopLoop = false; HdcServer *hdcServer = (HdcServer *)hSession->classInstance; - const int usbConnectRetryMax = 600; + const int usbConnectRetryMax = 100; while (true) { - if (hSession->hUSB->retryCount++ > usbConnectRetryMax) { // max 6s + WRITE_LOG(LOG_DEBUG, "HdcServer::UsbPreConnect"); + if (++hSession->hUSB->retryCount > usbConnectRetryMax) { // max 10s hdcServer->FreeSession(hSession->sessionId); stopLoop = true; break; @@ -541,8 +575,7 @@ void HdcServer::UsbPreConnect(uv_timer_t *handle) int HdcServer::CreateConnect(const string &connectKey) { uint8_t connType = 0; - if (connectKey.find(":") != std::string::npos) { - // TCP + if (connectKey.find(":") != std::string::npos) { // TCP connType = CONN_TCP; } else { // USB connType = CONN_USB; @@ -590,27 +623,20 @@ int HdcServer::CreateConnect(const string &connectKey) return ERR_SUCCESS; } -void HdcServer::RegisterChannel(HSession hSession, const uint32_t channelId) +void HdcServer::AttachChannel(HSession hSession, const uint32_t channelId) { HdcServerForClient *hSfc = static_cast(clsServerForClient); HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr); + int ret = 0; if (!hChannel) { return; } uv_tcp_init(&hSession->childLoop, &hChannel->hChildWorkTCP); hChannel->hChildWorkTCP.data = hChannel; - hChannel->targetSession = hSession; -} - -void HdcServer::AttachChannel(HSession hSession, const uint32_t channelId) -{ - HdcServerForClient *hSfc = static_cast(clsServerForClient); - HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr); - if (!hChannel) { - return; - } - if (uv_tcp_open((uv_tcp_t *)&hChannel->hChildWorkTCP, (uv_os_sock_t)hChannel->fdChildWorkTCP) < 0) { - WRITE_LOG(LOG_DEBUG, "Hdcserver AttachChannel uv_tcp_open failed"); + hChannel->targetSessionId = hSession->sessionId; + if ((ret = uv_tcp_open((uv_tcp_t *)&hChannel->hChildWorkTCP, hChannel->fdChildWorkTCP)) < 0) { + WRITE_LOG(LOG_DEBUG, "Hdcserver AttachChannel uv_tcp_open failed %s, channelid:%d fdChildWorkTCP:%d", + uv_err_name(ret), hChannel->channelId, hChannel->fdChildWorkTCP); return; } Base::SetTcpOptions((uv_tcp_t *)&hChannel->hChildWorkTCP); @@ -624,8 +650,16 @@ void HdcServer::DeatchChannel(const uint32_t channelId) if (!hChannel) { return; } - Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP); - hChannel->childCleared = true; + if (uv_is_closing((const uv_handle_t *)&hChannel->hChildWorkTCP)) { + hChannel->childCleared = true; + WRITE_LOG(LOG_DEBUG, "Childchannel free direct, cid:%d", channelId); + } else { + Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP, [](uv_handle_t *handle) -> void { + HChannel hChannel = (HChannel)handle->data; + hChannel->childCleared = true; + WRITE_LOG(LOG_DEBUG, "Childchannel free callback, cid:%d", hChannel->channelId); + }); + } }; bool HdcServer::ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, @@ -633,10 +667,11 @@ bool HdcServer::ServerCommand(const uint32_t sessionId, const uint32_t channelId { HdcServerForClient *hSfc = static_cast(clsServerForClient); HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr); - if (!hChannel) { + HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr); + if (!hChannel || !hSession) { return false; } - return FetchCommand(hChannel->targetSession, channelId, command, bufPtr, size); + return FetchCommand(hSession, channelId, command, bufPtr, size); } // clang-format off @@ -705,4 +740,5 @@ bool HdcServer::RemoveInstanceTask(const uint8_t op, HTaskInfo hTask) } return ret; } + } // namespace Hdc \ No newline at end of file diff --git a/src/host/server.h b/src/host/server.h old mode 100755 new mode 100644 index ecfff0a2ace3c08c7285b830285fbae83999fe12..7e9319acb9279a6766a481094005276ffea844d4 --- a/src/host/server.h +++ b/src/host/server.h @@ -28,12 +28,11 @@ public: int CreateConnect(const string &connectKey); bool Initial(const char *listenString); void AttachChannel(HSession hSession, const uint32_t channelId); - void RegisterChannel(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); + void NotifyInstanceSessionFree(HSession hSession, bool freeOrClear); HdcHostTCP *clsTCPClt; HdcHostUSB *clsUSBClt; diff --git a/src/host/server_for_client.cpp b/src/host/server_for_client.cpp old mode 100755 new mode 100644 index a89f45a4855ff5d2b6af9d49f0cc14cf5c628665..ba30b964aa21a608742046abe7e6a7b95b5e6f8f --- a/src/host/server_for_client.cpp +++ b/src/host/server_for_client.cpp @@ -51,8 +51,18 @@ void HdcServerForClient::AcceptClient(uv_stream_t *server, int status) thisClass->FreeChannel(uid); return; } - Base::SetTcpOptions(&hChannel->hWorkTCP); - uv_read_start((uv_stream_t *)&hChannel->hWorkTCP, AllocCallback, ReadStream); + WRITE_LOG(LOG_DEBUG, "HdcServerForClient acceptClient"); + // limit first recv + int bufMaxSize = 0; + uv_recv_buffer_size((uv_handle_t *)&hChannel->hWorkTCP, &bufMaxSize); + auto funcChannelHeaderAlloc = [](uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) -> void { + HChannel context = (HChannel)handle->data; + Base::ReallocBuf(&context->ioBuf, &context->bufSize, context->availTailIndex, sizeWanted); + buf->base = (char *)context->ioBuf + context->availTailIndex; + buf->len = sizeof(struct ChannelHandShake) + DWORD_SERIALIZE_SIZE; // only recv static size + }; + // first packet static size, after this packet will be dup for normal recv + uv_read_start((uv_stream_t *)&hChannel->hWorkTCP, funcChannelHeaderAlloc, ReadStream); // channel handshake step1 struct ChannelHandShake handShake; Base::ZeroStruct(handShake); @@ -62,7 +72,6 @@ void HdcServerForClient::AcceptClient(uv_stream_t *server, int status) } } -// https://andycong.top/2020/03/27/libuv%E5%A4%9A%E7%BA%BF%E7%A8%8B%E4%B8%AD%E4%BD%BF%E7%94%A8uv-accept/ void HdcServerForClient::SetTCPListen() { tcpListen.data = this; @@ -152,7 +161,7 @@ void HdcServerForClient::OrderFindTargets(HChannel hChannel) HdcDaemonInformation di; while (!lst.empty()) { Base::ZeroStruct(di); - count++; + ++count; di.connectKey = lst.front(); di.connType = CONN_TCP; di.connStatus = STATUS_READY; @@ -167,12 +176,6 @@ void HdcServerForClient::OrderFindTargets(HChannel hChannel) #endif } -void HdcServerForClient::FinishMainThreadTimer(uv_handle_t *handle) -{ - uv_timer_t *req = (uv_timer_t *)handle; - delete req; -} - void HdcServerForClient::OrderConnecTargetResult(uv_timer_t *req) { HChannel hChannel = (HChannel)req->data; @@ -199,7 +202,7 @@ void HdcServerForClient::OrderConnecTargetResult(uv_timer_t *req) break; } else { uint16_t *bRetryCount = (uint16_t *)hChannel->bufStd; - (*bRetryCount)++; + ++(*bRetryCount); if (*bRetryCount > 500) { // 5s bExitRepet = true; @@ -212,7 +215,7 @@ void HdcServerForClient::OrderConnecTargetResult(uv_timer_t *req) } if (bExitRepet) { thisClass->FreeChannel(hChannel->channelId); - uv_close((uv_handle_t *)req, FinishMainThreadTimer); + Base::TryCloseHandle((const uv_handle_t *)req, Base::CloseTimerCallback); } } @@ -230,10 +233,7 @@ bool HdcServerForClient::NewConnectTry(void *ptrServer, HChannel hChannel, const childRet = snprintf_s(hChannel->bufStd + 2, sizeof(hChannel->bufStd) - 2, sizeof(hChannel->bufStd) - 3, "%s", (char *)connectKey.c_str()); if (childRet > 0) { - uv_timer_t *waitTimeDoCmd = new uv_timer_t(); - uv_timer_init(loopMain, waitTimeDoCmd); - waitTimeDoCmd->data = hChannel; - uv_timer_start(waitTimeDoCmd, OrderConnecTargetResult, 10, 10); + Base::TimerUvTask(loopMain, hChannel, OrderConnecTargetResult, 10); ret = true; } } @@ -418,7 +418,11 @@ bool HdcServerForClient::TaskCommand(HChannel hChannel, void *formatCommandInput sizeCmdFlag = 9; } if (!strncmp(formatCommand->paraments.c_str(), cmdFlag.c_str(), sizeCmdFlag)) { // local do - ptrServer->DispatchTaskData(hChannel->targetSession, hChannel->channelId, formatCommand->cmdFlag, + HSession hSession = FindAliveSession(hChannel->targetSessionId); + if (!hSession) { + return false; + } + ptrServer->DispatchTaskData(hSession, hChannel->channelId, formatCommand->cmdFlag, (uint8_t *)formatCommand->paraments.c_str() + sizeCmdFlag, sizeSend - sizeCmdFlag); } else { // Send to Daemon-side to do SendToDaemon(hChannel, formatCommand->cmdFlag, (uint8_t *)formatCommand->paraments.c_str() + sizeCmdFlag, @@ -487,35 +491,56 @@ bool HdcServerForClient::DoCommand(HChannel hChannel, void *formatCommandInput) return ret; } -int HdcServerForClient::BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) +// just call from BindChannelToSession +HSession HdcServerForClient::FindAliveSessionFromDaemonMap(const HChannel hChannel) { + HSession hSession = nullptr; HDaemonInfo hdi = nullptr; HdcServer *ptrServer = (HdcServer *)clsServer; ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi); if (!hdi) { EchoClient(hChannel, MSG_FAIL, "Not match target founded, check connect-key please"); - return -1; + return nullptr; } - HSession hSession = (HSession)hdi->hSession; if (hdi->connStatus != STATUS_CONNECTED) { EchoClient(hChannel, MSG_FAIL, "Device not founded or connected"); - return -2; + return nullptr; + } + if (hdi->hSession->isDead) { + EchoClient(hChannel, MSG_FAIL, "Bind tartget session is dead"); + return nullptr; } + hSession = (HSession)hdi->hSession; + return hSession; +} - auto ctrl = HdcSessionBase::BuildCtrlString(SP_REGISTER_CHANNEL, hChannel->channelId, nullptr, 0); - Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); - while (!hChannel->hChildWorkTCP.loop) { - uv_sleep(1); +int HdcServerForClient::BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) +{ + HSession hSession = nullptr; + if ((hSession = FindAliveSessionFromDaemonMap(hChannel)) == nullptr) { + return ERR_SESSION_NOFOUND; } - if (uv_fileno((const uv_handle_t *)&hChannel->hWorkTCP, &hChannel->fdChildWorkTCP) < 0) { - return -3; + if ((hChannel->fdChildWorkTCP = Base::DuplicateUvSocket(&hChannel->hWorkTCP)) < 0) { + WRITE_LOG(LOG_FATAL, "Duplicate socket failed, cid:%d", hChannel->channelId); + return ERR_SOCKET_DUPLICATE; } -#ifdef UNIT_TEST - hChannel->fdChildWorkTCP = dup(hChannel->fdChildWorkTCP); -#endif - uv_read_stop((uv_stream_t *)&hChannel->hWorkTCP); // disable parent - auto ctrlAttach = HdcSessionBase::BuildCtrlString(SP_ATTACH_CHANNEL, hChannel->channelId, nullptr, 0); - Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrlAttach.data(), ctrlAttach.size()); + + uv_close_cb funcWorkTcpClose = [](uv_handle_t *handle) -> void { + HChannel hChannel = (HChannel)handle->data; + auto thisClass = (HdcServerForClient *)hChannel->clsChannel; + HSession hSession = nullptr; + if ((hSession = thisClass->FindAliveSessionFromDaemonMap(hChannel)) == nullptr) { + return; + } + WRITE_LOG(LOG_DEBUG, "Bind channel to session channelid:%d fdChildWorkTCP:%d", hChannel->channelId, + hChannel->fdChildWorkTCP); + auto ctrl = HdcSessionBase::BuildCtrlString(SP_ATTACH_CHANNEL, hChannel->channelId, nullptr, 0); + Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); + while (!hChannel->hChildWorkTCP.loop) { + uv_sleep(1); + } + }; + uv_close((uv_handle_t *)&hChannel->hWorkTCP, funcWorkTcpClose); return 0; } @@ -560,6 +585,7 @@ int HdcServerForClient::ChannelHandShake(HChannel hChannel, uint8_t *bufPtr, con if (!CheckAutoFillTarget(hChannel)) { return 0; } + // channel handshake stBindChannelToSession if (BindChannelToSession(hChannel, nullptr, 0)) { hChannel->availTailIndex = 0; WRITE_LOG(LOG_DEBUG, "BindChannelToSession failed"); @@ -596,8 +622,7 @@ int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const in formatCommand.cmdFlag = CMD_KERNEL_ECHO_RAW; } if (!DoCommand(hChannel, &formatCommand)) { - ret = -3; - return ret; + return -3; // error or want close } ret = bytesIO; return ret; @@ -606,9 +631,32 @@ int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const in void HdcServerForClient::NotifyInstanceChannelFree(HChannel hChannel) { HdcServer *ptrServer = (HdcServer *)clsServer; - if (hChannel->targetSession) { - uint8_t count = 1; - ptrServer->Send(hChannel->targetSession->sessionId, hChannel->channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1); + HSession hSession = FindAliveSession(hChannel->targetSessionId); + if (!hSession) { + return; } -}; + uint8_t count = 1; + ptrServer->Send(hSession->sessionId, hChannel->channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1); +} + +// avoid session dead +HSession HdcServerForClient::FindAliveSession(uint32_t sessionId) +{ + HdcServer *ptrServer = (HdcServer *)clsServer; + HSession hSession = ptrServer->AdminSession(OP_QUERY, sessionId, nullptr); + if (!hSession || hSession->isDead) { + return nullptr; + } else { + return hSession; + } +} + +bool HdcServerForClient::ChannelSendSessionCtrlMsg(vector &ctrlMsg, uint32_t sessionId) +{ + HSession hSession = FindAliveSession(sessionId); + if (!hSession) { + return false; + } + return Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrlMsg.data(), ctrlMsg.size()) > 0; +} } // namespace Hdc \ No newline at end of file diff --git a/src/host/server_for_client.h b/src/host/server_for_client.h old mode 100755 new mode 100644 index 7ae630d7b829f2e81190ba75636ae00515a47952..468f75f7fc5aab4e9649768bde5fe6e5bd7aec9e --- a/src/host/server_for_client.h +++ b/src/host/server_for_client.h @@ -37,7 +37,6 @@ private: void OrderFindTargets(HChannel hChannel); bool NewConnectTry(void *ptrServer, HChannel hChannel, const string &connectKey); static void OrderConnecTargetResult(uv_timer_t *req); - static void FinishMainThreadTimer(uv_handle_t *handle); bool SendToDaemon(HChannel hChannel, const uint16_t commandFlag, uint8_t *bufPtr, const int bufSize); int BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO); void NotifyInstanceChannelFree(HChannel hChannel); @@ -51,6 +50,9 @@ private: bool RemoveForward(HChannel hChannel, const char *paramentString); bool TaskCommand(HChannel hChannel, void *formatCommandInput); int ChannelHandShake(HChannel hChannel, uint8_t *bufPtr, const int bytesIO); + bool ChannelSendSessionCtrlMsg(vector &ctrlMsg, uint32_t sessionId); + HSession FindAliveSession(uint32_t sessionId); + HSession FindAliveSessionFromDaemonMap(const HChannel hChannel); uv_tcp_t tcpListen; void *clsServer; diff --git a/src/host/translate.cpp b/src/host/translate.cpp old mode 100755 new mode 100644 diff --git a/src/host/translate.h b/src/host/translate.h old mode 100755 new mode 100644 diff --git a/src/test/hdc_runtime_command.cpp b/src/test/hdc_runtime_command.cpp old mode 100755 new mode 100644 index 0f1e7b2453613cbd28ad78275b9c22e7a2d869e6..98f4fa782c0e3301bfb514d1a40a24ecffc3b0dd --- a/src/test/hdc_runtime_command.cpp +++ b/src/test/hdc_runtime_command.cpp @@ -112,7 +112,12 @@ int TestTaskCommand(int method, const string &debugServerPort, const string &deb "install /d/a.hap /mnt/hgfs/vtmp/b.hap /mnt/hgfs/vtmp -lrtsdpg"); // hap break; case UT_TEST_TMP: - TestRunClient(debugServerPort, debugConnectKey, "file send /mnt/hgfs/vtmp/f.txt /data/local/tmp/f2.txt"); + while (true) { + uv_sleep(50); + TestRunClient(debugServerPort, debugConnectKey, "list targets"); + TestRunClient(debugServerPort, debugConnectKey, "shell id"); + TestRunClient(debugServerPort, debugConnectKey, "shell bm dump -a"); + } #ifdef DEF_NULL TestRunClient(debugServerPort, debugConnectKey, "install /d/helloworld.hap"); TestRunClient(debugServerPort, debugConnectKey, "target mount"); @@ -122,6 +127,10 @@ int TestTaskCommand(int method, const string &debugServerPort, const string &deb TestRunClient(debugServerPort, debugConnectKey, "install /d -rt"); TestRunClient(debugServerPort, debugConnectKey, "fport tcp:8081 tcp:8082"); TestRunClient(debugServerPort, debugConnectKey, "fport tcp:8081 dev:/dev/urandom"); + TestRunClient(debugServerPort, debugConnectKey, "shell hilog"); + TestRunClient(debugServerPort, debugConnectKey, "file send /mnt/hgfs/vtmp/f.txt /tmp/f2.txt"); + TestRunClient(debugServerPort, debugConnectKey, "file recv /tmp/f2.txt /mnt/hgfs/vtmp/f2.txt"); + TestRunClient(debugServerPort, debugConnectKey, "shell find /proc"); #endif break; default: diff --git a/src/test/hdc_runtime_command.h b/src/test/hdc_runtime_command.h old mode 100755 new mode 100644 index 0c00e2f56ca384b273e0dcb702a1d64a7fd9370a..ece9a36db0a42dbcf598701280ee9418b92e00df --- a/src/test/hdc_runtime_command.h +++ b/src/test/hdc_runtime_command.h @@ -40,7 +40,7 @@ enum UTType { }; const string DEBUG_ADDRESS = Hdc::DEFAULT_SERVER_ADDR; -const string DEBUG_TCP_CONNECT_KEY = "192.168.0.205:10178"; +const string DEBUG_TCP_CONNECT_KEY = "127.0.0.1:10178"; const string DEBUG_USB_CONNECT_KEY = "any"; int TestRuntimeCommand(const int method, const string &debugServerPort, const string &debugConnectKey); diff --git a/src/test/hdc_runtime_frame.cpp b/src/test/hdc_runtime_frame.cpp old mode 100755 new mode 100644 index 596c19b042f491c0bcb4df1cfa8ff8b6936b5ee1..44220c8db6dec72712f08c87766d611597c4096e --- a/src/test/hdc_runtime_frame.cpp +++ b/src/test/hdc_runtime_frame.cpp @@ -52,7 +52,7 @@ bool FrameRuntime::Initial(bool bConnectToDaemon) constexpr int loopTime = 20; constexpr int sleepTime = 300; bool bRunCheckOK = false; - for (size_t i = 0; i < loopTime; i++) { + for (size_t i = 0; i < loopTime; ++i) { if (serverRunning && daemonRunning) { bRunCheckOK = true; break; diff --git a/src/test/hdc_runtime_frame.h b/src/test/hdc_runtime_frame.h old mode 100755 new mode 100644 diff --git a/src/test/main.cpp b/src/test/main.cpp old mode 100755 new mode 100644 diff --git a/src/test/ut_common.h b/src/test/ut_common.h old mode 100755 new mode 100644