202106 fixes

This commit is contained in:
zako 2021-06-30 22:07:29 +08:00
parent ddf6449c84
commit c21fd0d0c8
83 changed files with 931 additions and 605 deletions

4
.gitattributes vendored
View File

@ -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
View 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
View File

@ -197,5 +197,5 @@ hdc当前支持如下命令
研发工具链子系统
**developtools\_hdc\_standard**
**developtools\_hdc\_standard**

0
ohos.build Executable file → Normal file
View 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

Binary file not shown.

Binary file not shown.

BIN
prebuilt/windows/hdc_std.exe (Stored with Git LFS)

Binary file not shown.

1
src/common/async_cmd.cpp Executable file → Normal file
View 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
View File

6
src/common/auth.cpp Executable file → Normal file
View 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
View File

272
src/common/base.cpp Executable file → Normal file
View 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, &times);
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
View 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
View 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
View 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
View File

6
src/common/debug.cpp Executable file → Normal file
View 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
View File

30
src/common/define.h Executable file → Normal file
View 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 channelseparate 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
View File

43
src/common/file.cpp Executable file → Normal file
View 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
View File

8
src/common/file_descriptor.cpp Executable file → Normal file
View 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
View File

4
src/common/forward.cpp Executable file → Normal file
View 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
View File

42
src/common/serial_struct.h Executable file → Normal file
View 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
View 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
View 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
View File

0
src/common/task.h Executable file → Normal file
View File

0
src/common/tcp.cpp Executable file → Normal file
View File

0
src/common/tcp.h Executable file → Normal file
View File

17
src/common/transfer.cpp Executable file → Normal file
View 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
View File

2
src/common/usb.cpp Executable file → Normal file
View 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
View File

2
src/daemon/daemon.cpp Executable file → Normal file
View 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
View File

6
src/daemon/daemon_app.cpp Executable file → Normal file
View 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
View File

0
src/daemon/daemon_common.h Executable file → Normal file
View File

6
src/daemon/daemon_forward.cpp Executable file → Normal file
View 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
View File

14
src/daemon/daemon_tcp.cpp Executable file → Normal file
View 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
View File

4
src/daemon/daemon_unity.cpp Executable file → Normal file
View 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
View File

164
src/daemon/daemon_usb.cpp Executable file → Normal file
View 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
View 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
View 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
View File

2
src/daemon/main.cpp Executable file → Normal file
View 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
View 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
View File

0
src/daemon/usb_ffs.h Executable file → Normal file
View File

81
src/host/client.cpp Executable file → Normal file
View 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
View 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
View 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
View File

0
src/host/host_common.h Executable file → Normal file
View File

0
src/host/host_forward.cpp Executable file → Normal file
View File

0
src/host/host_forward.h Executable file → Normal file
View File

17
src/host/host_tcp.cpp Executable file → Normal file
View 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
View File

4
src/host/host_unity.cpp Executable file → Normal file
View 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
View File

45
src/host/host_usb.cpp Executable file → Normal file
View 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 incrementwindows 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

0
src/host/translate.h Executable file → Normal file
View File

11
src/test/hdc_runtime_command.cpp Executable file → Normal file
View 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
View 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
View 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
View File

0
src/test/main.cpp Executable file → Normal file
View File

0
src/test/ut_common.h Executable file → Normal file
View File