mirror of
https://gitee.com/openharmony/developtools_hdc
synced 2024-11-27 01:00:45 +00:00
202106 fixes
This commit is contained in:
parent
ddf6449c84
commit
c21fd0d0c8
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -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
|
||||
|
1
BUILD.gn
Executable file → Normal file
1
BUILD.gn
Executable file → Normal file
@ -50,7 +50,6 @@ ohos_executable("hdcd") {
|
||||
sources += hdc_common_sources
|
||||
|
||||
defines = [
|
||||
"HDC_DEBUG",
|
||||
"HARMONY_PROJECT",
|
||||
]
|
||||
|
||||
|
2
README_zh.md
Executable file → Normal file
2
README_zh.md
Executable file → Normal file
@ -197,5 +197,5 @@ hdc当前支持如下命令:
|
||||
|
||||
研发工具链子系统
|
||||
|
||||
**developtools\_hdc\_standard**
|
||||
|
||||
**developtools\_hdc\_standard**
|
0
ohos.build
Executable file → Normal file
0
ohos.build
Executable file → Normal file
BIN
prebuilt/hdc.x86_64.bin
(Stored with Git LFS)
Normal file
BIN
prebuilt/hdc.x86_64.bin
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
prebuilt/hdc.x86_64.exe
(Stored with Git LFS)
Normal file
BIN
prebuilt/hdc.x86_64.exe
(Stored with Git LFS)
Normal file
Binary file not shown.
Binary file not shown.
BIN
prebuilt/windows/hdc_std.exe
(Stored with Git LFS)
BIN
prebuilt/windows/hdc_std.exe
(Stored with Git LFS)
Binary file not shown.
1
src/common/async_cmd.cpp
Executable file → Normal file
1
src/common/async_cmd.cpp
Executable file → Normal file
@ -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)
|
||||
|
0
src/common/async_cmd.h
Executable file → Normal file
0
src/common/async_cmd.h
Executable file → Normal file
6
src/common/auth.cpp
Executable file → Normal file
6
src/common/auth.cpp
Executable file → Normal file
@ -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<void *> *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<void *> *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;
|
||||
|
0
src/common/auth.h
Executable file → Normal file
0
src/common/auth.h
Executable file → Normal file
272
src/common/base.cpp
Executable file → Normal file
272
src/common/base.cpp
Executable file → Normal file
@ -13,12 +13,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "base.h"
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <random>
|
||||
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<seconds>(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<microseconds>(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<int>(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<void(const uint8_t, string &, const void *)> cb)
|
||||
{
|
||||
struct DelayDoParam {
|
||||
uv_timer_t handle;
|
||||
uint8_t flag;
|
||||
string msg;
|
||||
void *data;
|
||||
std::function<void(const uint8_t, string &, const void *)> 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
|
||||
|
18
src/common/base.h
Executable file → Normal file
18
src/common/base.h
Executable file → Normal file
@ -89,11 +89,7 @@ namespace Base {
|
||||
// just zero memory buf, such as pointer
|
||||
template<class T> 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<void(const uint8_t, string &, const void *)> cb);
|
||||
inline bool DelayDoSimple(uv_loop_t *loop, const int delayMs,
|
||||
std::function<void(const uint8_t, string &, const void *)> 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
|
||||
|
||||
|
155
src/common/channel.cpp
Executable file → Normal file
155
src/common/channel.cpp
Executable file → Normal file
@ -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<uint8_t> HdcChannelBase::GetChannelHandshake(string &connectKey) const
|
||||
@ -84,24 +82,12 @@ bool HdcChannelBase::SetChannelTCPString(const string &addrString)
|
||||
|
||||
void HdcChannelBase::ClearChannels()
|
||||
{
|
||||
map<uint32_t, HChannel>::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;
|
||||
}
|
||||
|
||||
// work when libuv-handle at struct of HdcSession has all callback finished
|
||||
void HdcChannelBase::FreeChannelFinally(uv_idle_t *handle)
|
||||
{
|
||||
HChannel hChannel = (HChannel)handle->data;
|
||||
HdcChannelBase *thisClass = (HdcChannelBase *)hChannel->clsChannel;
|
||||
if (hChannel->uvRef > 0) {
|
||||
return;
|
||||
}
|
||||
thisClass->NotifyInstanceChannelFree(hChannel);
|
||||
thisClass->AdminChannel(OP_REMOVE, hChannel->channelId, nullptr);
|
||||
WRITE_LOG(LOG_DEBUG, "!!!FreeChannelFinally channelId:%d finish", hChannel->channelId);
|
||||
if (!hChannel->serverOrClient) {
|
||||
uv_stop(thisClass->loopMain);
|
||||
}
|
||||
delete hChannel;
|
||||
Base::TryCloseHandle((const uv_handle_t *)handle, Base::CloseIdleCallback);
|
||||
}
|
||||
|
||||
void HdcChannelBase::FreeChannelContinue(HChannel hChannel)
|
||||
{
|
||||
// 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<uv_stream_t*>(&hChannel->targetSession->ctrlPipe[STREAM_MAIN]),
|
||||
ctrl.data(), ctrl.size());
|
||||
while (!hChannel->childCleared) {
|
||||
usleep(1000);
|
||||
}
|
||||
}
|
||||
uv_mutex_destroy(&hChannel->sendMutex);
|
||||
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);
|
||||
Base::TryCloseHandle((uv_handle_t *)&hChannel->stdinTty, closeChannelHandle);
|
||||
Base::TryCloseHandle((uv_handle_t *)&hChannel->stdoutTty, closeChannelHandle);
|
||||
}
|
||||
hChannel->mainCleared = true;
|
||||
uv_mutex_unlock(&freeChannel);
|
||||
WRITE_LOG(LOG_DEBUG, "Freechannel finish id:%d sendref:%d", hChannel->channelId, uint32_t(hChannel->sendRef));
|
||||
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)
|
||||
|
7
src/common/channel.h
Executable file → Normal file
7
src/common/channel.h
Executable file → Normal file
@ -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<uint8_t> &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<void *> 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);
|
||||
|
0
src/common/common.h
Executable file → Normal file
0
src/common/common.h
Executable file → Normal file
6
src/common/debug.cpp
Executable file → Normal file
6
src/common/debug.cpp
Executable file → Normal file
@ -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);
|
||||
}
|
||||
|
0
src/common/debug.h
Executable file → Normal file
0
src/common/debug.h
Executable file → Normal file
30
src/common/define.h
Executable file → Normal file
30
src/common/define.h
Executable file → Normal file
@ -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<uint8_t> bufRecv;
|
||||
@ -290,11 +295,9 @@ struct HdcSession {
|
||||
string connectKey;
|
||||
uint8_t connType; // ConnType
|
||||
uint32_t sessionId;
|
||||
uv_mutex_t sendMutex;
|
||||
std::atomic<uint16_t> sendRef;
|
||||
uint8_t uvRef; // libuv handle ref -- just main thread now
|
||||
bool childCleared;
|
||||
bool mainCleared;
|
||||
map<uint32_t, HTaskInfo> *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<uint16_t> 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];
|
||||
|
0
src/common/define_plus.h
Executable file → Normal file
0
src/common/define_plus.h
Executable file → Normal file
43
src/common/file.cpp
Executable file → Normal file
43
src/common/file.cpp
Executable file → Normal file
@ -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];
|
||||
for (int i = 0; i < argc - CMD_ARG1_COUNT; i++) {
|
||||
if (argv[i] == CMD_OPTION_ZIP) {
|
||||
context->transferConfig.compressType = COMPRESS_LZ4;
|
||||
srcOffset += strlen(argv[i]) + 1;
|
||||
} else if (argv[i] == CMD_OPTION_SYNC) {
|
||||
context->transferConfig.updateIfNew = true;
|
||||
srcOffset += strlen(argv[i]) + 1;
|
||||
} else if (argv[i] == CMD_OPTION_TSTMP) {
|
||||
context->transferConfig.holdTimestamp = true;
|
||||
srcOffset += strlen(argv[i]) + 1;
|
||||
}
|
||||
}
|
||||
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);
|
||||
for (int i = 0; i < argc - 2; i++) {
|
||||
if (!strcmp(argv[i], "-z")) {
|
||||
context->transferConfig.compressType = COMPRESS_LZ4;
|
||||
}
|
||||
if (!strcmp(argv[i], "-sync")) {
|
||||
context->transferConfig.updateIfNew = true;
|
||||
}
|
||||
if (!strcmp(argv[i], "-a")) {
|
||||
context->transferConfig.holdTimestamp = true;
|
||||
}
|
||||
}
|
||||
refCount++;
|
||||
++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);
|
||||
|
0
src/common/file.h
Executable file → Normal file
0
src/common/file.h
Executable file → Normal file
8
src/common/file_descriptor.cpp
Executable file → Normal file
8
src/common/file_descriptor.cpp
Executable file → Normal file
@ -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);
|
||||
|
0
src/common/file_descriptor.h
Executable file → Normal file
0
src/common/file_descriptor.h
Executable file → Normal file
4
src/common/forward.cpp
Executable file → Normal file
4
src/common/forward.cpp
Executable file → Normal file
@ -38,7 +38,7 @@ bool HdcForwardBase::ReadyForRelease()
|
||||
void HdcForwardBase::StopTask()
|
||||
{
|
||||
map<uint32_t, HCtxForward>::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)
|
||||
|
0
src/common/forward.h
Executable file → Normal file
0
src/common/forward.h
Executable file → Normal file
42
src/common/serial_struct.h
Executable file → Normal file
42
src/common/serial_struct.h
Executable file → Normal file
@ -1213,7 +1213,6 @@ namespace SerialStruct {
|
||||
const std::string &_in;
|
||||
size_t _pos;
|
||||
};
|
||||
|
||||
// mytype
|
||||
template<> struct Serializer<uint8_t> {
|
||||
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<uint16_t> {
|
||||
static void Serialize(uint32_t tag, uint16_t value, FlagsType<>, Writer &out, bool force = false)
|
||||
{
|
||||
Serializer<uint32_t>::Serialize(tag, value, FlagsType(), out, force);
|
||||
}
|
||||
|
||||
static void SerializePacked(uint16_t value, FlagsType<>, Writer &out)
|
||||
{
|
||||
Serializer<uint32_t>::SerializePacked(value, FlagsType(), out);
|
||||
}
|
||||
|
||||
static bool Parse(WireType wire_type, uint16_t &value, FlagsType<>, reader &in)
|
||||
{
|
||||
uint32_t intermedaite_value;
|
||||
if (Serializer<uint32_t>::Parse(wire_type, intermedaite_value, FlagsType<>(), in)) {
|
||||
value = static_cast<uint16_t>(intermedaite_value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ParsePacked(uint16_t &value, FlagsType<>, reader &in)
|
||||
{
|
||||
uint32_t intermedaite_value;
|
||||
if (Serializer<uint32_t>::ParsePacked(intermedaite_value, FlagsType<>(), in)) {
|
||||
value = static_cast<uint16_t>(intermedaite_value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
// mytype finish
|
||||
template<class T> std::string SerializeToString(const T &value)
|
||||
@ -1302,6 +1332,16 @@ namespace SerialStruct {
|
||||
Field<5, &Hdc::HdcSessionBase::SessionHandShake::buf>("buf"));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct Descriptor<Hdc::HdcSessionBase::PayloadProtect> {
|
||||
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
|
||||
|
228
src/common/session.cpp
Executable file → Normal file
228
src/common/session.cpp
Executable file → Normal file
@ -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<uint32_t, HSession>::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<uint32_t, HSession>::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<uint32_t>(Base::GetRuntimeMSec()) : sessionId);
|
||||
hSession->serverOrDaemon = serverOrDaemon;
|
||||
uv_mutex_init(&hSession->sendMutex);
|
||||
hSession->hWorkThread = uv_thread_self();
|
||||
hSession->mapTask = new map<uint32_t, HTaskInfo>();
|
||||
hSession->listKey = new list<void *>;
|
||||
@ -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) {
|
||||
HSession hSession = (HSession)handle->data;
|
||||
HdcSessionBase *thisClass = (HdcSessionBase *)hSession->classInstance;
|
||||
if (hSession->sendRef > 0) {
|
||||
return;
|
||||
}
|
||||
// Unified Send to the main thread
|
||||
if (hSession->hWorkThread != uv_thread_self()) {
|
||||
PushAsyncMessage(hSession->sessionId, ASYNC_FREE_SESSION, nullptr, 0);
|
||||
#ifdef HDC_HOST
|
||||
if (hSession->hUSB != nullptr && hSession->hUSB->transferRecv != nullptr) {
|
||||
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) {
|
||||
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<PayloadHead *>(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<uint8_t *>(&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
|
||||
}
|
||||
// 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 (memcpy_s(finayBuf + sizeof(PayloadHead), s.size(),
|
||||
reinterpret_cast<uint8_t *>(const_cast<char *>(s.c_str())), s.size())) {
|
||||
break;
|
||||
}
|
||||
payloadHead->protocolVer = VER_PROTOCOL;
|
||||
payloadHead->dataSize = htonl(rc4BufLen);
|
||||
ret = SendByProtocol(hSession, sendBuf, sizeSendBuf);
|
||||
break;
|
||||
if (dataSize > 0 && memcpy_s(finayBuf + sizeof(PayloadHead) + s.size(), dataSize, data, dataSize)) {
|
||||
break;
|
||||
}
|
||||
bufRet = true;
|
||||
} while (false);
|
||||
if (!bufRet) {
|
||||
delete[] finayBuf;
|
||||
return ERR_BUF_COPY;
|
||||
}
|
||||
// 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<char *>(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<uint8_t> HdcSessionBase::BuildCtrlString(InnerCtrlCommand command, uint32_t channelId,
|
||||
const uint8_t *data, int dataSize)
|
||||
vector<uint8_t> HdcSessionBase::BuildCtrlString(InnerCtrlCommand command, uint32_t channelId, uint8_t *data,
|
||||
int dataSize)
|
||||
{
|
||||
vector<uint8_t> 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
|
||||
|
25
src/common/session.h
Executable file → Normal file
25
src/common/session.h
Executable file → Normal file
@ -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<uint8_t> BuildCtrlString(InnerCtrlCommand command, uint32_t channelId,
|
||||
const uint8_t *data, int dataSize);
|
||||
static vector<uint8_t> 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<uint32_t, HSession> mapSession;
|
||||
uv_rwlock_t lockMapSession;
|
||||
std::atomic<uint32_t> sessionRef = 0;
|
||||
const uint8_t payloadProtectStaticVcode = 0x09;
|
||||
};
|
||||
} // namespace Hdc
|
||||
#endif
|
0
src/common/task.cpp
Executable file → Normal file
0
src/common/task.cpp
Executable file → Normal file
0
src/common/task.h
Executable file → Normal file
0
src/common/task.h
Executable file → Normal file
0
src/common/tcp.cpp
Executable file → Normal file
0
src/common/tcp.cpp
Executable file → Normal file
0
src/common/tcp.h
Executable file → Normal file
0
src/common/tcp.h
Executable file → Normal file
17
src/common/transfer.cpp
Executable file → Normal file
17
src/common/transfer.cpp
Executable file → Normal file
@ -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<char *>(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>
|
||||
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;
|
||||
}
|
||||
|
0
src/common/transfer.h
Executable file → Normal file
0
src/common/transfer.h
Executable file → Normal file
2
src/common/usb.cpp
Executable file → Normal file
2
src/common/usb.cpp
Executable file → Normal file
@ -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) {
|
||||
|
0
src/common/usb.h
Executable file → Normal file
0
src/common/usb.h
Executable file → Normal file
2
src/daemon/daemon.cpp
Executable file → Normal file
2
src/daemon/daemon.cpp
Executable file → Normal file
@ -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;
|
||||
|
0
src/daemon/daemon.h
Executable file → Normal file
0
src/daemon/daemon.h
Executable file → Normal file
6
src/daemon/daemon_app.cpp
Executable file → Normal file
6
src/daemon/daemon_app.cpp
Executable file → Normal file
@ -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;
|
||||
|
0
src/daemon/daemon_app.h
Executable file → Normal file
0
src/daemon/daemon_app.h
Executable file → Normal file
0
src/daemon/daemon_common.h
Executable file → Normal file
0
src/daemon/daemon_common.h
Executable file → Normal file
6
src/daemon/daemon_forward.cpp
Executable file → Normal file
6
src/daemon/daemon_forward.cpp
Executable file → Normal file
@ -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;
|
||||
}
|
||||
|
0
src/daemon/daemon_forward.h
Executable file → Normal file
0
src/daemon/daemon_forward.h
Executable file → Normal file
14
src/daemon/daemon_tcp.cpp
Executable file → Normal file
14
src/daemon/daemon_tcp.cpp
Executable file → Normal file
@ -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<HdcSessionBase *>(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);
|
||||
usleep(maxWaitTime);
|
||||
}
|
||||
if (uv_fileno((const uv_handle_t *)&hSession->hWorkTCP, &hSession->fdChildWorkTCP) < 0) {
|
||||
goto Finish;
|
||||
}
|
||||
#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:
|
||||
|
0
src/daemon/daemon_tcp.h
Executable file → Normal file
0
src/daemon/daemon_tcp.h
Executable file → Normal file
4
src/daemon/daemon_unity.cpp
Executable file → Normal file
4
src/daemon/daemon_unity.cpp
Executable file → Normal file
@ -59,7 +59,7 @@ void HdcDaemonUnity::OnFdRead(uv_fs_t *req)
|
||||
CtxUnityIO *ctxIO = static_cast<CtxUnityIO *>(req->data);
|
||||
ContextUnity *ctx = static_cast<ContextUnity *>(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);
|
||||
|
0
src/daemon/daemon_unity.h
Executable file → Normal file
0
src/daemon/daemon_unity.h
Executable file → Normal file
164
src/daemon/daemon_usb.cpp
Executable file → Normal file
164
src/daemon/daemon_usb.cpp
Executable file → Normal file
@ -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<HdcDaemon *>(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<HdcDaemon *>(hSession->classInstance);
|
||||
HdcDaemon *daemon = reinterpret_cast<HdcDaemon *>(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<uv_stream_t *>(&hChildSession->dataPipe[STREAM_MAIN]),
|
||||
readBuf, readBytes)) {
|
||||
if (!SendToHdcStream(hChildSession, reinterpret_cast<uv_stream_t *>(&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<CtxUvFileCommonIo *>(req->data);
|
||||
auto hSession = reinterpret_cast<HSession>(ctxIo->data);
|
||||
auto hUSB = reinterpret_cast<HUSB>(ctxIo->data);
|
||||
auto thisClass = reinterpret_cast<HdcDaemonUSB *>(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<HdcDaemon *>(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<HdcDaemon *>(thisClass->clsMainBase);
|
||||
if (thisClass->isAlive || thisClass->ref > 0) {
|
||||
return;
|
||||
}
|
||||
if (thisClass->ConnectEPPoint(hUSB)) {
|
||||
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) != ERR_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
// connect OK
|
||||
thisClass->isAlive = true;
|
||||
thisClass->LoopUSBRead(thisClass->usbMain);
|
||||
thisClass->LoopUSBRead(hUSB);
|
||||
}
|
||||
} // namespace Hdc
|
10
src/daemon/daemon_usb.h
Executable file → Normal file
10
src/daemon/daemon_usb.h
Executable file → Normal file
@ -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<uint32_t> ref = 0;
|
||||
uv_timer_t checkEP; // server-use
|
||||
uv_mutex_t sendEP;
|
||||
bool isAlive = false;
|
||||
int controlEp = 0; // EP0
|
||||
};
|
||||
} // namespace Hdc
|
||||
#endif
|
13
src/daemon/jdwp.cpp
Executable file → Normal file
13
src/daemon/jdwp.cpp
Executable file → Normal file
@ -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;
|
||||
|
0
src/daemon/jdwp.h
Executable file → Normal file
0
src/daemon/jdwp.h
Executable file → Normal file
2
src/daemon/main.cpp
Executable file → Normal file
2
src/daemon/main.cpp
Executable file → Normal file
@ -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);
|
||||
|
2
src/daemon/shell.cpp
Executable file → Normal file
2
src/daemon/shell.cpp
Executable file → Normal file
@ -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) {
|
||||
}
|
||||
|
0
src/daemon/shell.h
Executable file → Normal file
0
src/daemon/shell.h
Executable file → Normal file
0
src/daemon/usb_ffs.h
Executable file → Normal file
0
src/daemon/usb_ffs.h
Executable file → Normal file
81
src/host/client.cpp
Executable file → Normal file
81
src/host/client.cpp
Executable file → Normal file
@ -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<uint8_t *>(handShakePacket), sizeof(ChannelHandShake));
|
||||
Send(hChannel->channelId, reinterpret_cast<uint8_t *>(hShake), sizeof(ChannelHandShake));
|
||||
hChannel->handshakeOK = true;
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
1
src/host/client.h
Executable file → Normal file
1
src/host/client.h
Executable file → Normal file
@ -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;
|
||||
|
4
src/host/host_app.cpp
Executable file → Normal file
4
src/host/host_app.cpp
Executable file → Normal file
@ -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;
|
||||
|
0
src/host/host_app.h
Executable file → Normal file
0
src/host/host_app.h
Executable file → Normal file
0
src/host/host_common.h
Executable file → Normal file
0
src/host/host_common.h
Executable file → Normal file
0
src/host/host_forward.cpp
Executable file → Normal file
0
src/host/host_forward.cpp
Executable file → Normal file
0
src/host/host_forward.h
Executable file → Normal file
0
src/host/host_forward.h
Executable file → Normal file
17
src/host/host_tcp.cpp
Executable file → Normal file
17
src/host/host_tcp.cpp
Executable file → Normal file
@ -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;
|
||||
|
0
src/host/host_tcp.h
Executable file → Normal file
0
src/host/host_tcp.h
Executable file → Normal file
4
src/host/host_unity.cpp
Executable file → Normal file
4
src/host/host_unity.cpp
Executable file → Normal file
@ -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)) {
|
||||
|
0
src/host/host_unity.h
Executable file → Normal file
0
src/host/host_unity.h
Executable file → Normal file
45
src/host/host_usb.cpp
Executable file → Normal file
45
src/host/host_usb.cpp
Executable file → Normal file
@ -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<HdcSessionBase *>(hSession->classInstance);
|
||||
HdcHostUSB *thisClass = reinterpret_cast<HdcHostUSB *>(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;
|
||||
|
3
src/host/host_usb.h
Executable file → Normal file
3
src/host/host_usb.h
Executable file → Normal file
@ -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;
|
||||
|
4
src/host/main.cpp
Executable file → Normal file
4
src/host/main.cpp
Executable file → Normal file
@ -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;
|
||||
}
|
||||
|
122
src/host/server.cpp
Executable file → Normal file
122
src/host/server.cpp
Executable file → Normal file
@ -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<string, HDaemonInfo>::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<string, HDaemonInfo>::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<HdcServerForClient *>(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<string, HForwardInfo>::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<HdcServerForClient *>(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<HdcServerForClient *>(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<HdcServerForClient *>(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
|
3
src/host/server.h
Executable file → Normal file
3
src/host/server.h
Executable file → Normal file
@ -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;
|
||||
|
130
src/host/server_for_client.cpp
Executable file → Normal file
130
src/host/server_for_client.cpp
Executable file → Normal file
@ -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;
|
||||
}
|
||||
|
||||
int HdcServerForClient::BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO)
|
||||
{
|
||||
HSession hSession = nullptr;
|
||||
if ((hSession = FindAliveSessionFromDaemonMap(hChannel)) == nullptr) {
|
||||
return ERR_SESSION_NOFOUND;
|
||||
}
|
||||
if ((hChannel->fdChildWorkTCP = Base::DuplicateUvSocket(&hChannel->hWorkTCP)) < 0) {
|
||||
WRITE_LOG(LOG_FATAL, "Duplicate socket failed, cid:%d", hChannel->channelId);
|
||||
return ERR_SOCKET_DUPLICATE;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
if (uv_fileno((const uv_handle_t *)&hChannel->hWorkTCP, &hChannel->fdChildWorkTCP) < 0) {
|
||||
return -3;
|
||||
}
|
||||
#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<uint8_t> &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
|
4
src/host/server_for_client.h
Executable file → Normal file
4
src/host/server_for_client.h
Executable file → Normal file
@ -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<uint8_t> &ctrlMsg, uint32_t sessionId);
|
||||
HSession FindAliveSession(uint32_t sessionId);
|
||||
HSession FindAliveSessionFromDaemonMap(const HChannel hChannel);
|
||||
|
||||
uv_tcp_t tcpListen;
|
||||
void *clsServer;
|
||||
|
0
src/host/translate.cpp
Executable file → Normal file
0
src/host/translate.cpp
Executable file → Normal file
0
src/host/translate.h
Executable file → Normal file
0
src/host/translate.h
Executable file → Normal file
11
src/test/hdc_runtime_command.cpp
Executable file → Normal file
11
src/test/hdc_runtime_command.cpp
Executable file → Normal file
@ -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:
|
||||
|
2
src/test/hdc_runtime_command.h
Executable file → Normal file
2
src/test/hdc_runtime_command.h
Executable file → Normal file
@ -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);
|
||||
|
2
src/test/hdc_runtime_frame.cpp
Executable file → Normal file
2
src/test/hdc_runtime_frame.cpp
Executable file → Normal file
@ -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;
|
||||
|
0
src/test/hdc_runtime_frame.h
Executable file → Normal file
0
src/test/hdc_runtime_frame.h
Executable file → Normal file
0
src/test/main.cpp
Executable file → Normal file
0
src/test/main.cpp
Executable file → Normal file
0
src/test/ut_common.h
Executable file → Normal file
0
src/test/ut_common.h
Executable file → Normal file
Loading…
Reference in New Issue
Block a user